Compare commits

..

131 Commits

Author SHA1 Message Date
Justin Clark-Casey (justincc) 8b267b5bb5 Fix bug in HG attachment throttling code where attachments were never rezzed on any teleport within a foreign grid after the first.
Bug was introduced in ghosts branch commit 69abade
2014-11-21 21:34:18 +00:00
Justin Clark-Casey (justincc) c18cecbeb7 Change jobengine logging command to "debug jobengine log <int>" rather than loglevel, in common with similar commands. 2014-11-21 21:25:55 +00:00
Justin Clark-Casey (justincc) 11ed60645a When logging reigon information returned by GateKeeperService.GetHyperlinkRegion, log the return server URL returned.
This helps diagnoses misconfiguration where, for instance, a LAN ExternalHostName has been configured that isn't reachable externally.
2014-11-21 20:36:48 +00:00
Justin Clark-Casey (justincc) 84d557a7bd Make small adjustment to JobEngine default from previous commit to enable it when [Startup] section is not present (though this is extremely unlikely). 2014-11-21 02:16:56 +00:00
Justin Clark-Casey (justincc) c96806a3f5 Add [Startup] JobEngineEnabled setting that allows the job engine to be disabled for testing purposes if necessary. 2014-11-21 01:44:30 +00:00
Justin Clark-Casey (justincc) 377b79bafc Move conditionals which control whether a task is placed in the JobEngine inside Watchdog.RunJob() (renamed from RunWhenPossible) and generalize them. 2014-11-21 01:08:58 +00:00
Justin Clark-Casey (justincc) df75f14bca Add [BulletSim] option AvatarToAvatarCollisionsByDefault to control whether avatars collide. This is true by default.
This is implemented with a new collision type (PhantomToOthersAvatar) to potentially allow colliding and non-colliding avatars to be present in the same scene.
So there is no provision yet for giving avatars different collision types.
This commit replaces the temporary change in commit f3eaa6d8 where avatars would never collide when using BulletSim
This is equivalent to the av_av_collisions_off option in ODE.
2014-11-20 21:28:12 +00:00
Justin Clark-Casey (justincc) bf5e220450 Fix compile error from previous 1d56029848 2014-11-11 18:10:51 +00:00
Justin Clark-Casey (justincc) 1d56029848 Fix issue where llRemoteLoadScriptPin() would treat 0 (the default) as a valid set pin in a destination prim rather than the unset no pin state
Adds regression test for this case.
2014-11-11 17:28:24 +00:00
Justin Clark-Casey (justincc) 6affa906ee When processing incoming attachments via HG, if a request for uuid gathering or final asset import takes too long remove remaining requests from same user to prevent hold up of other user's incoming attachments.
This improves upon the earlier naive simply queueing immplementation.
Threshold is 30 seconds.  If this happens to a user they can relog and fetch will be reattempted.
2014-11-06 01:15:22 +00:00
Justin Clark-Casey (justincc) 9d78d16cf3 Introduce an IteratingUuidGatherer where each fetch from the asset service (iteration) can be controlled by the caller.
This is to enable an imminent change where incoming HG scene object fetching can assess the time taken by each request rather than being forced to perform all requests in one call.
Soon, this will replace the existing UuidGatherer since it is both simpler and more flexible.
2014-11-05 19:36:53 +00:00
Justin Clark-Casey (justincc) 6fa2e685a9 Add incoming packet async handling engine to queue some inbound udp async requests.
This is to reduce the potential for overload of the threadpool if there are many simultaneous requets in high concurrency situations.
Currently only applied to AvatarProperties and GenericMessage requests.
2014-11-05 19:02:26 +00:00
Justin Clark-Casey (justincc) 297b27e473 Add missing class from recent commit 69abade 2014-11-04 18:26:35 +00:00
Justin Clark-Casey (justincc) 9c8d5f54d8 Add "show threadpool calls active" console debug command.
This shows named threadpool calls (excluding timer and network calls) that are currently queued or running.
Also shows total of labelled and any anonymous calls.
2014-11-04 17:21:22 +00:00
Justin Clark-Casey (justincc) 69abadedae Add naive implementation of controlled incoming HG attachments to manage load.
Instead of processing all incoming attachment scene object concurrently, process them consecutively to eliminate potential overload from this source.
This is a naive implementation because it does not currently account for slow foreign asset services.
Although it may take longer, this approach may also improve attachment visibility for HG avatars
since the scene object is now always added to the scene after receiving assets from the foreign service and not before.
2014-11-04 16:49:32 +00:00
Justin Clark-Casey (justincc) 3372210c46 Label all threadpool calls being made in core OpenSimulator. This is to add problem diagnosis.
"show threadpool calls" now also returns named (labelled), anonymous (unlabelled) and total call stats.
2014-11-04 00:55:48 +00:00
Justin Clark-Casey (justincc) d3a550bc85 Add "show threadpool calls" command to show count of all labelled smartthreadpool calls 2014-11-03 23:49:11 +00:00
Justin Clark-Casey (justincc) 965c53ebd7 Just for now, don't alert the user or log if we couldn't change their server-side preferences due to no e-mail address being sent.
This is to avoid user confusion in the oscc rehearsal as they are often not aware that this fails because no e-mail is set.
Also may be failing in the hypergrid case, though this may also be a config issue.
This is meant as a temporary solution.
2014-10-31 23:04:18 +00:00
Justin Clark-Casey (justincc) 31b92f0217 Actually persist a changed console set agent-limit via "region set".
Unfortunately, it's not currently easy to do this with "max-agent-limit"
- this must be separately set as MaxAgents in region config if it's to persist over restarts.
2014-10-31 22:32:35 +00:00
Justin Clark-Casey (justincc) 12f50a2798 Add "region set" console command.
This current allows one to set two region parameters
agent-limit <int> will set the current root agent limit for the region, as also settable through the viewer, though some impose a max setting (e.g. 100).
max-agent-limit <int> will set the maximum allowed root agent limit.  This can also be set via the MaxAgent parameter in region config.
2014-10-31 21:44:31 +00:00
Justin Clark-Casey (justincc) fdb902d762 Add "region get" command as a synononym for "show region" console command.
This matches existing similar commands and a soon to be added "region set" command.
2014-10-31 21:12:25 +00:00
justincc a58ae73694 Update libomv to cedac55
This resolves an issue with pCampbot where some bots would occasionally connect with the same UDP source port.
This sometimes led to console messages where bots would report receiving packets multiple times that weren't marked as resends.
DLLs built under windows
2014-10-30 23:31:45 +00:00
Justin Clark-Casey (justincc) 43ac867512 Stop Mono 3.2.8 from binding a UDP socket to a port already in use.
At least on Mono 3.2.8 (but not under Windows), one can bind multiple UDP sockets to the same port by default.
Different simulators cannot demultiplex each other's messages, so a set of confusing non-obvious errors arise if this occurs.
This change prevents such multiple binding.
2014-10-30 20:54:23 +00:00
Justin Clark-Casey (justincc) 064897be85 On pCampbot, if we add the none (n) behaviour then make it actually stop any bots in motion.
Previously, adding this behaviour after physics (p) would leave the bot to drift off for ever in its last movement direction.
2014-10-29 00:29:11 +00:00
Justin Clark-Casey (justincc) 4275342515 Add "wearables check" console command
This checks that all the wearable assets and any assets for a given logged in avatar exist in the asset service
2014-10-28 23:00:49 +00:00
Justin Clark-Casey (justincc) cc23d4bac5 Add "wearables show" console command.
This shows summary wearables information (shape, hair, etc.) for all avatars in the scene or specific information about a given avatar's wearables.
Similar to the existing "attachments show" command.
2014-10-28 17:29:04 +00:00
Justin Clark-Casey (justincc) 1c12930c03 Fix recent regression where adaptive throttles stopped adjusting.
Extends regression tests to test response of adaptive throttles to ack'ed and expired packets.
2014-10-28 00:44:03 +00:00
Justin Clark-Casey (justincc) 096aecc097 Fix setting of max scene throttle so that setting it restricts the child client throttles properly.
In "show throttles", also renames 'total' column to 'actual' to reflect that it is not necessarily the throttles requested for/by the client.
Also fills out 'target' in non-adapative mode to the actual throttle requested for/by the client.
2014-10-25 02:09:37 +01:00
Justin Clark-Casey (justincc) bda36ad2e0 Add request drip rate to assertions for token bucket regression tests 2014-10-25 00:36:50 +01:00
Justin Clark-Casey (justincc) 67007c7d21 Add regression tests for token buckets on their own 2014-10-25 00:32:46 +01:00
Justin Clark-Casey (justincc) cdc3301a33 Make regression throttle tests consistently test target and max throttle settings.
As part of this also refactors code to put all throttle asserts in a single regression test method
2014-10-25 00:09:39 +01:00
Justin Clark-Casey (justincc) 27efecc82f minor: In "show client stats" command, properly handle the case where a client has made no AgentUpdate requests (as is the case with agents that have only even been child) rather than throwing an exception 2014-10-24 21:52:31 +01:00
Justin Clark-Casey (justincc) a17bbeca9d minor: Correct letter accidentally added to copyright notice on top of Scene.cs (almost five years ago!) 2014-10-22 23:51:14 +01:00
Justin Clark-Casey (justincc) 6fa8ddf0fc In Scene.AddNewAgent(), avoid a situation where an exception can result in a client being added to the manager without IClientAPI.SceneAgent being set.
This is done by adjusting the order of code so that SceneAgent will always be set before adding the client.
Various parts of the code (rightly) assume that a a client registered to the manager will always have a SceneAgent set no matter what.
2014-10-22 23:46:05 +01:00
Justin Clark-Casey (justincc) 7d2aad3873 For now, send all non-full terse updates for ones own avatar directly to the LLUDP client stack rather than queueing internally within LLClientView.
When an HG avatar enters a scene, it delays processing of entity updates.  Could be crowding out by other updates or something else.
This delay in ones own av mvmt updates results in mvmt lag experienced on the client.  Avoiding the internal LLClientView for these packets appears to resolve this issue.
Appears most noticeably for avatars with attachments, though has also been seen on those without sometimes.  Hasn't been observed for non-HG avatars in general.
Will be investigating exactly what the problem is, at which point there will be a more permanent solution.
2014-10-21 18:27:09 +01:00
Justin Clark-Casey (justincc) c1a2c4a0bd Add "debug lludp throttles get/set request" and get current
This allows one to set the requested throttle (which normally comes from the client) as opposed to the max.
2014-10-21 02:29:39 +01:00
Justin Clark-Casey (justincc) eaa048eb89 Change the word order of some debug lludp settings for readability
On server, scene-throttle-max becomes max-scene-throttle and likewise max-new-client-throttle
On clients, throttle-max becomes max
2014-10-21 02:17:38 +01:00
Justin Clark-Casey (justincc) bb3e68c069 Add "debug lludp get/set new-client-throttle-max" to allow default new client throttle to be set separately from existing clients.
"debug lludp throttles get/set throttle-max" now only gets and sets current max client throttles
2014-10-21 02:10:55 +01:00
Justin Clark-Casey (justincc) 5dc0730f06 Add "debug lludp get" command which currently just shows scene-throttle-max to mirror "debug lludp set"
Information is also available in "show server throttles" but that's more for non-debug info rather than attempting to get and set parameters on the fly for debug purposes.
2014-10-21 01:48:59 +01:00
Justin Clark-Casey (justincc) 3e25e6a170 Add some more llGiveInventory() regression tests 2014-10-20 23:57:16 +01:00
Melanie Thielker c6f39a0bfd Fix transferring inventory from prims to agent inventory 2014-10-20 23:50:17 +01:00
Justin Clark-Casey (justincc) 830735a42f When inserting missing CreatorData in the HGAssetMapper, do the rewrite on a streaming xml basis rather than loading it all into memory via XmlDocument.
This is because objects with lots of parts can have a lot of xml to load into memory, and this has been seen to have a noticeable performance impact.
Whereas streaming has been seen to reduce the impact in normal serialization.
Implmentation is messy but I couldn't see a better way of doing it when you can't assume that you know the exact structure of the input XML.
2014-10-20 23:46:34 +01:00
Justin Clark-Casey (justincc) dede17b0d2 Add regression test TestPostAssetRewrite() to check results of HGAssetMapper.Post() object asset rewriting, 2014-10-16 01:13:38 +01:00
Justin Clark-Casey (justincc) a54c784b81 If an exception makes it to the top of a JobEngine request, catch and log instead of letting it terminate the simulator... 2014-10-14 20:42:41 +01:00
Justin Clark-Casey (justincc) 493a86dfed Allow GetMesh capability to be served directly by a server like GetTexture
To do this required GetMesh to be converted to a BaseStreamHandler
Unlike GetTexture connector, no redirect URL functionality yet (this wasn't present in the first place).
2014-10-14 18:37:22 +01:00
Justin Clark-Casey (justincc) 22020927c6 Start JobEngine by default in simulator for now. 2014-10-14 17:13:53 +01:00
Justin Clark-Casey (justincc) b9b2f5686f If JobEngine is active, then use it to copy/rez attachments for an avatar entering the scene that isn't initially logging on. This will execute tasks consecutively rather than concurrently.
This has two aims
1) Reduce initial teleport failures when a foreign Hypergrid user enters a region by not holding up the teleport for attachment rez (this can be particularly costly when HG gets all assets in the object graph.
2) Reduce server load that may impact other simulator activities.
This complements existing JobEngine options that perform initial login attachment rez and appearance send in consecutive tasks.
2014-10-14 16:57:58 +01:00
Justin Clark-Casey (justincc) 275613ad83 minor: be consistent about reporting errors out of HttpServerBase 2014-10-14 00:35:15 +01:00
Justin Clark-Casey (justincc) 2935e79ca3 If the port entry in [Network] for a server is missing, then actually tell the user that's the problem rather than simply exiting silently.
Also exit with Environment.Exit(), not by aborting the thread.
2014-10-13 23:57:46 +01:00
Justin Clark-Casey (justincc) 0437d44785 Add an IConfigSource constructor to HGAssetBroker so that it can be instantiated directly for potentially handling some capabilities directly in services with HG active 2014-10-13 23:10:08 +01:00
Justin Clark-Casey (justincc) 00e31de872 Fix an issue where specifying both max client and server outgoing UDP throttles would cause client throttles to be lower than expected when total requests exceeded the scene limit.
This was because specifying a max client throttle would always request the max from the parent server throttle, no matter the actual total requests on the client throttle.
This would lead to a lower server multiplier than expected.
This change also adds a 'target' column to the "show throttles" output that shows the target rate (as set by client) if adaptive throttles is active.
This commit also re-adds the functionality lost in recent 5c1a1458 to set a max client throttle when adaptive is active.
This commit also adds TestClientThrottlePerClientAndRegionLimited and TestClientThrottleAdaptiveNoLimit regression tests
2014-10-10 23:36:50 +01:00
Justin Clark-Casey (justincc) 458540400a Use automatic properties for Parent and TotalDripRequest in TokenBucket to make code analysis easier. No functional change. 2014-10-10 18:38:54 +01:00
Justin Clark-Casey (justincc) 5c1a14587d Remove the unnecessary intermediate total token bucket.
This only had one child, which is the 'adaptive' token bucket.
So from testing and currently analysis, we can use that bucket directly which simplifies the code.
2014-10-10 00:58:16 +01:00
Justin Clark-Casey (justincc) b28b31b3ee minor: remove warnings from unused fields in LocalGridServicesConnector 2014-10-09 01:30:24 +01:00
Justin Clark-Casey (justincc) 16eb9253b0 minor: Remove unused field from EntityTransferModule 2014-10-09 01:25:11 +01:00
Justin Clark-Casey (justincc) ba0707ca1e minor: remove compiler warning from unused field in SimulatorFeaturesModule 2014-10-09 01:23:53 +01:00
Justin Clark-Casey (justincc) 3e4550adf7 minor: resolve warnings from unused fields in XBakesGet and Post handlers 2014-10-09 01:08:21 +01:00
Justin Clark-Casey (justincc) e902824da7 Remove compiler warning from UserProfilesHandlers 2014-10-09 01:03:45 +01:00
Justin Clark-Casey (justincc) 235eb92c0e minor: remove warning in BasicHttpAuthentication by commenting out unused remove_me parameter (which looks like it might still be potentially useful for logging) 2014-10-09 00:57:10 +01:00
Justin Clark-Casey (justincc) d69ab1e037 extend TestClientThrottleRegionLimited for 2 clients after testing 1. Renames to TestSingleClientThrottleRegionLimited() 2014-10-09 00:51:36 +01:00
Justin Clark-Casey (justincc) d69e3760e1 Add regression test TestClientThrottleRegionLimited() for testing simple behaviour of throttles where a region-wide total outbound limit is in place. 2014-10-08 23:54:11 +01:00
Justin Clark-Casey (justincc) a83f5f2153 factor out common throttle setting byte[] array construction in ThrottleTests. 2014-10-08 22:50:34 +01:00
Justin Clark-Casey (justincc) 3802f2da3b Add regression test TestClientThrottleLimited() for throttle behaviour when a max client total limit is enforced server-side 2014-10-08 21:30:52 +01:00
Justin Clark-Casey (justincc) 51043746f3 refactor: consistently put all test classes in the OpenSim.Tests.Common package rather than some in OpenSim.Tests.Common.Mock
the separate mock package was not useful and was just another using line to always add
2014-10-08 21:09:25 +01:00
Justin Clark-Casey (justincc) b6eaef79dd minor: disable logging in regression test TestClientThrottleSetNoLimit 2014-10-08 20:54:09 +01:00
Justin Clark-Casey (justincc) c993067204 minor: comment out unused method in regression BasicCircuitTests 2014-10-08 20:53:39 +01:00
Justin Clark-Casey (justincc) ef39fcf465 Add basic regression test ThrottleTests.TestClientThrottleSetNoLimit 2014-10-08 20:52:17 +01:00
Justin Clark-Casey (justincc) e8337d6a51 refactor: Move test clientstack setup code out of BasicCircuitTests into OpenSim.Tests.Common.ClientStackHelpers 2014-10-08 20:17:51 +01:00
Justin Clark-Casey (justincc) 90b31a2f54 Fix recent regression in "debug lludp throttles get" command that stopped it printing any information. Also fix max throttle displayed to be properly kbps 2014-10-08 00:46:24 +01:00
Justin Clark-Casey (justincc) b40220885e minor: in "show server throttles", display unset if new client throttle value is not set rather than 0 2014-10-08 00:31:35 +01:00
Justin Clark-Casey (justincc) 649891a0d8 Add throttle-max option to "debug lludp throttles set" to allow runtime setting of default and existing client throttles.
Doesn't yet adjust until clients submit new throttle settings.
2014-10-07 18:34:08 +01:00
Justin Clark-Casey (justincc) a529bc8f2a Change "debug lludp throttle *" commands to "debug lludp throttles" for consistency (and because I keep typing throttles).
This will still work with "debug lludp throttle" anyway.
2014-10-07 01:44:36 +01:00
Justin Clark-Casey (justincc) 16aca6ddbd small adjustment to commented out scene_throttle_max_bps and client_throttle_max_bps examples in OpenSimDefaults.ini
Make them actually reflect 20 mbit and 1.5 mbit respectively
2014-10-07 01:14:13 +01:00
Justin Clark-Casey (justincc) 38458d4be8 Change help text for client_throttle_max_bps in OpenSimDefaults.ini to state it is in bytes, not bits
This is the same as already done for scene_throttle_max_bps
Internally, the token buckets are in bytes and the other help text makes it clear that the number is bytes per second
(though with the wrong assumption that 1 mbit = 1024 * 1024 bits whereas 1 mbit = 1000 kbits = 1000000 bits)
2014-10-07 01:10:57 +01:00
Justin Clark-Casey (justincc) 9ee171f441 Fix console set and get of max scene rate. Was performing wrong calculation - throttle buckets are set in bytes, not bits 2014-10-07 01:08:22 +01:00
Justin Clark-Casey (justincc) 7ca4e2cb6f Eliminate 'max' throttle setting from server throttles report since this never applies. 2014-10-07 00:08:44 +01:00
Justin Clark-Casey (justincc) 523f0b8938 Allow "debug lludp throttle *" commands to work without a user name, in which case they apply to all users in the lludp server 2014-10-07 00:03:05 +01:00
Justin Clark-Casey (justincc) 4f04c0b560 minor: add apparant total to logging when client sets throttles 2014-10-06 23:39:52 +01:00
Justin Clark-Casey (justincc) b7f78bf0f7 minor: fix bug in throttle logging where arguments were mismatched 2014-10-06 23:34:27 +01:00
Justin Clark-Casey (justincc) 5cb3b87b21 Add "debug lludp set scene-throttle-max <value>" console command to allow us to potentially set the scene max throttle on the fly. 2014-10-06 23:29:41 +01:00
Justin Clark-Casey (justincc) 97e25a0f45 Move information about "server agent rate" throttles into "show server throttles" command rather than "show throttles"
THis allows us to see the rates when no client is connected to the region.
2014-10-06 22:18:54 +01:00
Justin Clark-Casey (justincc) 026df644b5 Add "show server throttles" command for showing server specific information about throttles
This is separate from the user-oriented "show throttles" command since one will often only want to know about varying client throttle settings.
Currently displays max scene throttle and adaptive throttles config if set.
2014-10-06 20:34:17 +01:00
Justin Clark-Casey (justincc) c3b1c72c33 refactor: Use simpler auto-implemented property for HttpPort in GridRegion 2014-10-03 01:22:25 +01:00
Justin Clark-Casey (justincc) 277dbb9acd minor: Remove compiler warning from GridRegion in IGridService 2014-10-03 00:43:04 +01:00
Justin Clark-Casey (justincc) 6cfebd66ec minor: remove compiler warning from OpenProfileClient 2014-10-03 00:38:48 +01:00
Justin Clark-Casey (justincc) c9d7eb30db Add OutgoingPacketsQueuedCount clientstack stat.
This is the total of queued outgoing packets across all connections, as also seen in the "show queues" command.
Gives some early indication of whether the simulator can't send all outgoing packets fast enough.
Though then one would want to check that this isn't due to a few bad client connections.
2014-10-02 23:49:37 +01:00
Justin Clark-Casey (justincc) db5de62394 minor: Remove compiler warnings from unused fields in TokenBucket 2014-10-02 23:20:39 +01:00
Justin Clark-Casey (justincc) 5c3f33bb48 refactor: Move LLUDPServer console commands into their own class. 2014-10-02 23:18:21 +01:00
Justin Clark-Casey (justincc) d50f85dff6 minor: Comment out received seed caps request logging for now 2014-10-02 22:37:45 +01:00
BlueWall b7abcd28e1 Fix key name in example Regions.ini file 2014-10-02 22:37:34 +01:00
AliciaRaven d53703362e When a prim is bought through BuySellModule, the click action is not changed back from buy object. This means that after the object is bought, it still appears as if for sale which can be confusing. This sets it back to touch, the default after sale.
Signed-off-by: BlueWall <jamesh@bluewallgroup.com>
2014-10-02 22:37:25 +01:00
Justin Clark-Casey (justincc) 4e1f2ba1f4 Make "generate map" console command also trigger upload to maptiles as well as asset generation without performing tile generation twice. 2014-10-02 22:37:11 +01:00
Diva Canto 51951682e7 Fixed a hard-to-run-into bug in groups: at the time of creation of a group, the OwnerRoleID in the groups table was inconsistent with the roleID in the roles table. OpenSim core was not running into this bug, but 3rd party modules (like Wifi) were. 2014-10-02 22:36:23 +01:00
Justin Clark-Casey (justincc) c5c387e838 refactor: rename "debug lludp throttle status" to "debug lludp throttle get" to match set command 2014-09-30 18:43:02 +01:00
Justin Clark-Casey (justincc) f7fef5bc3b Add "debug lludp throttle set" command to allow setting of parameters at runtime
Can currently only set adaptive true|false, where adaptive = false
2014-09-30 18:41:04 +01:00
Justin Clark-Casey (justincc) 8e5a62c8e7 Add "debug lludp throttle status" command to return status information about a client's throttle (currently just whether adaptive is enabled). 2014-09-30 18:18:34 +01:00
Justin Clark-Casey (justincc) ad15e06611 Add "debug lludp throttle log <level> <avatar-first-name> <avatar-last-name>" to control extra throttle related debug logging. 2014-09-30 18:12:51 +01:00
Justin Clark-Casey (justincc) 319c51b8a8 Don't unnecessarily remove from backup objects that were not directly attached from the scene.
These are never in region backup in the first place since recent 11830c43
Extend regression test to check backup status.
2014-09-29 23:18:18 +01:00
Justin Clark-Casey (justincc) 11830c4363 Do not add attachments to the region scene object backup list.
Attachment persistence is not handled in this way and this just results in a load of busy work until a check in each SOG terminates a backup check for attachments anyway.
2014-09-27 01:02:27 +01:00
Justin Clark-Casey (justincc) 2eece5b009 Move expired objects cleaning trigger to the maintenance thread of a region rather than it's main scene loop.
[Startup] default setting UpdateTempCleaningEveryNFrames becomes UpdateTempCleaningEveryNSeconds.
Default becomes 180s instead of effective 182s (which would also vary with any changes in frame time or extra long frames)
2014-09-27 00:30:42 +01:00
Roger Kirkman 528a7f3352 Add missing HGInventoryService responsible for creating My Suitcase to StandaloneHypergrid.ini 2014-09-27 00:30:33 +01:00
Justin Clark-Casey (justincc) c02b33d592 Eliminate a few unnecessary calculations in the maintenance loop.
Also uses wait event instead of sleep for periodicity control.
2014-09-26 21:29:27 +01:00
Justin Clark-Casey (justincc) 07c6630c1c Fix recent minor regression where the default frame time wasn't being set if there was no startup config section.
Caused some regression tests to fail.
2014-09-26 21:22:41 +01:00
Justin Clark-Casey (justincc) cfc95afc3d If Bullet is running on its own thread, use a reset event to control timing rather than a sleep.
In theory, there should be no difference between these mechanisms.
However, on at least Mono 3.2.8 waiting via an event appears to be much more accurate.
2014-09-26 20:56:22 +01:00
Justin Clark-Casey (justincc) 85e04198fe Improve frame time stability by taking a few unnecessary repeated calculations out of the main scene loop.
Also uses a wait event to sleep rather than a Thread.Sleep to allow the loop to be interrupted in a more controlled manner when necessary.
2014-09-26 20:05:22 +01:00
Justin Clark-Casey (justincc) 1256d643be Add "debug lludp data out" console command for logging outgoing data just before it's put on the wire.
Unlike "debug lludp packet" which logs at the point where OpenSim first asks the clientstack to send a certain outgoing packet, this logs immediately before the actual send.
For low-level debugging purposes.
2014-09-24 23:42:57 +01:00
Justin Clark-Casey (justincc) f2715a5a2f Update libopenmetaverse to 0f4b361.
Primarily to get a small message logging improvement for pCampbot.
2014-09-24 23:22:05 +01:00
Justin Clark-Casey (justincc) d2b8281df9 Add "debug lludp packet" command to pCampbot.
This allows one to log the packets received by a particular bot that are not duplicates of already received packets.
Similar to the OpenSimulator command at the same name but currently any positive level logs all received packets.
No facility yet for logging outgoing packets.
For debug purposes.
2014-09-24 23:03:39 +01:00
Justin Clark-Casey (justincc) 6b05cfce25 Remove an unnecessary check at the bottom of Scene.CloseAgent()
At this point sp != null so no check required.
2014-09-24 00:45:19 +01:00
Justin Clark-Casey (justincc) 0448935b1b Set appearance refresh to false by default.
This setting was originally added some time ago to deal with issues where appearance was not received properly by all users.
However, it does not scale well with large numbers of agents.
Disabling to see if the original problem has abated or whether this will have to be tackled in another way.
2014-09-23 18:11:05 +01:00
Justin Clark-Casey (justincc) bc01c27c8a Replace two connecting bots state booleans in pCampbot with a single state machine.
Also adds "show status" command to pCampbot that currently just shows bot connecting state
2014-09-23 17:28:02 +01:00
Justin Clark-Casey (justincc) 95aade7fdb When osNpcMoveToTarget() is called for a sitting avatar then silently do nothing rather than throwing an error.
Resolves http://opensimulator.org/mantis/view.php?id=7311
2014-09-23 17:27:27 +01:00
Justin Clark-Casey (justincc) 7ff27e32bc Add cinderblocks and bobshaffer2 to contributors. 2014-09-23 17:27:22 +01:00
Justin Clark-Casey (justincc) 89c153ca7f Fix issues where setting llSetTextureAnim(FALSE... did not work properly).
I ended up amalgamating patches from http://opensimulator.org/mantis/view.php?id=7313 and http://opensimulator.org/mantis/view.php?id=7318
Thanks a lot to both bobshaffer2 and cinderblocks.
2014-09-23 17:27:18 +01:00
Justin Clark-Casey (justincc) a6c79fe956 Fix regression from recent a02dae5 where stand positions are no longer correct when a sit target is specified.
Adjusts stand position using just avatar position relative to the root prim instead.
Fixes http://opensimulator.org/mantis/view.php?id=7315 and preserves previous fix for http://opensimulator.org/mantis/view.php?id=7299
2014-09-23 17:27:13 +01:00
Justin Clark-Casey (justincc) 1e5c3f26f0 Make BulletSim thread be ThreadPriority.Highest if running
Will only effect Windows or mono with a patch such as https://gist.github.com/justincc/31e52218d098529b4696 applied
For test purposes
2014-09-16 18:32:36 +01:00
Justin Clark-Casey (justincc) e6df61fbe9 Make outboudn and packet inbox handling threads highest priority.
Will only have any affect under Windows or mono with a patch such as https://gist.github.com/justincc/31e52218d098529b4696 (not recommended) applied.
For assessment purposes.
2014-09-16 18:27:08 +01:00
Justin Clark-Casey (justincc) 5991a98d80 Set ThreadPriority on main scene thread to highest.
This will only have an effect on Windows systems or mono with the (not recommended) mono-3.2.8 debug patch https://gist.github.com/justincc/31e52218d098529b4696 applied
2014-09-16 18:17:05 +01:00
Justin Clark-Casey (justincc) c4ed67aeee Make proper fix for last commit wrt Mantis 7317 by replacing disallowed c char and not literal 'c' 2014-09-09 18:55:38 +01:00
Justin Clark-Casey (justincc) 258de1f17f For stat names containing periods, replace with '#' rather than throw exception
In relation to http://opensimulator.org/mantis/view.php?id=7317
2014-09-09 18:52:07 +01:00
Justin Clark-Casey (justincc) f8fa76c09f Add loglevel to jobengine that can be controlled via "debug jobengine loglevel <level>".
Defaults to 0
Level 1 currently does verbose logging about every queued and processed job.
2014-09-09 18:42:02 +01:00
Justin Clark-Casey (justincc) 0b7736b861 Temporarily add root agent rez attachments work to job engine if it is running rather than as a fire and forget.
Experiment to see if serializing attachment rez and send initial data jobs improves other parts of sim performance.
2014-09-09 18:26:41 +01:00
Justin Clark-Casey (justincc) a086adf427 Add experimental job engine to see if queueing some existing async work during root agent entry to a region improves perf rather than always attempting to execute everything concurrently
Job engine is controlled via "debug jobengine start|stop|status".
Can only currently be enabled and disabled dynamically at runtime.
Currently only applies to code sending initial region data (objects, other avatar data) to a client.
2014-09-09 18:14:56 +01:00
Justin Clark-Casey (justincc) e76cc35409 Merge branch 'master' into ghosts 2014-09-09 17:22:09 +01:00
Justin Clark-Casey (justincc) a129e9e351 Merge branch 'master' into ghosts 2014-09-03 00:26:53 +01:00
Justin Clark-Casey (justincc) 3c7eacf39b Fix recent regression from 473c5594 where camera started to judder on moving vehicles.
Other parts of OpenSimulator are relying on SP.Velocity == 0 for vehicles.
So add and use SP.GetWorldVelocity() instead when we need vehicle velocity, along the same lines as existing SP.GetWorldRotation()
2014-09-02 23:35:03 +01:00
Justin Clark-Casey (justincc) cd6f73392a Reinsert OpenMetaverse.dll from commit fbdf507 from an accidental replace in f1f935e
This only affected pCampbot.
2014-09-02 19:00:14 +01:00
Justin Clark-Casey (justincc) 1559a3a099 Merge branch 'master' into ghosts 2014-09-02 18:34:54 +01:00
Justin Clark-Casey (justincc) 6520065625 Merge branch 'master' into ghosts 2014-08-26 18:52:50 +01:00
Justin Clark-Casey (justincc) 693bfdc0fb Merge branch 'master' into ghosts 2014-08-26 18:26:27 +01:00
Justin Clark-Casey (justincc) f3eaa6d81e Temporary hack to disable av to av collisions in bulletsim.
Need to do this for a test.  Final implementation will be properly controlled through a property.
2014-08-26 18:17:09 +01:00
1667 changed files with 180231 additions and 265184 deletions

13
.gitignore vendored
View File

@ -1,6 +1,5 @@
.project
.settings
.gitignore
*.csproj
*.csproj.user
*.build
@ -11,7 +10,6 @@
*.pidb
*.dll.build
*.dll
*.log
# Ignore .user and .suo files as these are user preference specific
# http://stackoverflow.com/questions/72298/should-i-add-the-visual-studio-suo-and-user-files-to-source-control
@ -31,8 +29,6 @@
*/*/*/*/*/bin
*/*/*/*/*/*/bin
*/*/*/*/*/*/*/bin
.vs/
addon-modules/
bin/Debug/*.dll
bin/*.dll.mdb
bin/*.db
@ -71,12 +67,6 @@ bin/OpenSim.Grid.InventoryServer.log
bin/OpenSim.Grid.MessagingServer.log
bin/OpenSim.Grid.UserServer.log
bin/OpenSim.log
bin/OpenSimStats.log
bin/Robust.log
bin/RobustStats.log
bin/OpenSimConsoleHistory.txt
bin/RobustConsoleHistory.txt
bin/*.Tests.log
bin/*.manifest
bin/crashes/
Examples/*.dll
@ -94,6 +84,7 @@ TAGS
Makefile.local
bin/.version
compile.bat
addon-modules
OpenSim/Data/Tests/test-results/
OpenSim/Framework/Serialization/Tests/test-results/
OpenSim/Framework/Servers/Tests/test-results/
@ -112,5 +103,3 @@ OpenSim/Tests/test-results/
test-results/
doc/html
doc/doxygen.error.log
*.patch

View File

@ -113,12 +113,10 @@
</exec>
<fail message="Failures reported in unit tests." unless="${int::parse(testresult.opensim.region.coremodules.tests)==0}" />
<!--
<exec program="${nunitcmd}" failonerror="true" resultproperty="testresult.opensim.region.optionalmodules.tests">
<arg value="./bin/OpenSim.Region.OptionalModules.Tests.dll" />
</exec>
<fail message="Failures reported in unit tests." unless="${int::parse(testresult.opensim.region.optionalmodules.tests)==0}" />
-->
<exec program="${nunitcmd}" failonerror="true" resultproperty="testresult.opensim.region.framework.tests">
<arg value="./bin/OpenSim.Region.Framework.Tests.dll" />
@ -145,12 +143,7 @@
</exec>
<fail message="Failures reported in unit tests." unless="${int::parse(testresult.opensim.services.inventoryservice.tests)==0}" />
<exec program="${nunitcmd}" failonerror="true" resultproperty="testresult.opensim.tests.permissions">
<arg value="./bin/OpenSim.Tests.Permissions.dll" />
</exec>
<fail message="Failures reported in unit tests." unless="${int::parse(testresult.opensim.tests.permissions)==0}" />
<delete dir="%temp%"/>
<delete dir="%temp%"/>
</target>
<target name="test-stress" depends="build, find-nunit">
@ -233,12 +226,10 @@
<arg value="-xml=test-results/OpenSim.Region.CoreModules.Tests.dll-Results.xml" />
</exec>
<!--
<exec program="${nunitcmd}" failonerror="false" resultproperty="testresult.opensim.region.optionalmodules.tests">
<arg value="./bin/OpenSim.Region.OptionalModules.Tests.dll" />
<arg value="-xml=test-results/OpenSim.Region.OptionalModules.Tests.dll-Results.xml" />
</exec>
-->
<exec program="${nunitcmd}" failonerror="false" resultproperty="testresult.opensim.region.framework.tests">
<arg value="./bin/OpenSim.Region.Framework.Tests.dll" />
@ -265,23 +256,17 @@
<arg value="-xml=test-results/OpenSim.Services.InventoryService.Tests.dll-Results.xml" />
</exec>
<exec program="${nunitcmd}" failonerror="false" resultproperty="testresult.opensim.tests.permissions">
<arg value="./bin/OpenSim.Tests.Permissions.dll" />
<arg value="-xml=test-results/OpenSim.Tests.Permissions.dll-Results.xml" />
</exec>
<fail message="Failures reported in unit tests." unless="${int::parse(testresult.opensim.tests)==0}" />
<fail message="Failures reported in unit tests." unless="${int::parse(testresult.opensim.framework.tests)==0}" />
<fail message="Failures reported in unit tests." unless="${int::parse(testresult.opensim.framework.servers.tests)==0}" />
<fail message="Failures reported in unit tests." unless="${int::parse(testresult.opensim.region.clientstack.lindenudp.tests)==0}" />
<fail message="Failures reported in unit tests." unless="${int::parse(testresult.opensim.region.scriptengine.tests)==0}" />
<fail message="Failures reported in unit tests." unless="${int::parse(testresult.opensim.region.coremodules.tests)==0}" />
<!-- <fail message="Failures reported in unit tests." unless="${int::parse(testresult.opensim.region.optionalmodules.tests)==0}" /> -->
<fail message="Failures reported in unit tests." unless="${int::parse(testresult.opensim.region.optionalmodules.tests)==0}" />
<fail message="Failures reported in unit tests." unless="${int::parse(testresult.opensim.region.framework.tests)==0}" />
<fail message="Failures reported in unit tests." unless="${int::parse(testresult.opensim.data.tests)==0}" />
<fail message="Failures reported in unit tests." unless="${int::parse(testresult.opensim.capabilities.handlers.tests)==0}" />
<fail message="Failures reported in unit tests." unless="${int::parse(testresult.opensim.services.inventoryservice.tests)==0}" />
<fail message="Failures reported in unit tests." unless="${int::parse(testresult.opensim.tests.permissions)==0}" />
</target>
<target name="doxygen">

View File

@ -1,35 +1,38 @@
# Building on Windows
Steps:
* runprebuild.bat
* Load OpenSim.sln into Visual Studio .NET and build the solution.
* chdir bin
* copy OpenSim.ini.example to OpenSim.ini and other appropriate files in bin/config-include
* run OpenSim.exe
# Building on Linux / Mac
# Building on Linux
Prereqs:
* Mono > 5.0
* On some Linux distributions you may need to install additional packages.
* msbuild or xbuild if still supported by the mono version
* See http://opensimulator.org/wiki/Dependencies for more information.
* Mono >= 2.4.3
* Nant >= 0.85
* On some Linux distributions you may need to install additional packages.
See http://opensimulator.org/wiki/Dependencies for more information.
* May also use xbuild (included in mono distributions)
* May use Monodevelop, a cross-platform IDE
From the distribution type:
* ./runprebuild.sh
* type msbuild or xbuild
* nant (or !* xbuild)
* cd bin
* copy OpenSim.ini.example to OpenSim.ini and other appropriate files in bin/config-include
* review and change those ini files according to your needs
* windows: execute opensim.exe or opensim32.exe for small regions
* linux: run ./opensim.sh
* msbuild (xbuild) option switches
* clean: msbuild /target:clean
* debug: (default) msbuild /property:Configuration=Debug
* release: msbuild /property:Configuration=Release
* run mono OpenSim.exe
!* xbuild option switches
!* clean: xbuild /target:clean
!* debug: (default) xbuild /property:Configuration=Debug
!* release: xbuild /property:Configuration=Release
# Using Monodevelop
From the distribution type:
* ./runprebuild.sh
* type monodevelop OpenSim.sln
# References

View File

@ -4,19 +4,37 @@ The following people have contributed to OpenSim (Thank you for your effort!)
These folks represent the current core team for OpenSim, and are the
people that make the day to day of OpenSim happen.
* justincc (OSVW Consulting, justincc.org)
* chi11ken (Genkii)
* dahlia
* Melanie Thielker
* Diva (Crista Lopes, University of California, Irvine)
* Robert Adams (MisterBlue)
* Dan Lake
* Marck
* Mic Bowman
* BlueWall (James Hughes)
* Nebadon Izumi (Michael Cerquoni, OSgrid)
* Snoopy Pfeffer
* Robert Adams
* Oren Hurvitz (Kitely)
* Kevin Cozens
* Leal Duarte (Ubit Umarov)
= Core Developers Following the White Rabbit =
Core developers who have temporarily (we hope) gone chasing the white rabbit.
They are in all similar to the active core developers, except that they haven't
been that active lately, so their voting rights are awaiting their come back.
* Nebadon Izumi (Michael Cerquoni, OSgrid)
* Alicia Raven
* MW (Tribal Media AB)
* Adam Frisby (DeepThink Pty Ltd)
* lbsa71 (Tribal Media AB)
* Teravus (w3z)
* Ckrinke (Charles Krinke)
* Dr Scofield aka Dirk Husemann (IBM Research - Zurich)
* mikem (3Di)
* Homer_Horwitz
* nlin (3Di)
* Arthur Rodrigo S Valadares (IBM)
* John Hurliman
= Past Open Sim Developers =
These folks are alumns of the OpenSim core group, but are now
@ -38,26 +56,7 @@ where we are today.
* adjohn (Genkii)
* idb (Ian Brown)
* Johan Berntsson (3Di)
* MW (Tribal Media AB)
* Adam Frisby (DeepThink Pty Ltd)
* lbsa71 (Tribal Media AB)
* Ckrinke (Charles Krinke)
* Dr Scofield aka Dirk Husemann (IBM Research - Zurich)
* mikem (3Di)
* Homer_Horwitz
* nlin (3Di)
* John Hurliman
* chi11ken (Genkii)
* dahlia
* justincc (OSVW Consulting, justincc.org)
* Arthur Rodrigo S Valadares (IBM)
* BlueWall (James Hughes)
* Dan Lake
* Marck
* Mic Bowman
* Oren Hurvitz (Kitely)
* Snoopy Pfeffer
* Teravus (w3z)
= Additional OpenSim Contributors =
These folks have contributed code patches or content to OpenSimulator to help make it
@ -69,9 +68,9 @@ what it is today.
* alex_carnell
* Alan Webb (IBM)
* Aleric
* Alicia Raven
* Allen Kerensky
* BigFootAg
* Bill Blight
* BlueWall Slade
* bobshaffer2
* brianw/Sir_Ahzz
@ -89,14 +88,10 @@ what it is today.
* dmiles (Daxtron Labs)
* Dong Jun Lan (IBM)
* DoranZemlja
* Drake Arconis
* dr0b3rts
* dslake
* eeyore
* FredoChaplin
* FreakyTech
* Garmin Kawaguichi
* Gavin Hird
* Gerhard
* Godfrey
* Greg C.
@ -106,10 +101,7 @@ what it is today.
* Fernando Oliveira
* Fly-Man
* Flyte Xevious
* Freaky Tech
* Garmin Kawaguichi
* Geir Noklebye
* Glenn Martin (MOSES)
* Gryc Ueusp
* H-H-H (ginge264)
* Hiro Lecker
@ -117,7 +109,6 @@ what it is today.
* Imaze Rhiano
* Intimidated
* Jak Daniels
* Jeff Kelly
* Jeremy Bongio (IBM)
* jhurliman
* John R Sohn (XenReborn)
@ -131,27 +122,21 @@ what it is today.
* KittyLiu
* Kurt Taylor (IBM)
* Lani Global
* lickx
* lillith_xue
* lkalif
* LuciusSirnah
* lulurun
* M.Igarashi
* Magnuz Binder
* maimedleech
* Mana Janus
* Mandarinka Tasty
* MarcelEdward
* Matt Lehmann
* mewtwo0641
* Mic Bowman
* Michelle Argus
* Michael Cortez (The Flotsam Project, http://osflotsam.org/)
* Michael Heilmann (MOSES)
* Micheil Merlin
* Mike Osias (IBM)
* Mike Pitman (IBM)
* Mike Rieker (Dreamnation)
* mikemig
* mikkopa/_someone - RealXtend
* Misterblue
@ -165,14 +150,12 @@ what it is today.
* openlifegrid.com
* otakup0pe
* Pixel Tomsen
* Quill Littlefeather
* ralphos
* RemedyTomm
* Revolution
* Richard Alimi (IBM)
* Rick Alther (IBM)
* Rob Smart (IBM)
* Robert Louden (MOSES)
* Roger Kirkman (zadark)
* rtomita
* Ruud Lathorp
@ -180,25 +163,17 @@ what it is today.
* Salahzar Stenvaag
* satguru p srivastava
* sempuki
* Shy Robbiani
* SignpostMarv
* SpotOn3D
* Stefan_Boom / stoehr
* Steven Zielinski (MOSES)
* Stolen Ruby
* Strawberry Fride
* Talun
* TechplexEngineer (Blake Bourque)
* TBG Renfold
* Terry Ford
* tglion
* tlaukkan/Tommil (Tommi S. E. Laukkanen, Bubble Cloud)
* TomDataWorks
* TomTheDragon (muckwaddle)
* tyre
* uriesk
* Vegaslon <vegaslon@gmail.com>
* Vincent Sylvester
* VikingErik
* Vytek
* webmage (IBM)

7241
OpenSim.FxCop Normal file

File diff suppressed because it is too large Load Diff

View File

@ -30,7 +30,6 @@ using System.Collections.Generic;
using OpenSim.Framework;
using OpenSim.Region.Framework.Interfaces;
using OpenSim.Services.Interfaces;
namespace OpenSim.Groups
{

View File

@ -46,7 +46,7 @@ namespace OpenSim.Groups
public string AccessToken;
}
public class ExtendedGroupMembersData
public class ExtendedGroupMembersData
{
// This is the only difference: this is a string
public string AgentID;
@ -65,7 +65,7 @@ namespace OpenSim.Groups
public UUID RoleID;
// This is the only difference: this is a string
public string MemberID;
}
public struct ExtendedGroupNoticeData

103
OpenSim/Addons/Groups/GroupsMessagingModule.cs Executable file → Normal file
View File

@ -131,7 +131,7 @@ namespace OpenSim.Groups
{
if (!m_groupMessagingEnabled)
return;
scene.RegisterModuleInterface<IGroupsMessagingModule>(this);
m_sceneList.Add(scene);
@ -163,7 +163,7 @@ namespace OpenSim.Groups
if (m_groupData == null)
{
m_log.Error("[Groups.Messaging]: Could not get IGroupsServicesConnector, GroupsMessagingModule is now disabled.");
RemoveRegion(scene);
RemoveRegion(scene);
return;
}
@ -218,7 +218,7 @@ namespace OpenSim.Groups
m_msgTransferModule = null;
}
public Type ReplaceableInterface
public Type ReplaceableInterface
{
get { return null; }
}
@ -252,7 +252,7 @@ namespace OpenSim.Groups
m_debugEnabled = verbose;
MainConsole.Instance.Output("{0} verbose logging set to {1}", Name, m_debugEnabled);
MainConsole.Instance.OutputFormat("{0} verbose logging set to {1}", Name, m_debugEnabled);
}
/// <summary>
@ -262,7 +262,7 @@ namespace OpenSim.Groups
{
if (m_debugEnabled)
m_log.DebugFormat("[Groups.Messaging]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
GroupRecord groupInfo = m_groupData.GetGroupRecord(agentID.ToString(), groupID, null);
if (groupInfo != null)
@ -279,7 +279,7 @@ namespace OpenSim.Groups
{
SendMessageToGroup(im, groupID, UUID.Zero, null);
}
public void SendMessageToGroup(
GridInstantMessage im, UUID groupID, UUID sendingAgentForGroupCalls, Func<GroupMembersData, bool> sendCondition)
{
@ -355,9 +355,9 @@ namespace OpenSim.Groups
{
if (!sendCondition(member))
{
if (m_debugEnabled)
if (m_debugEnabled)
m_log.DebugFormat(
"[Groups.Messaging]: Not sending to {0} as they do not fulfill send condition",
"[Groups.Messaging]: Not sending to {0} as they do not fulfill send condition",
member.AgentID);
continue;
@ -366,7 +366,7 @@ namespace OpenSim.Groups
else if (hasAgentDroppedGroupChatSession(member.AgentID.ToString(), groupID))
{
// Don't deliver messages to people who have dropped this session
if (m_debugEnabled)
if (m_debugEnabled)
m_log.DebugFormat("[Groups.Messaging]: {0} has dropped session, not delivering to them", member.AgentID);
continue;
@ -414,7 +414,7 @@ namespace OpenSim.Groups
"[Groups.Messaging]: SendMessageToGroup for group {0} with {1} visible members, {2} online took {3}ms",
groupID, groupMembersCount, groupMembers.Count(), Environment.TickCount - requestStartTick);
}
#region SimGridEventHandlers
void OnClientLogin(IClientAPI client)
@ -445,13 +445,13 @@ namespace OpenSim.Groups
// The instant message module will only deliver messages of dialog types:
// MessageFromAgent, StartTyping, StopTyping, MessageFromObject
//
// Any other message type will not be delivered to a client by the
// Any other message type will not be delivered to a client by the
// Instant Message Module
UUID regionID = new UUID(msg.RegionID);
if (m_debugEnabled)
{
m_log.DebugFormat("[Groups.Messaging]: {0} called, IM from region {1}",
m_log.DebugFormat("[Groups.Messaging]: {0} called, IM from region {1}",
System.Reflection.MethodBase.GetCurrentMethod().Name, regionID);
DebugGridInstantMessage(msg);
@ -508,7 +508,7 @@ namespace OpenSim.Groups
m_log.DebugFormat("[Groups.Messaging]: skipping agent {0} because he has an agent in region of origin", sp.UUID);
return;
}
else
else
{
if (m_debugEnabled)
m_log.DebugFormat("[Groups.Messaging]: not skipping agent {0}", sp.UUID);
@ -531,7 +531,7 @@ namespace OpenSim.Groups
}
}
});
}
}
}
@ -555,7 +555,7 @@ namespace OpenSim.Groups
break;
case (byte)InstantMessageDialog.SessionSend:
// User hasn't dropped, so they're in the session,
// User hasn't dropped, so they're in the session,
// maybe we should deliver it.
IClientAPI client = GetActiveClient(new UUID(msg.toAgentID));
if (client != null)
@ -599,34 +599,35 @@ namespace OpenSim.Groups
{
if (m_debugEnabled) m_log.DebugFormat("[Groups.Messaging]: Sending chatterbox invite instant message");
UUID fromAgent = new UUID(msg.fromAgentID);
// Force? open the group session dialog???
// and simultanously deliver the message, so we don't need to do a seperate client.SendInstantMessage(msg);
IEventQueue eq = activeClient.Scene.RequestModuleInterface<IEventQueue>();
if (eq != null)
{
eq.ChatterboxInvitation(
GroupID
, groupInfo.GroupName
, fromAgent
, msg.message
, AgentID
, msg.fromAgentName
, msg.dialog
, msg.timestamp
, msg.offline == 1
, (int)msg.ParentEstateID
, msg.Position
, 1
, new UUID(msg.imSessionID)
, msg.fromGroup
, OpenMetaverse.Utils.StringToBytes(groupInfo.GroupName)
);
eq.ChatterboxInvitation(
GroupID
, groupInfo.GroupName
, new UUID(msg.fromAgentID)
, msg.message
, AgentID
, msg.fromAgentName
, msg.dialog
, msg.timestamp
, msg.offline == 1
, (int)msg.ParentEstateID
, msg.Position
, 1
, new UUID(msg.imSessionID)
, msg.fromGroup
, OpenMetaverse.Utils.StringToBytes(groupInfo.GroupName)
);
var update = new GroupChatListAgentUpdateData(AgentID);
var updates = new List<GroupChatListAgentUpdateData> { update };
eq.ChatterBoxSessionAgentListUpdates(GroupID, new UUID(msg.toAgentID), updates);
}
eq.ChatterBoxSessionAgentListUpdates(
new UUID(GroupID)
, AgentID
, new UUID(msg.toAgentID)
, false //canVoiceChat
, false //isModerator
, false //text mute
);
}
}
}
@ -653,7 +654,7 @@ namespace OpenSim.Groups
UUID AgentID = new UUID(im.fromAgentID);
GroupRecord groupInfo = m_groupData.GetGroupRecord(UUID.Zero.ToString(), GroupID, null);
if (groupInfo != null)
{
AgentInvitedToGroupChatSession(AgentID.ToString(), GroupID);
@ -661,12 +662,14 @@ namespace OpenSim.Groups
ChatterBoxSessionStartReplyViaCaps(remoteClient, groupInfo.GroupName, GroupID);
IEventQueue queue = remoteClient.Scene.RequestModuleInterface<IEventQueue>();
if (queue != null)
{
var update = new GroupChatListAgentUpdateData(AgentID);
var updates = new List<GroupChatListAgentUpdateData> { update };
queue.ChatterBoxSessionAgentListUpdates(GroupID, remoteClient.AgentId, updates);
}
queue.ChatterBoxSessionAgentListUpdates(
GroupID
, AgentID
, new UUID(im.toAgentID)
, false //canVoiceChat
, false //isModerator
, false //text mute
);
}
}
@ -676,7 +679,7 @@ namespace OpenSim.Groups
UUID GroupID = new UUID(im.imSessionID);
UUID AgentID = new UUID(im.fromAgentID);
if (m_debugEnabled)
if (m_debugEnabled)
m_log.DebugFormat("[Groups.Messaging]: Send message to session for group {0} with session ID {1}", GroupID, im.imSessionID.ToString());
//If this agent is sending a message, then they want to be in the session
@ -708,7 +711,11 @@ namespace OpenSim.Groups
bodyMap.Add("session_info", sessionMap);
IEventQueue queue = remoteClient.Scene.RequestModuleInterface<IEventQueue>();
queue?.Enqueue(queue.BuildEvent("ChatterBoxSessionStartReply", bodyMap), remoteClient.AgentId);
if (queue != null)
{
queue.Enqueue(queue.BuildEvent("ChatterBoxSessionStartReply", bodyMap), remoteClient.AgentId);
}
}
private void DebugGridInstantMessage(GridInstantMessage im)

686
OpenSim/Addons/Groups/GroupsModule.cs Executable file → Normal file

File diff suppressed because it is too large Load Diff

View File

@ -103,7 +103,7 @@ namespace OpenSim.Groups
if (!m_Enabled)
return;
m_log.DebugFormat("[Groups]: Registering {0} with {1}", this.Name, scene.RegionInfo.RegionName);
m_log.DebugFormat("[Groups]: Registering {0} with {1}", this.Name, scene.RegionInfo.RegionName);
scene.RegisterModuleInterface<IGroupsServicesConnector>(this);
m_Scenes.Add(scene);
@ -135,7 +135,7 @@ namespace OpenSim.Groups
{
m_LocalGroupsConnector = new GroupsServiceLocalConnectorModule(m_Config, m_UserManagement);
// Also, if local, create the endpoint for the HGGroupsService
new HGGroupsServiceRobustConnector(m_Config, MainServer.Instance, string.Empty,
new HGGroupsServiceRobustConnector(m_Config, MainServer.Instance, string.Empty,
scene.RequestModuleInterface<IOfflineIMService>(), scene.RequestModuleInterface<IUserAccountService>());
}
@ -170,7 +170,7 @@ namespace OpenSim.Groups
if (sp is ScenePresence && ((ScenePresence)sp).PresenceType != PresenceType.Npc)
{
AgentCircuitData aCircuit = ((ScenePresence)sp).Scene.AuthenticateHandler.GetAgentCircuitData(client.AgentId);
if (aCircuit != null && (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaHGLogin) != 0 &&
if (aCircuit != null && (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaHGLogin) != 0 &&
m_OfflineIM != null && m_Messaging != null)
{
List<GridInstantMessage> ims = m_OfflineIM.GetMessages(aCircuit.AgentID);
@ -184,12 +184,12 @@ namespace OpenSim.Groups
#region IGroupsServicesConnector
public UUID CreateGroup(UUID RequestingAgentID, string name, string charter, bool showInList, UUID insigniaID, int membershipFee, bool openEnrollment,
public UUID CreateGroup(UUID RequestingAgentID, string name, string charter, bool showInList, UUID insigniaID, int membershipFee, bool openEnrollment,
bool allowPublish, bool maturePublish, UUID founderID, out string reason)
{
reason = string.Empty;
if (m_UserManagement.IsLocalGridUser(RequestingAgentID))
return m_LocalGroupsConnector.CreateGroup(RequestingAgentID, name, charter, showInList, insigniaID,
return m_LocalGroupsConnector.CreateGroup(RequestingAgentID, name, charter, showInList, insigniaID,
membershipFee, openEnrollment, allowPublish, maturePublish, founderID, out reason);
else
{
@ -198,14 +198,14 @@ namespace OpenSim.Groups
}
}
public bool UpdateGroup(string RequestingAgentID, UUID groupID, string charter, bool showInList, UUID insigniaID, int membershipFee,
public bool UpdateGroup(string RequestingAgentID, UUID groupID, string charter, bool showInList, UUID insigniaID, int membershipFee,
bool openEnrollment, bool allowPublish, bool maturePublish, out string reason)
{
reason = string.Empty;
string url = string.Empty;
string name = string.Empty;
if (IsLocal(groupID, out url, out name))
return m_LocalGroupsConnector.UpdateGroup(AgentUUI(RequestingAgentID), groupID, charter, showInList, insigniaID, membershipFee,
return m_LocalGroupsConnector.UpdateGroup(AgentUUI(RequestingAgentID), groupID, charter, showInList, insigniaID, membershipFee,
openEnrollment, allowPublish, maturePublish, out reason);
else
{
@ -246,9 +246,9 @@ namespace OpenSim.Groups
return null;
}
public List<DirGroupsReplyData> FindGroups(string RequestingAgentIDstr, string search)
public List<DirGroupsReplyData> FindGroups(string RequestingAgentID, string search)
{
return m_LocalGroupsConnector.FindGroups(RequestingAgentIDstr, search);
return m_LocalGroupsConnector.FindGroups(AgentUUI(RequestingAgentID), search);
}
public List<GroupMembersData> GetGroupMembers(string RequestingAgentID, UUID GroupID)
@ -374,7 +374,7 @@ namespace OpenSim.Groups
}
}
return new List<GroupRoleMembersData>();
}
@ -561,7 +561,7 @@ namespace OpenSim.Groups
// so we have the list of urls to send the notice to
// this may take a long time...
WorkManager.RunInThread(delegate
Watchdog.RunInThread(delegate
{
foreach (string u in urls)
{
@ -572,7 +572,7 @@ namespace OpenSim.Groups
hasAttachment, attType, attName, attItemID, AgentUUIForOutside(attOwnerID));
}
}
}, null, string.Format("AddGroupNotice (agent {0}, group {1})", RequestingAgentID, groupID));
}, string.Format("AddGroupNotice (agent {0}, group {1})", RequestingAgentID, groupID) , null);
return true;
}
@ -605,8 +605,14 @@ namespace OpenSim.Groups
private string AgentUUI(string AgentIDStr)
{
UUID AgentID = UUID.Zero;
if (!UUID.TryParse(AgentIDStr, out AgentID) || AgentID == UUID.Zero)
return UUID.Zero.ToString();
try
{
AgentID = new UUID(AgentIDStr);
}
catch (FormatException)
{
return AgentID.ToString();
}
if (m_UserManagement.IsLocalGridUser(AgentID))
return AgentID.ToString();
@ -620,7 +626,7 @@ namespace OpenSim.Groups
}
if (agent != null)
return Util.ProduceUserUniversalIdentifier(agent);
// we don't know anything about this foreign user
// try asking the user management module, which may know more
return m_UserManagement.GetUserUUI(AgentID);
@ -630,8 +636,14 @@ namespace OpenSim.Groups
private string AgentUUIForOutside(string AgentIDStr)
{
UUID AgentID = UUID.Zero;
if (!UUID.TryParse(AgentIDStr, out AgentID) || AgentID == UUID.Zero)
return UUID.Zero.ToString();
try
{
AgentID = new UUID(AgentIDStr);
}
catch (FormatException)
{
return AgentID.ToString();
}
AgentCircuitData agent = null;
foreach (Scene scene in m_Scenes)
@ -652,7 +664,7 @@ namespace OpenSim.Groups
string url = string.Empty, first = string.Empty, last = string.Empty, tmp = string.Empty;
if (Util.ParseUniversalUserIdentifier(uID, out userID, out url, out first, out last, out tmp))
m_UserManagement.AddUser(userID, first, last, url);
return userID;
}

View File

@ -64,8 +64,8 @@ namespace OpenSim.Groups
m_log.DebugFormat("[Groups.RobustHGConnector]: Starting with config name {0}", m_ConfigName);
string homeURI = Util.GetConfigVarFromSections<string>(config, "HomeURI",
new string[] { "Startup", "Hypergrid", m_ConfigName}, string.Empty);
string homeURI = Util.GetConfigVarFromSections<string>(config, "HomeURI",
new string[] { "Startup", "Hypergrid", m_ConfigName}, string.Empty);
if (homeURI == string.Empty)
throw new Exception(String.Format("[Groups.RobustHGConnector]: please provide the HomeURI [Startup] or in section {0}", m_ConfigName));
@ -115,10 +115,9 @@ namespace OpenSim.Groups
protected override byte[] ProcessRequest(string path, Stream requestData,
IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
{
string body;
using(StreamReader sr = new StreamReader(requestData))
body = sr.ReadToEnd();
StreamReader sr = new StreamReader(requestData);
string body = sr.ReadToEnd();
sr.Close();
body = body.Trim();
//m_log.DebugFormat("[XXX]: query String: {0}", body);

View File

@ -34,12 +34,12 @@ namespace OpenSim.Groups
{
public interface IGroupsServicesConnector
{
UUID CreateGroup(UUID RequestingAgentID, string name, string charter, bool showInList, UUID insigniaID, int membershipFee,
UUID CreateGroup(UUID RequestingAgentID, string name, string charter, bool showInList, UUID insigniaID, int membershipFee,
bool openEnrollment, bool allowPublish, bool maturePublish, UUID founderID, out string reason);
bool UpdateGroup(string RequestingAgentID, UUID groupID, string charter, bool showInList, UUID insigniaID, int membershipFee,
bool UpdateGroup(string RequestingAgentID, UUID groupID, string charter, bool showInList, UUID insigniaID, int membershipFee,
bool openEnrollment, bool allowPublish, bool maturePublish, out string reason);
ExtendedGroupRecord GetGroupRecord(string RequestingAgentID, UUID GroupID, string GroupName);
List<DirGroupsReplyData> FindGroups(string RequestingAgentIDstr, string search);
List<DirGroupsReplyData> FindGroups(string RequestingAgentID, string search);
List<GroupMembersData> GetGroupMembers(string RequestingAgentID, UUID GroupID);
bool AddGroupRole(string RequestingAgentID, UUID groupID, UUID roleID, string name, string description, string title, ulong powers, out string reason);
@ -75,7 +75,7 @@ namespace OpenSim.Groups
/// If the user is a member of the group then the data structure is returned. If not, then null is returned.
/// </returns>
ExtendedGroupMembershipData GetAgentGroupMembership(string RequestingAgentID, string AgentID, UUID GroupID);
/// <summary>
/// Get information about the groups to which a user belongs.
/// </summary>
@ -87,7 +87,7 @@ namespace OpenSim.Groups
/// </returns>
List<GroupMembershipData> GetAgentGroupMemberships(string RequestingAgentID, string AgentID);
bool AddGroupNotice(string RequestingAgentID, UUID groupID, UUID noticeID, string fromName, string subject, string message,
bool AddGroupNotice(string RequestingAgentID, UUID groupID, UUID noticeID, string fromName, string subject, string message,
bool hasAttachment, byte attType, string attName, UUID attItemID, string attOwnerID);
GroupNoticeInfo GetGroupNotice(string RequestingAgentID, UUID noticeID);
List<ExtendedGroupNoticeData> GetGroupNotices(string RequestingAgentID, UUID GroupID);

View File

@ -34,7 +34,6 @@ using System.Text;
using OpenSim.Framework;
using OpenSim.Region.Framework.Scenes;
using OpenSim.Region.Framework.Interfaces;
using OpenSim.Services.Interfaces;
using OpenMetaverse;
using Mono.Addins;
@ -108,7 +107,7 @@ namespace OpenSim.Groups
if (!m_Enabled)
return;
m_log.DebugFormat("[Groups]: Registering {0} with {1}", this.Name, scene.RegionInfo.RegionName);
m_log.DebugFormat("[Groups]: Registering {0} with {1}", this.Name, scene.RegionInfo.RegionName);
scene.RegisterModuleInterface<IGroupsServicesConnector>(this);
m_Scenes.Add(scene);
}
@ -146,16 +145,16 @@ namespace OpenSim.Groups
#region IGroupsServicesConnector
public UUID CreateGroup(UUID RequestingAgentID, string name, string charter, bool showInList, UUID insigniaID, int membershipFee, bool openEnrollment,
public UUID CreateGroup(UUID RequestingAgentID, string name, string charter, bool showInList, UUID insigniaID, int membershipFee, bool openEnrollment,
bool allowPublish, bool maturePublish, UUID founderID, out string reason)
{
m_log.DebugFormat("[Groups]: Creating group {0}", name);
reason = string.Empty;
return m_GroupsService.CreateGroup(RequestingAgentID.ToString(), name, charter, showInList, insigniaID,
return m_GroupsService.CreateGroup(RequestingAgentID.ToString(), name, charter, showInList, insigniaID,
membershipFee, openEnrollment, allowPublish, maturePublish, founderID, out reason);
}
public bool UpdateGroup(string RequestingAgentID, UUID groupID, string charter, bool showInList, UUID insigniaID, int membershipFee,
public bool UpdateGroup(string RequestingAgentID, UUID groupID, string charter, bool showInList, UUID insigniaID, int membershipFee,
bool openEnrollment, bool allowPublish, bool maturePublish, out string reason)
{
reason = string.Empty;
@ -173,9 +172,9 @@ namespace OpenSim.Groups
return null;
}
public List<DirGroupsReplyData> FindGroups(string RequestingAgentIDstr, string search)
public List<DirGroupsReplyData> FindGroups(string RequestingAgentID, string search)
{
return m_GroupsService.FindGroups(RequestingAgentIDstr, search);
return m_GroupsService.FindGroups(RequestingAgentID, search);
}
public List<GroupMembersData> GetGroupMembers(string RequestingAgentID, UUID GroupID)
@ -296,7 +295,7 @@ namespace OpenSim.Groups
public bool AddGroupNotice(string RequestingAgentID, UUID groupID, UUID noticeID, string fromName, string subject, string message,
bool hasAttachment, byte attType, string attName, UUID attItemID, string attOwnerID)
{
return m_GroupsService.AddGroupNotice(RequestingAgentID, groupID, noticeID, fromName, subject, message,
return m_GroupsService.AddGroupNotice(RequestingAgentID, groupID, noticeID, fromName, subject, message,
hasAttachment, attType, attName, attItemID, attOwnerID);
}

View File

@ -3,7 +3,7 @@ using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using Mono.Addins;
// General Information about an assembly is controlled through the following
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("OpenSim.Addons.Groups")]
@ -15,8 +15,8 @@ using Mono.Addins;
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
@ -26,11 +26,11 @@ using Mono.Addins;
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Minor Version
// Build Number
// Revision
//
[assembly: AssemblyVersion(OpenSim.VersionInfo.AssemblyVersionNumber)]
[assembly: AssemblyVersion("0.8.1.*")]
[assembly: Addin("OpenSim.Groups", OpenSim.VersionInfo.VersionNumber)]
[assembly: AddinDependency("OpenSim.Region.Framework", OpenSim.VersionInfo.VersionNumber)]
[assembly: Addin("OpenSim.Groups", "0.1")]
[assembly: AddinDependency("OpenSim", "0.5")]

View File

@ -41,7 +41,7 @@ using Nini.Config;
namespace OpenSim.Groups
{
public class GroupsServiceRemoteConnector
public class GroupsServiceRemoteConnector
{
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
@ -71,7 +71,7 @@ namespace OpenSim.Groups
}
///
m_log.DebugFormat("[Groups.RemoteConnector]: Groups server at {0}, authentication {1}",
m_log.DebugFormat("[Groups.RemoteConnector]: Groups server at {0}, authentication {1}",
m_ServerURI, (m_Auth == null ? "None" : m_Auth.GetType().ToString()));
}
@ -153,7 +153,7 @@ namespace OpenSim.Groups
return GroupsDataUtils.GroupRecord((Dictionary<string, object>)ret["RESULT"]);
}
public List<DirGroupsReplyData> FindGroups(string RequestingAgentIDstr, string query)
public List<DirGroupsReplyData> FindGroups(string RequestingAgentID, string query)
{
List<DirGroupsReplyData> hits = new List<DirGroupsReplyData>();
if (string.IsNullOrEmpty(query))
@ -161,7 +161,7 @@ namespace OpenSim.Groups
Dictionary<string, object> sendData = new Dictionary<string, object>();
sendData["Query"] = query;
sendData["RequestingAgentID"] = RequestingAgentIDstr;
sendData["RequestingAgentID"] = RequestingAgentID;
Dictionary<string, object> ret = MakeRequest("FINDGROUPS", sendData);

View File

@ -36,7 +36,6 @@ using OpenSim.Framework;
using OpenSim.Region.Framework.Scenes;
using OpenSim.Region.Framework.Interfaces;
using OpenSim.Server.Base;
using OpenSim.Services.Interfaces;
using OpenMetaverse;
using Mono.Addins;
@ -113,7 +112,7 @@ namespace OpenSim.Groups
if (!m_Enabled)
return;
m_log.DebugFormat("[Groups.RemoteConnector]: Registering {0} with {1}", this.Name, scene.RegionInfo.RegionName);
m_log.DebugFormat("[Groups.RemoteConnector]: Registering {0} with {1}", this.Name, scene.RegionInfo.RegionName);
scene.RegisterModuleInterface<IGroupsServicesConnector>(this);
m_Scenes.Add(scene);
}
@ -151,7 +150,7 @@ namespace OpenSim.Groups
#region IGroupsServicesConnector
public UUID CreateGroup(UUID RequestingAgentID, string name, string charter, bool showInList, UUID insigniaID, int membershipFee, bool openEnrollment,
public UUID CreateGroup(UUID RequestingAgentID, string name, string charter, bool showInList, UUID insigniaID, int membershipFee, bool openEnrollment,
bool allowPublish, bool maturePublish, UUID founderID, out string reason)
{
m_log.DebugFormat("[Groups.RemoteConnector]: Creating group {0}", name);
@ -167,7 +166,7 @@ namespace OpenSim.Groups
return groupID;
}
public bool UpdateGroup(string RequestingAgentID, UUID groupID, string charter, bool showInList, UUID insigniaID, int membershipFee,
public bool UpdateGroup(string RequestingAgentID, UUID groupID, string charter, bool showInList, UUID insigniaID, int membershipFee,
bool openEnrollment, bool allowPublish, bool maturePublish, out string reason)
{
string r = string.Empty;
@ -186,16 +185,16 @@ namespace OpenSim.Groups
if (GroupID == UUID.Zero && (GroupName == null || GroupName != null && GroupName == string.Empty))
return null;
return m_CacheWrapper.GetGroupRecord(RequestingAgentID,GroupID,GroupName, delegate
{
return m_GroupsService.GetGroupRecord(RequestingAgentID, GroupID, GroupName);
return m_CacheWrapper.GetGroupRecord(RequestingAgentID,GroupID,GroupName, delegate
{
return m_GroupsService.GetGroupRecord(RequestingAgentID, GroupID, GroupName);
});
}
public List<DirGroupsReplyData> FindGroups(string RequestingAgentIDstr, string search)
public List<DirGroupsReplyData> FindGroups(string RequestingAgentID, string search)
{
// TODO!
return m_GroupsService.FindGroups(RequestingAgentIDstr, search);
return m_GroupsService.FindGroups(RequestingAgentID, search);
}
public bool AddAgentToGroup(string RequestingAgentID, string AgentID, UUID GroupID, UUID RoleID, string token, out string reason)
@ -362,7 +361,7 @@ namespace OpenSim.Groups
m_GroupsService.RemoveAgentToGroupInvite(RequestingAgentID, inviteID);
}
public bool AddGroupNotice(string RequestingAgentID, UUID groupID, UUID noticeID, string fromName, string subject, string message,
public bool AddGroupNotice(string RequestingAgentID, UUID groupID, UUID noticeID, string fromName, string subject, string message,
bool hasAttachment, byte attType, string attName, UUID attItemID, string attOwnerID)
{
GroupNoticeInfo notice = new GroupNoticeInfo();

View File

@ -91,10 +91,9 @@ namespace OpenSim.Groups
protected override byte[] ProcessRequest(string path, Stream requestData,
IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
{
string body;
using(StreamReader sr = new StreamReader(requestData))
body = sr.ReadToEnd();
StreamReader sr = new StreamReader(requestData);
string body = sr.ReadToEnd();
sr.Close();
body = body.Trim();
//m_log.DebugFormat("[XXX]: query String: {0}", body);
@ -287,7 +286,7 @@ namespace OpenSim.Groups
string requestingAgentID = request["RequestingAgentID"].ToString();
if (!m_GroupsService.RemoveAgentFromGroup(requestingAgentID, agentID, groupID))
NullResult(result, string.Format("Insufficient permissions. {0}", agentID));
NullResult(result, string.Format("Insufficient permissions.", agentID));
else
result["RESULT"] = "true";
}
@ -394,7 +393,7 @@ namespace OpenSim.Groups
if (!request.ContainsKey("RequestingAgentID") || !request.ContainsKey("GroupID") || !request.ContainsKey("RoleID") ||
!request.ContainsKey("Name") || !request.ContainsKey("Description") || !request.ContainsKey("Title") ||
!request.ContainsKey("Powers") || !request.ContainsKey("OP"))
!request.ContainsKey("Powers") || !request.ContainsKey("OP"))
NullResult(result, "Bad network data");
else
@ -520,11 +519,11 @@ namespace OpenSim.Groups
bool success = false;
if (op == "ADD")
success = m_GroupsService.AddAgentToGroupRole(request["RequestingAgentID"].ToString(), request["AgentID"].ToString(),
success = m_GroupsService.AddAgentToGroupRole(request["RequestingAgentID"].ToString(), request["AgentID"].ToString(),
new UUID(request["GroupID"].ToString()), new UUID(request["RoleID"].ToString()));
else if (op == "DELETE")
success = m_GroupsService.RemoveAgentFromGroupRole(request["RequestingAgentID"].ToString(), request["AgentID"].ToString(),
success = m_GroupsService.RemoveAgentFromGroupRole(request["RequestingAgentID"].ToString(), request["AgentID"].ToString(),
new UUID(request["GroupID"].ToString()), new UUID(request["RoleID"].ToString()));
result["RESULT"] = success.ToString();
@ -648,8 +647,8 @@ namespace OpenSim.Groups
string op = request["OP"].ToString();
if (op == "ADD" && request.ContainsKey("GroupID") && request.ContainsKey("RoleID") && request.ContainsKey("AgentID"))
{
bool success = m_GroupsService.AddAgentToGroupInvite(request["RequestingAgentID"].ToString(),
{
bool success = m_GroupsService.AddAgentToGroupInvite(request["RequestingAgentID"].ToString(),
new UUID(request["InviteID"].ToString()), new UUID(request["GroupID"].ToString()),
new UUID(request["RoleID"].ToString()), request["AgentID"].ToString());
@ -665,7 +664,7 @@ namespace OpenSim.Groups
}
else if (op == "GET")
{
GroupInviteInfo invite = m_GroupsService.GetAgentToGroupInvite(request["RequestingAgentID"].ToString(),
GroupInviteInfo invite = m_GroupsService.GetAgentToGroupInvite(request["RequestingAgentID"].ToString(),
new UUID(request["InviteID"].ToString()));
if (invite != null)

View File

@ -31,8 +31,7 @@ using System.Reflection;
using System.Threading;
using OpenSim.Framework;
//using OpenSim.Region.Framework.Interfaces;
using OpenSim.Services.Interfaces;
using OpenSim.Region.Framework.Interfaces;
using OpenMetaverse;
@ -145,20 +144,14 @@ namespace OpenSim.Groups
if (firstCall)
{
try
{
//group = m_GroupsService.GetGroupRecord(RequestingAgentID, GroupID, GroupName);
group = d();
//group = m_GroupsService.GetGroupRecord(RequestingAgentID, GroupID, GroupName);
group = d();
lock (m_Cache)
{
m_Cache.AddOrUpdate(cacheKey, group, GROUPS_CACHE_TIMEOUT);
return (ExtendedGroupRecord)group;
}
}
finally
lock (m_Cache)
{
m_Cache.AddOrUpdate(cacheKey, group, GROUPS_CACHE_TIMEOUT);
m_ActiveRequests.Remove(cacheKey);
return (ExtendedGroupRecord)group;
}
}
else
@ -250,19 +243,13 @@ namespace OpenSim.Groups
if (firstCall)
{
try
{
membership = d();
membership = d();
lock (m_Cache)
{
m_Cache.AddOrUpdate(cacheKey, membership, GROUPS_CACHE_TIMEOUT);
return (ExtendedGroupMembershipData)membership;
}
}
finally
lock (m_Cache)
{
m_Cache.AddOrUpdate(cacheKey, membership, GROUPS_CACHE_TIMEOUT);
m_ActiveRequests.Remove(cacheKey);
return (ExtendedGroupMembershipData)membership;
}
}
else
@ -299,18 +286,12 @@ namespace OpenSim.Groups
if (firstCall)
{
try
{
membership = d();
lock (m_Cache)
{
m_Cache.AddOrUpdate(cacheKey, membership, GROUPS_CACHE_TIMEOUT);
return (ExtendedGroupMembershipData)membership;
}
}
finally
membership = d();
lock (m_Cache)
{
m_Cache.AddOrUpdate(cacheKey, membership, GROUPS_CACHE_TIMEOUT);
m_ActiveRequests.Remove(cacheKey);
return (ExtendedGroupMembershipData)membership;
}
}
else
@ -346,18 +327,12 @@ namespace OpenSim.Groups
if (firstCall)
{
try
{
memberships = d();
lock (m_Cache)
{
m_Cache.AddOrUpdate(cacheKey, memberships, GROUPS_CACHE_TIMEOUT);
return (List<GroupMembershipData>)memberships;
}
}
finally
memberships = d();
lock (m_Cache)
{
m_Cache.AddOrUpdate(cacheKey, memberships, GROUPS_CACHE_TIMEOUT);
m_ActiveRequests.Remove(cacheKey);
return (List<GroupMembershipData>)memberships;
}
}
else
@ -394,26 +369,20 @@ namespace OpenSim.Groups
if (firstCall)
{
try
{
List<ExtendedGroupMembersData> _members = d();
if (_members != null && _members.Count > 0)
members = _members.ConvertAll<GroupMembersData>(new Converter<ExtendedGroupMembersData, GroupMembersData>(m_ForeignImporter.ConvertGroupMembersData));
else
members = new List<GroupMembersData>();
lock (m_Cache)
{
//m_Cache.AddOrUpdate(cacheKey, members, GROUPS_CACHE_TIMEOUT);
m_Cache.AddOrUpdate(cacheKey, _members, GROUPS_CACHE_TIMEOUT);
return (List<GroupMembersData>)members;
}
}
finally
List<ExtendedGroupMembersData> _members = d();
if (_members != null && _members.Count > 0)
members = _members.ConvertAll<GroupMembersData>(new Converter<ExtendedGroupMembersData, GroupMembersData>(m_ForeignImporter.ConvertGroupMembersData));
else
members = new List<GroupMembersData>();
lock (m_Cache)
{
//m_Cache.AddOrUpdate(cacheKey, members, GROUPS_CACHE_TIMEOUT);
m_Cache.AddOrUpdate(cacheKey, _members, GROUPS_CACHE_TIMEOUT);
m_ActiveRequests.Remove(cacheKey);
return (List<GroupMembersData>)members;
}
}
else
@ -528,22 +497,16 @@ namespace OpenSim.Groups
if (firstCall)
{
try
roles = d();
if (roles != null)
{
roles = d();
if (roles != null)
lock (m_Cache)
{
lock (m_Cache)
{
m_Cache.AddOrUpdate(cacheKey, roles, GROUPS_CACHE_TIMEOUT);
return (List<GroupRolesData>)roles;
}
m_Cache.AddOrUpdate(cacheKey, roles, GROUPS_CACHE_TIMEOUT);
m_ActiveRequests.Remove(cacheKey);
return (List<GroupRolesData>)roles;
}
}
finally
{
m_ActiveRequests.Remove(cacheKey);
}
}
else
Thread.Sleep(50);
@ -578,29 +541,23 @@ namespace OpenSim.Groups
if (firstCall)
{
try
{
List<ExtendedGroupRoleMembersData> _rmembers = d();
List<ExtendedGroupRoleMembersData> _rmembers = d();
if (_rmembers != null && _rmembers.Count > 0)
rmembers = _rmembers.ConvertAll<GroupRoleMembersData>(new Converter<ExtendedGroupRoleMembersData, GroupRoleMembersData>(m_ForeignImporter.ConvertGroupRoleMembersData));
else
rmembers = new List<GroupRoleMembersData>();
if (_rmembers != null && _rmembers.Count > 0)
rmembers = _rmembers.ConvertAll<GroupRoleMembersData>(new Converter<ExtendedGroupRoleMembersData, GroupRoleMembersData>(m_ForeignImporter.ConvertGroupRoleMembersData));
else
rmembers = new List<GroupRoleMembersData>();
lock (m_Cache)
{
// For some strange reason, when I cache the list of GroupRoleMembersData,
// it gets emptied out. The TryGet gets an empty list...
//m_Cache.AddOrUpdate(cacheKey, rmembers, GROUPS_CACHE_TIMEOUT);
// Caching the list of ExtendedGroupRoleMembersData doesn't show that issue
// I don't get it.
m_Cache.AddOrUpdate(cacheKey, _rmembers, GROUPS_CACHE_TIMEOUT);
return (List<GroupRoleMembersData>)rmembers;
}
}
finally
lock (m_Cache)
{
// For some strange reason, when I cache the list of GroupRoleMembersData,
// it gets emptied out. The TryGet gets an empty list...
//m_Cache.AddOrUpdate(cacheKey, rmembers, GROUPS_CACHE_TIMEOUT);
// Caching the list of ExtendedGroupRoleMembersData doesn't show that issue
// I don't get it.
m_Cache.AddOrUpdate(cacheKey, _rmembers, GROUPS_CACHE_TIMEOUT);
m_ActiveRequests.Remove(cacheKey);
return (List<GroupRoleMembersData>)rmembers;
}
}
else
@ -709,19 +666,12 @@ namespace OpenSim.Groups
if (firstCall)
{
try
{
roles = d();
lock (m_Cache)
{
m_Cache.AddOrUpdate(cacheKey, roles, GROUPS_CACHE_TIMEOUT);
m_ActiveRequests.Remove(cacheKey);
return (List<GroupRolesData>)roles;
}
}
finally
roles = d();
lock (m_Cache)
{
m_Cache.AddOrUpdate(cacheKey, roles, GROUPS_CACHE_TIMEOUT);
m_ActiveRequests.Remove(cacheKey);
return (List<GroupRolesData>)roles;
}
}
else
@ -817,19 +767,13 @@ namespace OpenSim.Groups
if (firstCall)
{
try
{
GroupNoticeInfo _notice = d();
GroupNoticeInfo _notice = d();
lock (m_Cache)
{
m_Cache.AddOrUpdate(cacheKey, _notice, GROUPS_CACHE_TIMEOUT);
return _notice;
}
}
finally
lock (m_Cache)
{
m_Cache.AddOrUpdate(cacheKey, _notice, GROUPS_CACHE_TIMEOUT);
m_ActiveRequests.Remove(cacheKey);
return _notice;
}
}
else
@ -865,24 +809,20 @@ namespace OpenSim.Groups
if (firstCall)
{
try
{
notices = d();
notices = d();
lock (m_Cache)
{
m_Cache.AddOrUpdate(cacheKey, notices, GROUPS_CACHE_TIMEOUT);
return (List<ExtendedGroupNoticeData>)notices;
}
}
finally
lock (m_Cache)
{
m_Cache.AddOrUpdate(cacheKey, notices, GROUPS_CACHE_TIMEOUT);
m_ActiveRequests.Remove(cacheKey);
return (List<ExtendedGroupNoticeData>)notices;
}
}
else
Thread.Sleep(50);
}
}
}
}
}

View File

@ -43,63 +43,59 @@ namespace OpenSim.Groups
{
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
public const GroupPowers DefaultEveryonePowers =
GroupPowers.AllowSetHome |
GroupPowers.Accountable |
GroupPowers.JoinChat |
GroupPowers.AllowVoiceChat |
GroupPowers.ReceiveNotices |
GroupPowers.StartProposal |
GroupPowers.VoteOnProposal;
public const GroupPowers DefaultEveryonePowers = GroupPowers.AllowSetHome |
GroupPowers.Accountable |
GroupPowers.JoinChat |
GroupPowers.AllowVoiceChat |
GroupPowers.ReceiveNotices |
GroupPowers.StartProposal |
GroupPowers.VoteOnProposal;
public const GroupPowers OfficersPowers = DefaultEveryonePowers |
GroupPowers.AllowFly |
GroupPowers.AllowLandmark |
GroupPowers.AllowRez |
GroupPowers.AssignMemberLimited |
GroupPowers.ChangeIdentity |
GroupPowers.ChangeMedia |
GroupPowers.ChangeOptions |
GroupPowers.DeedObject |
GroupPowers.Eject |
GroupPowers.FindPlaces |
GroupPowers.Invite |
GroupPowers.LandChangeIdentity |
GroupPowers.LandDeed |
GroupPowers.LandDivideJoin |
GroupPowers.LandEdit |
GroupPowers.AllowEnvironment |
GroupPowers.LandEjectAndFreeze |
GroupPowers.LandGardening |
GroupPowers.LandManageAllowed |
GroupPowers.LandManageBanned |
GroupPowers.LandManagePasses |
GroupPowers.LandOptions |
GroupPowers.LandRelease |
GroupPowers.LandSetSale |
GroupPowers.MemberVisible |
GroupPowers.ModerateChat |
GroupPowers.ObjectManipulate |
GroupPowers.ObjectSetForSale |
GroupPowers.ReturnGroupOwned |
GroupPowers.ReturnGroupSet |
GroupPowers.ReturnNonGroup |
GroupPowers.RoleProperties |
GroupPowers.SendNotices |
GroupPowers.SetLandingPoint;
public const GroupPowers OwnerPowers = OfficersPowers |
GroupPowers.Accountable |
GroupPowers.AllowEditLand |
GroupPowers.AssignMember |
GroupPowers.ChangeActions |
GroupPowers.CreateRole |
GroupPowers.DeleteRole |
GroupPowers.ExperienceAdmin |
GroupPowers.ExperienceCreator |
GroupPowers.GroupBanAccess |
GroupPowers.HostEvent |
GroupPowers.RemoveMember;
public const GroupPowers OwnerPowers = GroupPowers.Accountable |
GroupPowers.AllowEditLand |
GroupPowers.AllowFly |
GroupPowers.AllowLandmark |
GroupPowers.AllowRez |
GroupPowers.AllowSetHome |
GroupPowers.AllowVoiceChat |
GroupPowers.AssignMember |
GroupPowers.AssignMemberLimited |
GroupPowers.ChangeActions |
GroupPowers.ChangeIdentity |
GroupPowers.ChangeMedia |
GroupPowers.ChangeOptions |
GroupPowers.CreateRole |
GroupPowers.DeedObject |
GroupPowers.DeleteRole |
GroupPowers.Eject |
GroupPowers.FindPlaces |
GroupPowers.Invite |
GroupPowers.JoinChat |
GroupPowers.LandChangeIdentity |
GroupPowers.LandDeed |
GroupPowers.LandDivideJoin |
GroupPowers.LandEdit |
GroupPowers.LandEjectAndFreeze |
GroupPowers.LandGardening |
GroupPowers.LandManageAllowed |
GroupPowers.LandManageBanned |
GroupPowers.LandManagePasses |
GroupPowers.LandOptions |
GroupPowers.LandRelease |
GroupPowers.LandSetSale |
GroupPowers.ModerateChat |
GroupPowers.ObjectManipulate |
GroupPowers.ObjectSetForSale |
GroupPowers.ReceiveNotices |
GroupPowers.RemoveMember |
GroupPowers.ReturnGroupOwned |
GroupPowers.ReturnGroupSet |
GroupPowers.ReturnNonGroup |
GroupPowers.RoleProperties |
GroupPowers.SendNotices |
GroupPowers.SetLandingPoint |
GroupPowers.StartProposal |
GroupPowers.VoteOnProposal;
#region Daily Cleanup
@ -129,7 +125,7 @@ namespace OpenSim.Groups
#endregion
public UUID CreateGroup(string RequestingAgentID, string name, string charter, bool showInList, UUID insigniaID, int membershipFee, bool openEnrollment,
public UUID CreateGroup(string RequestingAgentID, string name, string charter, bool showInList, UUID insigniaID, int membershipFee, bool openEnrollment,
bool allowPublish, bool maturePublish, UUID founderID, out string reason)
{
reason = string.Empty;
@ -154,25 +150,20 @@ namespace OpenSim.Groups
data.Data["ShowInList"] = showInList ? "1" : "0";
data.Data["AllowPublish"] = allowPublish ? "1" : "0";
data.Data["MaturePublish"] = maturePublish ? "1" : "0";
UUID ownerRoleID = UUID.Random();
data.Data["OwnerRoleID"] = ownerRoleID.ToString();
UUID roleID = UUID.Random();
data.Data["OwnerRoleID"] = roleID.ToString();
if (!m_Database.StoreGroup(data))
return UUID.Zero;
// Create Everyone role
_AddOrUpdateGroupRole(RequestingAgentID, data.GroupID, UUID.Zero, "Everyone", "Everyone in the group is in the everyone role.", "Member of " + name, (ulong)DefaultEveryonePowers, true);
// Create Officers role
UUID officersRoleID = UUID.Random();
_AddOrUpdateGroupRole(RequestingAgentID, data.GroupID, officersRoleID, "Officers", "The officers of the group, with more powers than regular members.", "Officer of " + name, (ulong)OfficersPowers, true);
_AddOrUpdateGroupRole(RequestingAgentID, data.GroupID, UUID.Zero, "Everyone", "Everyone in the group", "Member of " + name, (ulong)DefaultEveryonePowers, true);
// Create Owner role
_AddOrUpdateGroupRole(RequestingAgentID, data.GroupID, ownerRoleID, "Owners", "Owners of the group", "Owner of " + name, (ulong)OwnerPowers, true);
_AddOrUpdateGroupRole(RequestingAgentID, data.GroupID, roleID, "Owners", "Owners of the group", "Owner of " + name, (ulong)OwnerPowers, true);
// Add founder to group
_AddAgentToGroup(RequestingAgentID, founderID.ToString(), data.GroupID, ownerRoleID);
_AddAgentToGroup(RequestingAgentID, founderID.ToString(), data.GroupID, officersRoleID);
_AddAgentToGroup(RequestingAgentID, founderID.ToString(), data.GroupID, roleID);
return data.GroupID;
}
@ -231,22 +222,15 @@ namespace OpenSim.Groups
if (d.Data.ContainsKey("Location") && d.Data["Location"] != string.Empty)
continue;
int nmembers = m_Database.MemberCount(d.GroupID);
if(nmembers == 0)
continue;
DirGroupsReplyData g = new DirGroupsReplyData();
g.groupID = d.GroupID;
if (d.Data.ContainsKey("Name"))
g.groupName = d.Data["Name"];
else
{
m_log.DebugFormat("[Groups]: Key Name not found");
continue;
}
g.groupID = d.GroupID;
g.members = nmembers;
g.members = m_Database.MemberCount(d.GroupID);
groups.Add(g);
}
@ -279,7 +263,7 @@ namespace OpenSim.Groups
if (ownerRole != null)
ownerRoleID = ownerRole.RoleID;
// Check visibility?
// Check visibility?
// When we don't want to check visibility, we pass it "all" as the requestingAgentID
bool checkVisibility = !RequestingAgentID.Equals(UUID.Zero.ToString());
@ -322,21 +306,6 @@ namespace OpenSim.Groups
m.Contribution = Int32.Parse(d.Data["Contribution"]);
m.ListInProfile = d.Data["ListInProfile"] == "1" ? true : false;
GridUserData gud = m_GridUserService.Get(d.PrincipalID);
if (gud != null)
{
if (bool.Parse(gud.Data["Online"]))
{
m.OnlineStatus = @"Online";
}
else
{
int unixtime = int.Parse(gud.Data["Login"]);
// The viewer is very picky about how these strings are formed. Eg. it will crash on malformed dates!
m.OnlineStatus = (unixtime == 0) ? @"unknown" : Util.ToDateTime(unixtime).ToString("MM/dd/yyyy");
}
}
// Is this person an owner of the group?
m.IsOwner = (rolemembershipsList.Find(r => r.RoleID == ownerRoleID) != null) ? true : false;
@ -500,8 +469,8 @@ namespace OpenSim.Groups
// check permissions
bool limited = HasPower(RequestingAgentID, GroupID, GroupPowers.AssignMemberLimited);
bool unlimited = HasPower(RequestingAgentID, GroupID, GroupPowers.AssignMember) || IsOwner(RequestingAgentID, GroupID);
if (!limited && !unlimited)
bool unlimited = HasPower(RequestingAgentID, GroupID, GroupPowers.AssignMember) | IsOwner(RequestingAgentID, GroupID);
if (!limited || !unlimited)
{
m_log.DebugFormat("[Groups]: ({0}) Attempt at assigning {1} to role {2} denied because of lack of permission", RequestingAgentID, AgentID, RoleID);
return false;
@ -511,7 +480,7 @@ namespace OpenSim.Groups
if (!unlimited && limited)
{
// check whether person's has this role
RoleMembershipData rolemembership = m_Database.RetrieveRoleMember(GroupID, RoleID, RequestingAgentID);
RoleMembershipData rolemembership = m_Database.RetrieveRoleMember(GroupID, RoleID, AgentID);
if (rolemembership == null)
{
m_log.DebugFormat("[Groups]: ({0}) Attempt at assigning {1} to role {2} denied because of limited permission", RequestingAgentID, AgentID, RoleID);
@ -531,26 +500,13 @@ namespace OpenSim.Groups
return false;
// check permissions
bool limited = HasPower(RequestingAgentID, GroupID, GroupPowers.AssignMemberLimited);
bool unlimited = HasPower(RequestingAgentID, GroupID, GroupPowers.AssignMember) || IsOwner(RequestingAgentID, GroupID);
if (!limited && !unlimited)
if (!unlimited)
{
m_log.DebugFormat("[Groups]: ({0}) Attempt at removing {1} from role {2} denied because of lack of permission", RequestingAgentID, AgentID, RoleID);
return false;
}
// AssignMemberLimited means that the person can assign another person to the same roles that she has in the group
if (!unlimited && limited)
{
// check whether person's has this role
RoleMembershipData rolemembership = m_Database.RetrieveRoleMember(GroupID, RoleID, RequestingAgentID);
if (rolemembership == null)
{
m_log.DebugFormat("[Groups]: ({0}) Attempt at removing {1} from role {2} denied because of limited permission", RequestingAgentID, AgentID, RoleID);
return false;
}
}
RoleMembershipData rolemember = m_Database.RetrieveRoleMember(GroupID, RoleID, AgentID);
if (rolemember == null)
@ -568,8 +524,8 @@ namespace OpenSim.Groups
{
newRoleID = r.RoleID;
break;
}
}
}
}
MembershipData member = m_Database.RetrieveMember(GroupID, AgentID);
if (member != null)
@ -727,7 +683,7 @@ namespace OpenSim.Groups
m_Database.StoreMember(membership);
}
public bool AddGroupNotice(string RequestingAgentID, UUID groupID, UUID noticeID, string fromName, string subject, string message,
public bool AddGroupNotice(string RequestingAgentID, UUID groupID, UUID noticeID, string fromName, string subject, string message,
bool hasAttachment, byte attType, string attName, UUID attItemID, string attOwnerID)
{
// Check perms
@ -840,7 +796,7 @@ namespace OpenSim.Groups
if (RoleID != UUID.Zero)
_AddAgentToGroupRole(RequestingAgentID, AgentID, GroupID, RoleID);
// Make this the active group
// Make thit this active group
PrincipalData pdata = new PrincipalData();
pdata.PrincipalID = AgentID;
pdata.ActiveGroupID = GroupID;
@ -858,7 +814,7 @@ namespace OpenSim.Groups
return false;
}
if (!add && data == null) // it doesn't exist, can't update
if (!add && data == null) // it deosn't exist, can't update
{
m_log.DebugFormat("[Groups]: Group {0} doesn't exist. Can't update it", groupID);
return false;

View File

@ -1,4 +1,4 @@
/*
/*
* Copyright (c) Contributors, http://opensimulator.org/
* See CONTRIBUTORS.TXT for a full list of copyright holders.
*
@ -38,7 +38,6 @@ namespace OpenSim.Groups
public class GroupsServiceBase : ServiceBase
{
protected IGroupsData m_Database = null;
protected IGridUserData m_GridUserService = null;
public GroupsServiceBase(IConfigSource config, string cName)
: base(config)
@ -46,7 +45,6 @@ namespace OpenSim.Groups
string dllName = String.Empty;
string connString = String.Empty;
string realm = "os_groups";
string usersRealm = "GridUser";
string configName = (cName == string.Empty) ? "Groups" : cName;
//
@ -81,21 +79,6 @@ namespace OpenSim.Groups
m_Database = LoadPlugin<IGroupsData>(dllName, new Object[] { connString, realm });
if (m_Database == null)
throw new Exception("Could not find a storage interface in the given module " + dllName);
//
// [GridUserService] section overrides [DatabaseService], if it exists
//
IConfig usersConfig = config.Configs["GridUserService"];
if (usersConfig != null)
{
dllName = usersConfig.GetString("StorageProvider", dllName);
connString = usersConfig.GetString("ConnectionString", connString);
usersRealm = usersConfig.GetString("Realm", usersRealm);
}
m_GridUserService = LoadPlugin<IGridUserData>(dllName, new Object[] { connString, usersRealm });
if (m_GridUserService == null)
throw new Exception("Could not find a storage inferface for the given users module " + dllName);
}
}
}
}

View File

@ -76,7 +76,7 @@ namespace OpenSim.Groups
// Check if it already exists
GroupData grec = m_Database.RetrieveGroup(groupID);
if (grec == null ||
if (grec == null ||
(grec != null && grec.Data["Location"] != string.Empty && grec.Data["Location"].ToLower() != serviceLocation.ToLower()))
{
// Create the group

View File

@ -114,6 +114,7 @@ namespace OpenSim.OfflineIM
scene.ForEachClient(delegate(IClientAPI client)
{
client.OnRetrieveInstantMessages -= RetrieveInstantMessages;
client.OnMuteListRequest -= OnMuteListRequest;
});
}
@ -161,6 +162,7 @@ namespace OpenSim.OfflineIM
private void OnNewClient(IClientAPI client)
{
client.OnRetrieveInstantMessages += RetrieveInstantMessages;
client.OnMuteListRequest += OnMuteListRequest;
}
private void RetrieveInstantMessages(IClientAPI client)
@ -192,6 +194,20 @@ namespace OpenSim.OfflineIM
}
}
// Apparently this is needed in order for the viewer to request the IMs.
private void OnMuteListRequest(IClientAPI client, uint crc)
{
m_log.DebugFormat("[OfflineIM.V2] Got mute list request for crc {0}", crc);
string filename = "mutes" + client.AgentId.ToString();
IXfer xfer = client.Scene.RequestModuleInterface<IXfer>();
if (xfer != null)
{
xfer.AddNewFile(filename, new Byte[0]);
client.SendMuteListUpdate(filename);
}
}
private void UndeliveredMessage(GridInstantMessage im)
{
if (im.dialog != (byte)InstantMessageDialog.MessageFromObject &&

View File

@ -3,7 +3,7 @@ using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using Mono.Addins;
// General Information about an assembly is controlled through the following
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("OpenSim.Addons.OfflineIM")]
@ -15,8 +15,8 @@ using Mono.Addins;
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
@ -26,11 +26,11 @@ using Mono.Addins;
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Minor Version
// Build Number
// Revision
//
[assembly: AssemblyVersion(OpenSim.VersionInfo.AssemblyVersionNumber)]
[assembly: AssemblyVersion("0.8.1.*")]
[assembly: Addin("OpenSim.OfflineIM", OpenSim.VersionInfo.VersionNumber)]
[assembly: AddinDependency("OpenSim.Region.Framework", OpenSim.VersionInfo.VersionNumber)]
[assembly: Addin("OpenSim.OfflineIM", "0.1")]
[assembly: AddinDependency("OpenSim", "0.5")]

View File

@ -77,7 +77,7 @@ namespace OpenSim.OfflineIM
break;
}
///
m_log.DebugFormat("[OfflineIM.V2.RemoteConnector]: Offline IM server at {0} with auth {1}",
m_log.DebugFormat("[OfflineIM.V2.RemoteConnector]: Offline IM server at {0} with auth {1}",
m_ServerURI, (m_Auth == null ? "None" : m_Auth.GetType().ToString()));
}
@ -140,7 +140,7 @@ namespace OpenSim.OfflineIM
{
Dictionary<string, object> sendData = new Dictionary<string, object>();
sendData["UserID"] = userID;
MakeRequest("DELETE", sendData);
}

View File

@ -90,7 +90,7 @@ namespace OpenSim.OfflineIM
public bool StoreMessage(GridInstantMessage im, out string reason)
{
reason = string.Empty;
// Check limits
UUID principalID = new UUID(im.toAgentID);
long count = m_Database.GetCount("PrincipalID", principalID.ToString());
@ -110,8 +110,9 @@ namespace OpenSim.OfflineIM
{
m_serializer.Serialize(writer, im);
writer.Flush();
imXml = Util.UTF8NoBomEncoding.GetString(mstream.ToArray());
}
imXml = Util.UTF8NoBomEncoding.GetString(mstream.ToArray());
}
OfflineIMData data = new OfflineIMData();

View File

@ -32,17 +32,17 @@ using System.Threading;
using log4net;
using OpenMetaverse;
using OpenSim.Framework;
using OpenSim.Framework.RegionLoader.Filesystem;
using OpenSim.Framework.RegionLoader.Web;
using OpenSim.Region.CoreModules.Agent.AssetTransaction;
using OpenSim.Region.CoreModules.Avatar.InstantMessage;
using OpenSim.Region.CoreModules.Scripting.DynamicTexture;
using OpenSim.Region.CoreModules.Scripting.LoadImageURL;
using OpenSim.Region.CoreModules.Scripting.XMLRPC;
using OpenSim.Services.Interfaces;
using Mono.Addins;
namespace OpenSim.ApplicationPlugins.LoadRegions
{
[Extension(Path="/OpenSim/Startup", Id="LoadRegions", NodeName="Plugin")]
public class LoadRegionsPlugin : IApplicationPlugin, IRegionCreator
{
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
@ -124,7 +124,7 @@ namespace OpenSim.ApplicationPlugins.LoadRegions
m_log.Debug("[LOAD REGIONS PLUGIN]: Creating Region: " + regionsToLoad[i].RegionName + " (ThreadID: " +
Thread.CurrentThread.ManagedThreadId.ToString() +
")");
bool changed = m_openSim.PopulateRegionEstateInfo(regionsToLoad[i]);
m_openSim.CreateRegion(regionsToLoad[i], true, out scene);

View File

@ -27,17 +27,16 @@
using System.Reflection;
using System.Runtime.InteropServices;
using Mono.Addins;
// General information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly : AssemblyTitle("OpenSim.ApplicationPlugins.LoadRegions")]
[assembly : AssemblyTitle("OpenSim.Addin")]
[assembly : AssemblyDescription("")]
[assembly : AssemblyConfiguration("")]
[assembly : AssemblyCompany("http://opensimulator.org")]
[assembly : AssemblyProduct("OpenSim")]
[assembly : AssemblyProduct("OpenSim.Addin")]
[assembly : AssemblyCopyright("Copyright © OpenSimulator.org Developers 2007-2009")]
[assembly : AssemblyTrademark("")]
[assembly : AssemblyCulture("")]
@ -61,8 +60,6 @@ using Mono.Addins;
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("0.7.6.*")]
[assembly : AssemblyVersion(OpenSim.VersionInfo.AssemblyVersionNumber)]
[assembly: Addin("OpenSim.ApplicationPlugins.LoadRegions", OpenSim.VersionInfo.VersionNumber)]
[assembly: AddinDependency("OpenSim", OpenSim.VersionInfo.VersionNumber)]
[assembly : AssemblyVersion("0.8.1.*")]

View File

@ -0,0 +1,11 @@
<Addin id="OpenSim.ApplicationPlugins.LoadRegions" version="0.1">
<Runtime>
<Import assembly="OpenSim.ApplicationPlugins.LoadRegions.dll"/>
</Runtime>
<Dependencies>
<Addin id="OpenSim" version="0.5" />
</Dependencies>
<Extension path = "/OpenSim/Startup">
<Plugin id="LoadRegions" type="OpenSim.ApplicationPlugins.LoadRegions.LoadRegionsPlugin" />
</Extension>
</Addin>

View File

@ -1,9 +1,8 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using Mono.Addins;
// General Information about an assembly is controlled through the following
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("OpenSim.ApplicationPlugins.RegionModulesController")]
@ -15,8 +14,8 @@ using Mono.Addins;
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
@ -26,11 +25,9 @@ using Mono.Addins;
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Minor Version
// Build Number
// Revision
//
[assembly: AssemblyVersion(OpenSim.VersionInfo.AssemblyVersionNumber)]
[assembly: AssemblyVersion("0.8.1.*")]
[assembly: Addin("OpenSim.ApplicationPlugins.RegionModulesController", OpenSim.VersionInfo.VersionNumber)]
[assembly: AddinDependency("OpenSim", OpenSim.VersionInfo.VersionNumber)]

View File

@ -38,7 +38,6 @@ using OpenSim.Region.Framework.Scenes;
namespace OpenSim.ApplicationPlugins.RegionModulesController
{
[Extension(Path = "/OpenSim/Startup", Id = "LoadRegions", NodeName = "Plugin")]
public class RegionModulesControllerPlugin : IRegionModulesController,
IApplicationPlugin
{
@ -75,7 +74,7 @@ namespace OpenSim.ApplicationPlugins.RegionModulesController
}
#region IApplicationPlugin implementation
public void Initialise (OpenSimBase openSim)
{
m_openSim = openSim;
@ -111,7 +110,7 @@ namespace OpenSim.ApplicationPlugins.RegionModulesController
{
m_log.InfoFormat(
"[REGIONMODULES]: From plugin {0}, (version {1}), loaded {2} modules, {3} shared, {4} non-shared {5} unknown",
loadedModuleData.Key.Id,
loadedModuleData.Key.Id,
loadedModuleData.Key.Version,
loadedModuleData.Value[0] + loadedModuleData.Value[1] + loadedModuleData.Value[2],
loadedModuleData.Value[0], loadedModuleData.Value[1], loadedModuleData.Value[2]);
@ -131,9 +130,6 @@ namespace OpenSim.ApplicationPlugins.RegionModulesController
// Read the config again
string moduleString =
modulesConfig.GetString("Setup_" + node.Id, String.Empty);
// Test to see if we want this module
if (moduleString == "disabled")
continue;
// Get the port number, if there is one
if (moduleString != String.Empty)
@ -261,7 +257,7 @@ namespace OpenSim.ApplicationPlugins.RegionModulesController
}
#region Region Module interfacesController implementation
/// <summary>
/// Check that the given module is no disabled in the [Modules] section of the config files.
/// </summary>
@ -293,10 +289,10 @@ namespace OpenSim.ApplicationPlugins.RegionModulesController
if (className != String.Empty &&
node.Type.ToString() != className)
return false;
}
}
return true;
}
}
// The root of all evil.
// This is where we handle adding the modules to scenes when they
@ -368,10 +364,6 @@ namespace OpenSim.ApplicationPlugins.RegionModulesController
string moduleString =
modulesConfig.GetString("Setup_" + node.Id, String.Empty);
// We may not want to load this at all
if (moduleString == "disabled")
continue;
// Get the port number, if there is one
if (moduleString != String.Empty)
{
@ -509,8 +501,6 @@ namespace OpenSim.ApplicationPlugins.RegionModulesController
{
module.RegionLoaded(scene);
}
scene.AllModulesLoaded();
}
public void RemoveRegionFromModules (Scene scene)

View File

@ -0,0 +1,13 @@
<Addin id="OpenSim.ApplicationPlugins.RegionModulesController" version="0.1">
<Runtime>
<Import assembly="OpenSim.ApplicationPlugins.RegionModulesController.dll"/>
</Runtime>
<Dependencies>
<Addin id="OpenSim" version="0.5" />
</Dependencies>
<Extension path = "/OpenSim/Startup">
<Plugin id="RegionModulesController" type="OpenSim.ApplicationPlugins.RegionModulesController.RegionModulesControllerPlugin" />
</Extension>
</Addin>

View File

@ -1,9 +1,8 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using Mono.Addins;
// General Information about an assembly is controlled through the following
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("OpenSim.ApplicationPlugins.RemoteController")]
@ -15,8 +14,8 @@ using Mono.Addins;
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
@ -26,11 +25,9 @@ using Mono.Addins;
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Minor Version
// Build Number
// Revision
//
[assembly: AssemblyVersion(OpenSim.VersionInfo.AssemblyVersionNumber)]
[assembly: AssemblyVersion("0.8.1.*")]
[assembly: Addin("OpenSim.ApplicationPlugins.RemoteController", OpenSim.VersionInfo.VersionNumber)]
[assembly: AddinDependency("OpenSim", OpenSim.VersionInfo.VersionNumber)]

View File

@ -39,9 +39,9 @@ using log4net;
using Nini.Config;
using Nwc.XmlRpc;
using OpenMetaverse;
using Mono.Addins;
using OpenSim;
using OpenSim.Framework;
using OpenSim.Framework.Communications;
using OpenSim.Framework.Console;
using OpenSim.Framework.Servers;
using OpenSim.Framework.Servers.HttpServer;
@ -56,7 +56,6 @@ using RegionInfo = OpenSim.Framework.RegionInfo;
namespace OpenSim.ApplicationPlugins.RemoteController
{
[Extension(Path = "/OpenSim/Startup", Id = "LoadRegions", NodeName = "Plugin")]
public class RemoteAdminPlugin : IApplicationPlugin
{
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
@ -74,7 +73,6 @@ namespace OpenSim.ApplicationPlugins.RemoteController
private string m_name = "RemoteAdminPlugin";
private string m_version = "0.0";
private string m_openSimVersion;
public string Version
{
@ -94,8 +92,6 @@ namespace OpenSim.ApplicationPlugins.RemoteController
public void Initialise(OpenSimBase openSim)
{
m_openSimVersion = openSim.GetVersionText();
m_configSource = openSim.ConfigSource.Source;
try
{
@ -138,13 +134,10 @@ namespace OpenSim.ApplicationPlugins.RemoteController
availableMethods["admin_region_query"] = (req, ep) => InvokeXmlRpcMethod(req, ep, XmlRpcRegionQueryMethod);
availableMethods["admin_shutdown"] = (req, ep) => InvokeXmlRpcMethod(req, ep, XmlRpcShutdownMethod);
availableMethods["admin_broadcast"] = (req, ep) => InvokeXmlRpcMethod(req, ep, XmlRpcAlertMethod);
availableMethods["admin_dialog"] = (req, ep) => InvokeXmlRpcMethod(req, ep, XmlRpcDialogMethod);
availableMethods["admin_restart"] = (req, ep) => InvokeXmlRpcMethod(req, ep, XmlRpcRestartMethod);
availableMethods["admin_load_heightmap"] = (req, ep) => InvokeXmlRpcMethod(req, ep, XmlRpcLoadHeightmapMethod);
availableMethods["admin_save_heightmap"] = (req, ep) => InvokeXmlRpcMethod(req, ep, XmlRpcSaveHeightmapMethod);
availableMethods["admin_reset_land"] = (req, ep) => InvokeXmlRpcMethod(req, ep, XmlRpcResetLand);
// Agent management
availableMethods["admin_get_agents"] = (req, ep) => InvokeXmlRpcMethod(req, ep, XmlRpcGetAgentsMethod);
availableMethods["admin_teleport_agent"] = (req, ep) => InvokeXmlRpcMethod(req, ep, XmlRpcTeleportAgentMethod);
@ -169,11 +162,8 @@ namespace OpenSim.ApplicationPlugins.RemoteController
availableMethods["admin_acl_list"] = (req, ep) => InvokeXmlRpcMethod(req, ep, XmlRpcAccessListList);
availableMethods["admin_estate_reload"] = (req, ep) => InvokeXmlRpcMethod(req, ep, XmlRpcEstateReload);
// Misc
availableMethods["admin_refresh_search"] = (req, ep) => InvokeXmlRpcMethod(req, ep, XmlRpcRefreshSearch);
availableMethods["admin_refresh_map"] = (req, ep) => InvokeXmlRpcMethod(req, ep, XmlRpcRefreshMap);
availableMethods["admin_get_opensim_version"] = (req, ep) => InvokeXmlRpcMethod(req, ep, XmlRpcGetOpenSimVersion);
availableMethods["admin_get_agent_count"] = (req, ep) => InvokeXmlRpcMethod(req, ep, XmlRpcGetAgentCount);
// Land management
availableMethods["admin_reset_land"] = (req, ep) => InvokeXmlRpcMethod(req, ep, XmlRpcResetLand);
// Either enable full remote functionality or just selected features
string enabledMethods = m_config.GetString("enabled_methods", "all");
@ -274,148 +264,32 @@ namespace OpenSim.ApplicationPlugins.RemoteController
try
{
m_log.Info("[RADMIN]: Request to restart Region.");
CheckRegionParams(requestData, responseData);
Scene rebootedScene = null;
bool restartAll = false;
IConfig startupConfig = m_configSource.Configs["Startup"];
if (startupConfig != null)
{
if (startupConfig.GetBoolean("InworldRestartShutsDown", false))
{
rebootedScene = m_application.SceneManager.CurrentOrFirstScene;
restartAll = true;
}
}
if (rebootedScene == null)
{
CheckRegionParams(requestData, responseData);
GetSceneFromRegionParams(requestData, responseData, out rebootedScene);
}
IRestartModule restartModule = rebootedScene.RequestModuleInterface<IRestartModule>();
GetSceneFromRegionParams(requestData, responseData, out rebootedScene);
responseData["success"] = false;
responseData["accepted"] = true;
responseData["rebooting"] = true;
string message;
List<int> times = new List<int>();
if (requestData.ContainsKey("alerts"))
IRestartModule restartModule = rebootedScene.RequestModuleInterface<IRestartModule>();
if (restartModule != null)
{
string[] alertTimes = requestData["alerts"].ToString().Split( new char[] {','});
if (alertTimes.Length == 1 && Convert.ToInt32(alertTimes[0]) == -1)
{
m_log.Info("[RADMIN]: Request to cancel restart.");
List<int> times = new List<int> { 30, 15 };
if (restartModule != null)
{
message = "Restart has been cancelled";
if (requestData.ContainsKey("message"))
message = requestData["message"].ToString();
restartModule.AbortRestart(message);
responseData["success"] = true;
responseData["rebooting"] = false;
return;
}
}
foreach (string a in alertTimes)
times.Add(Convert.ToInt32(a));
restartModule.ScheduleRestart(UUID.Zero, "Region will restart in {0}", times.ToArray(), true);
responseData["success"] = true;
}
else
{
int timeout = 30;
if (requestData.ContainsKey("milliseconds"))
timeout = Int32.Parse(requestData["milliseconds"].ToString()) / 1000;
while (timeout > 0)
{
times.Add(timeout);
if (timeout > 300)
timeout -= 120;
else if (timeout > 30)
timeout -= 30;
else
timeout -= 15;
}
}
m_log.Info("[RADMIN]: Request to restart Region.");
message = "Region is restarting in {0}. Please save what you are doing and log out.";
if (requestData.ContainsKey("message"))
message = requestData["message"].ToString();
bool notice = true;
if (requestData.ContainsKey("noticetype")
&& ((string)requestData["noticetype"] == "dialog"))
{
notice = false;
}
if (startupConfig.GetBoolean("SkipDelayOnEmptyRegion", false))
{
m_log.Info("[RADMIN]: Counting affected avatars");
int agents = 0;
if (restartAll)
{
foreach (Scene s in m_application.SceneManager.Scenes)
{
foreach (ScenePresence sp in s.GetScenePresences())
{
if (!sp.IsChildAgent && !sp.IsNPC)
agents++;
}
}
}
else
{
foreach (ScenePresence sp in rebootedScene.GetScenePresences())
{
if (!sp.IsChildAgent && !sp.IsNPC)
agents++;
}
}
m_log.InfoFormat("[RADMIN]: Avatars in region: {0}", agents);
if (agents == 0)
{
m_log.Info("[RADMIN]: No avatars detected, shutting down without delay");
times.Clear();
times.Add(0);
}
}
List<Scene> restartList;
if (restartAll)
restartList = m_application.SceneManager.Scenes;
else
restartList = new List<Scene>() { rebootedScene };
foreach (Scene s in m_application.SceneManager.Scenes)
{
restartModule = s.RequestModuleInterface<IRestartModule>();
if (restartModule != null)
restartModule.ScheduleRestart(UUID.Zero, message, times.ToArray(), notice);
}
responseData["success"] = true;
}
catch (Exception e)
{
m_log.ErrorFormat("[RADMIN]: Restart region: failed: {0} {1}", e.Message, e.StackTrace);
// m_log.ErrorFormat("[RADMIN]: Restart region: failed: {0} {1}", e.Message, e.StackTrace);
responseData["rebooting"] = false;
throw;
throw e;
}
m_log.Info("[RADMIN]: Restart Region request complete");
@ -445,32 +319,6 @@ namespace OpenSim.ApplicationPlugins.RemoteController
m_log.Info("[RADMIN]: Alert request complete");
}
public void XmlRpcDialogMethod(XmlRpcRequest request, XmlRpcResponse response, IPEndPoint remoteClient)
{
Hashtable responseData = (Hashtable)response.Value;
m_log.Info("[RADMIN]: Dialog request started");
Hashtable requestData = (Hashtable)request.Params[0];
string message = (string)requestData["message"];
string fromuuid = (string)requestData["from"];
m_log.InfoFormat("[RADMIN]: Broadcasting: {0}", message);
responseData["accepted"] = true;
responseData["success"] = true;
m_application.SceneManager.ForEachScene(
delegate(Scene scene)
{
IDialogModule dialogModule = scene.RequestModuleInterface<IDialogModule>();
if (dialogModule != null)
dialogModule.SendNotificationToUsersInRegion(UUID.Zero, fromuuid, message);
});
m_log.Info("[RADMIN]: Dialog request complete");
}
private void XmlRpcLoadHeightmapMethod(XmlRpcRequest request, XmlRpcResponse response, IPEndPoint remoteClient)
{
m_log.Info("[RADMIN]: Load height maps request started");
@ -574,32 +422,13 @@ namespace OpenSim.ApplicationPlugins.RemoteController
message = "Region is going down now.";
}
if (requestData.ContainsKey("noticetype")
&& ((string) requestData["noticetype"] == "dialog"))
{
m_application.SceneManager.ForEachScene(
m_application.SceneManager.ForEachScene(
delegate(Scene scene)
{
IDialogModule dialogModule = scene.RequestModuleInterface<IDialogModule>();
if (dialogModule != null)
dialogModule.SendNotificationToUsersInRegion(UUID.Zero, "System", message);
});
}
else
{
if (!requestData.ContainsKey("noticetype")
|| ((string)requestData["noticetype"] != "none"))
{
m_application.SceneManager.ForEachScene(
delegate(Scene scene)
{
IDialogModule dialogModule = scene.RequestModuleInterface<IDialogModule>();
if (dialogModule != null)
dialogModule.SendGeneralAlert(message);
});
}
}
// Perform shutdown
System.Timers.Timer shutdownTimer = new System.Timers.Timer(timeout); // Wait before firing
@ -611,7 +440,7 @@ namespace OpenSim.ApplicationPlugins.RemoteController
}
responseData["success"] = true;
m_log.Info("[RADMIN]: Shutdown Administrator Request complete");
}
@ -783,9 +612,9 @@ namespace OpenSim.ApplicationPlugins.RemoteController
{
// No INI setting recorded.
}
string regionIniPath;
if (requestData.Contains("region_file"))
{
// Make sure that the file to be created is in a subdirectory of the region storage directory.
@ -809,7 +638,7 @@ namespace OpenSim.ApplicationPlugins.RemoteController
region.RegionName.Replace(" ", "_").Replace(":", "_").
Replace("/", "_")));
}
m_log.DebugFormat("[RADMIN] CreateRegion: persisting region {0} to {1}",
region.RegionID, regionIniPath);
region.SaveRegionToFile("dynamic region", regionIniPath);
@ -818,9 +647,9 @@ namespace OpenSim.ApplicationPlugins.RemoteController
{
region.Persistent = false;
}
// Set the estate
// Check for an existing estate
List<int> estateIDs = m_application.EstateDataService.GetEstates((string) requestData["estate_name"]);
if (estateIDs.Count < 1)
@ -831,12 +660,12 @@ namespace OpenSim.ApplicationPlugins.RemoteController
// ok, client wants us to use an explicit UUID
// regardless of what the avatar name provided
userID = new UUID((string) requestData["estate_owner_uuid"]);
// Check that the specified user exists
Scene currentOrFirst = m_application.SceneManager.CurrentOrFirstScene;
IUserAccountService accountService = currentOrFirst.UserAccountService;
UserAccount user = accountService.GetUserAccount(currentOrFirst.RegionInfo.ScopeID, userID);
if (user == null)
throw new Exception("Specified user was not found.");
}
@ -845,23 +674,23 @@ namespace OpenSim.ApplicationPlugins.RemoteController
// We need to look up the UUID for the avatar with the provided name.
string ownerFirst = (string) requestData["estate_owner_first"];
string ownerLast = (string) requestData["estate_owner_last"];
Scene currentOrFirst = m_application.SceneManager.CurrentOrFirstScene;
IUserAccountService accountService = currentOrFirst.UserAccountService;
UserAccount user = accountService.GetUserAccount(currentOrFirst.RegionInfo.ScopeID,
ownerFirst, ownerLast);
// Check that the specified user exists
if (user == null)
throw new Exception("Specified user was not found.");
userID = user.PrincipalID;
}
else
{
throw new Exception("Estate owner details not provided.");
}
// Create a new estate with the name provided
region.EstateSettings = m_application.EstateDataService.CreateNewEstate();
@ -888,7 +717,7 @@ namespace OpenSim.ApplicationPlugins.RemoteController
throw new Exception("Failed to join estate.");
}
}
// Create the region and perform any initial initialization
IScene newScene;
@ -1195,7 +1024,7 @@ namespace OpenSim.ApplicationPlugins.RemoteController
// Set home position
GridRegion home = scene.GridService.GetRegionByPosition(scopeID,
GridRegion home = scene.GridService.GetRegionByPosition(scopeID,
(int)Util.RegionToWorldLoc(regionXLocation), (int)Util.RegionToWorldLoc(regionYLocation));
if (null == home)
{
@ -1425,7 +1254,7 @@ namespace OpenSim.ApplicationPlugins.RemoteController
if ((null != regionXLocation) && (null != regionYLocation))
{
GridRegion home = scene.GridService.GetRegionByPosition(scopeID,
GridRegion home = scene.GridService.GetRegionByPosition(scopeID,
(int)Util.RegionToWorldLoc((uint)regionXLocation), (int)Util.RegionToWorldLoc((uint)regionYLocation));
if (null == home) {
m_log.WarnFormat("[RADMIN]: Unable to set home region for updated user account {0} {1}", firstName, lastName);
@ -1452,7 +1281,7 @@ namespace OpenSim.ApplicationPlugins.RemoteController
throw e;
}
m_log.Info("[RADMIN]: UpdateUserAccount: request complete");
}
}
@ -1644,7 +1473,7 @@ namespace OpenSim.ApplicationPlugins.RemoteController
GetSceneFromRegionParams(requestData, responseData, out scene);
string filename = (string) requestData["filename"];
bool mergeOar = false;
bool skipAssets = false;
@ -1658,7 +1487,7 @@ namespace OpenSim.ApplicationPlugins.RemoteController
}
IRegionArchiverModule archiver = scene.RequestModuleInterface<IRegionArchiverModule>();
Dictionary<string, object> archiveOptions = new Dictionary<string, object>();
Dictionary<string, object> archiveOptions = new Dictionary<string,object>();
if (mergeOar) archiveOptions.Add("merge", null);
if (skipAssets) archiveOptions.Add("skipAssets", null);
if (archiver != null)
@ -1771,7 +1600,7 @@ namespace OpenSim.ApplicationPlugins.RemoteController
scene.EventManager.OnOarFileSaved += RemoteAdminOarSaveCompleted;
m_log.InfoFormat(
"[RADMIN]: Submitting save OAR request for {0} to file {1}, request ID {2}",
"[RADMIN]: Submitting save OAR request for {0} to file {1}, request ID {2}",
scene.Name, filename, requestId);
archiver.ArchiveRegion(filename, requestId, options);
@ -1918,31 +1747,21 @@ namespace OpenSim.ApplicationPlugins.RemoteController
private void XmlRpcRegionQueryMethod(XmlRpcRequest request, XmlRpcResponse response, IPEndPoint remoteClient)
{
m_log.Info("[RADMIN]: Received Query XML Administrator Request");
Hashtable responseData = (Hashtable)response.Value;
Hashtable requestData = (Hashtable)request.Params[0];
int flags = 0;
string text = String.Empty;
int health = 0;
responseData["success"] = true;
CheckRegionParams(requestData, responseData);
Scene scene = null;
try
{
GetSceneFromRegionParams(requestData, responseData, out scene);
health = scene.GetHealth(out flags, out text);
}
catch
{
responseData["error"] = null;
}
GetSceneFromRegionParams(requestData, responseData, out scene);
int health = scene.GetHealth();
responseData["health"] = health;
responseData["success"] = true;
responseData["health"] = health;
responseData["flags"] = flags;
responseData["message"] = text;
m_log.Info("[RADMIN]: Query XML Administrator Request complete");
}
private void XmlRpcConsoleCommandMethod(XmlRpcRequest request, XmlRpcResponse response, IPEndPoint remoteClient)
@ -2118,8 +1937,8 @@ namespace OpenSim.ApplicationPlugins.RemoteController
Hashtable responseData = (Hashtable)response.Value;
// Hashtable requestData = (Hashtable)request.Params[0];
m_application.SceneManager.ForEachScene(s =>
s.RegionInfo.EstateSettings = m_application.EstateDataService.LoadEstateSettings(s.RegionInfo.RegionID, false)
m_application.SceneManager.ForEachScene(s =>
s.RegionInfo.EstateSettings = m_application.EstateDataService.LoadEstateSettings(s.RegionInfo.RegionID, false)
);
responseData["success"] = true;
@ -2251,6 +2070,7 @@ namespace OpenSim.ApplicationPlugins.RemoteController
{
Hashtable requestData = (Hashtable)request.Params[0];
Hashtable responseData = (Hashtable)response.Value;
string musicURL = string.Empty;
UUID groupID = UUID.Zero;
uint flags = 0;
@ -2260,129 +2080,41 @@ namespace OpenSim.ApplicationPlugins.RemoteController
set_group = UUID.TryParse(requestData["group"].ToString(), out groupID);
if (requestData.Contains("music") && requestData["music"] != null)
{
musicURL = requestData["music"].ToString();
set_music = true;
}
if (requestData.Contains("flags") && requestData["flags"] != null)
set_flags = UInt32.TryParse(requestData["flags"].ToString(), out flags);
m_log.InfoFormat("[RADMIN]: Received Reset Land Request group={0} musicURL={1} flags={2}",
(set_group ? groupID.ToString() : "unchanged"),
(set_music ? musicURL : "unchanged"),
m_log.InfoFormat("[RADMIN]: Received Reset Land Request group={0} musicURL={1} flags={2}",
(set_group ? groupID.ToString() : "unchanged"),
(set_music ? musicURL : "unchanged"),
(set_flags ? flags.ToString() : "unchanged"));
m_application.SceneManager.ForEachScene(delegate (Scene s)
m_application.SceneManager.ForEachScene(delegate(Scene s)
{
List<ILandObject> parcels = s.LandChannel.AllParcels();
foreach (ILandObject p in parcels)
{
if (set_music)
p.LandData.MusicURL = musicURL;
if (set_group)
p.LandData.GroupID = groupID;
if (set_flags)
p.LandData.Flags = flags;
s.LandChannel.UpdateLandObject(p.LandData.LocalID, p.LandData);
}
}
);
responseData["success"] = true;
m_log.Info("[RADMIN]: Reset Land Request complete");
}
private void XmlRpcRefreshSearch(XmlRpcRequest request, XmlRpcResponse response, IPEndPoint remoteClient)
{
m_log.Info("[RADMIN]: Received Refresh Search Request");
Hashtable responseData = (Hashtable)response.Value;
Hashtable requestData = (Hashtable)request.Params[0];
CheckRegionParams(requestData, responseData);
Scene scene = null;
GetSceneFromRegionParams(requestData, responseData, out scene);
ISearchModule searchModule = scene.RequestModuleInterface<ISearchModule>();
if (searchModule != null)
{
searchModule.Refresh();
responseData["success"] = true;
}
else
{
responseData["success"] = false;
}
m_log.Info("[RADMIN]: Refresh Search Request complete");
}
private void XmlRpcRefreshMap(XmlRpcRequest request, XmlRpcResponse response, IPEndPoint remoteClient)
{
m_log.Info("[RADMIN]: Received Refresh Map Request");
Hashtable responseData = (Hashtable)response.Value;
Hashtable requestData = (Hashtable)request.Params[0];
CheckRegionParams(requestData, responseData);
Scene scene = null;
GetSceneFromRegionParams(requestData, responseData, out scene);
IMapImageUploadModule mapTileModule = scene.RequestModuleInterface<IMapImageUploadModule>();
if (mapTileModule != null)
{
Util.FireAndForget((x) =>
{
mapTileModule.UploadMapTile(scene);
});
responseData["success"] = true;
}
else
{
responseData["success"] = false;
}
m_log.Info("[RADMIN]: Refresh Map Request complete");
}
private void XmlRpcGetOpenSimVersion(XmlRpcRequest request, XmlRpcResponse response, IPEndPoint remoteClient)
{
m_log.Info("[RADMIN]: Received Get OpenSim Version Request");
Hashtable responseData = (Hashtable)response.Value;
responseData["version"] = m_openSimVersion;
responseData["success"] = true;
m_log.Info("[RADMIN]: Get OpenSim Version Request complete");
}
private void XmlRpcGetAgentCount(XmlRpcRequest request, XmlRpcResponse response, IPEndPoint remoteClient)
{
m_log.Info("[RADMIN]: Received Get Agent Count Request");
Hashtable responseData = (Hashtable)response.Value;
Hashtable requestData = (Hashtable)request.Params[0];
CheckRegionParams(requestData, responseData);
Scene scene = null;
GetSceneFromRegionParams(requestData, responseData, out scene);
if (scene == null)
{
responseData["success"] = false;
}
else
{
responseData["count"] = scene.GetRootAgentCount();
responseData["success"] = true;
}
m_log.Info("[RADMIN]: Get Agent Count Request complete");
}
/// <summary>
/// Parse a float with the given parameter name from a request data hash table.
@ -2805,8 +2537,8 @@ namespace OpenSim.ApplicationPlugins.RemoteController
try
{
Dictionary<UUID,UUID> inventoryMap = new Dictionary<UUID,UUID>();
CopyInventoryFolders(destination, source, FolderType.Clothing, inventoryMap, avatarAppearance);
CopyInventoryFolders(destination, source, FolderType.BodyPart, inventoryMap, avatarAppearance);
CopyInventoryFolders(destination, source, AssetType.Clothing, inventoryMap, avatarAppearance);
CopyInventoryFolders(destination, source, AssetType.Bodypart, inventoryMap, avatarAppearance);
AvatarWearable[] wearables = avatarAppearance.Wearables;
@ -2842,20 +2574,20 @@ namespace OpenSim.ApplicationPlugins.RemoteController
IInventoryService inventoryService = m_application.SceneManager.CurrentOrFirstScene.InventoryService;
// Get Clothing folder of receiver
InventoryFolderBase destinationFolder = inventoryService.GetFolderForType(destination, FolderType.Clothing);
InventoryFolderBase destinationFolder = inventoryService.GetFolderForType(destination, AssetType.Clothing);
if (destinationFolder == null)
throw new Exception("Cannot locate folder(s)");
// Missing destination folder? This should *never* be the case
if (destinationFolder.Type != (short)FolderType.Clothing)
if (destinationFolder.Type != (short)AssetType.Clothing)
{
destinationFolder = new InventoryFolderBase();
destinationFolder.ID = UUID.Random();
destinationFolder.Name = "Clothing";
destinationFolder.Owner = destination;
destinationFolder.Type = (short)FolderType.Clothing;
destinationFolder.Type = (short)AssetType.Clothing;
destinationFolder.ParentID = inventoryService.GetRootFolder(destination).ID;
destinationFolder.Version = 1;
inventoryService.AddFolder(destinationFolder); // store base record
@ -2872,7 +2604,8 @@ namespace OpenSim.ApplicationPlugins.RemoteController
if (wearable[0].ItemID != UUID.Zero)
{
// Get inventory item and copy it
InventoryItemBase item = inventoryService.GetItem(source, wearable[0].ItemID);
InventoryItemBase item = new InventoryItemBase(wearable[0].ItemID, source);
item = inventoryService.GetItem(item);
if (item != null)
{
@ -2925,7 +2658,8 @@ namespace OpenSim.ApplicationPlugins.RemoteController
if (itemID != UUID.Zero)
{
// Get inventory item and copy it
InventoryItemBase item = inventoryService.GetItem(source, itemID);
InventoryItemBase item = new InventoryItemBase(itemID, source);
item = inventoryService.GetItem(item);
if (item != null)
{
@ -2971,7 +2705,7 @@ namespace OpenSim.ApplicationPlugins.RemoteController
/// This method is called by establishAppearance to copy inventory folders to make
/// copies of Clothing and Bodyparts inventory folders and attaches worn attachments
/// </summary>
private void CopyInventoryFolders(UUID destination, UUID source, FolderType assetType, Dictionary<UUID, UUID> inventoryMap,
private void CopyInventoryFolders(UUID destination, UUID source, AssetType assetType, Dictionary<UUID,UUID> inventoryMap,
AvatarAppearance avatarAppearance)
{
IInventoryService inventoryService = m_application.SceneManager.CurrentOrFirstScene.InventoryService;
@ -2987,12 +2721,9 @@ namespace OpenSim.ApplicationPlugins.RemoteController
{
sourceFolder = new InventoryFolderBase();
sourceFolder.ID = UUID.Random();
if (assetType == FolderType.Clothing)
{
if (assetType == AssetType.Clothing) {
sourceFolder.Name = "Clothing";
}
else
{
} else {
sourceFolder.Name = "Body Parts";
}
sourceFolder.Owner = source;
@ -3008,7 +2739,7 @@ namespace OpenSim.ApplicationPlugins.RemoteController
{
destinationFolder = new InventoryFolderBase();
destinationFolder.ID = UUID.Random();
if (assetType == FolderType.Clothing)
if (assetType == AssetType.Clothing)
{
destinationFolder.Name = "Clothing";
}
@ -3204,7 +2935,7 @@ namespace OpenSim.ApplicationPlugins.RemoteController
// Set home position
GridRegion home = scene.GridService.GetRegionByPosition(scopeID,
GridRegion home = scene.GridService.GetRegionByPosition(scopeID,
(int)Util.RegionToWorldLoc(regionXLocation), (int)Util.RegionToWorldLoc(regionYLocation));
if (null == home) {
m_log.WarnFormat("[RADMIN]: Unable to set home region for newly created user account {0} {1}", names[0], names[1]);
@ -3247,16 +2978,16 @@ namespace OpenSim.ApplicationPlugins.RemoteController
// m_log.DebugFormat("[RADMIN] {0} folders, {1} items in inventory",
// uic.folders.Count, uic.items.Count);
InventoryFolderBase clothingFolder = inventoryService.GetFolderForType(ID, FolderType.Clothing);
InventoryFolderBase clothingFolder = inventoryService.GetFolderForType(ID, AssetType.Clothing);
// This should *never* be the case
if (clothingFolder == null || clothingFolder.Type != (short)FolderType.Clothing)
if (clothingFolder == null || clothingFolder.Type != (short)AssetType.Clothing)
{
clothingFolder = new InventoryFolderBase();
clothingFolder.ID = UUID.Random();
clothingFolder.Name = "Clothing";
clothingFolder.Owner = ID;
clothingFolder.Type = (short)FolderType.Clothing;
clothingFolder.Type = (short)AssetType.Clothing;
clothingFolder.ParentID = inventoryService.GetRootFolder(ID).ID;
clothingFolder.Version = 1;
inventoryService.AddFolder(clothingFolder); // store base record
@ -3302,7 +3033,7 @@ namespace OpenSim.ApplicationPlugins.RemoteController
extraFolder.ID = UUID.Random();
extraFolder.Name = outfitName;
extraFolder.Owner = ID;
extraFolder.Type = (short)FolderType.Clothing;
extraFolder.Type = (short)AssetType.Clothing;
extraFolder.Version = 1;
extraFolder.ParentID = clothingFolder.ID;
inventoryService.AddFolder(extraFolder);

View File

@ -0,0 +1,11 @@
<Addin id="OpenSim.ApplicationPlugins.RemoteController" version="0.1">
<Runtime>
<Import assembly="OpenSim.ApplicationPlugins.RemoteController.dll"/>
</Runtime>
<Dependencies>
<Addin id="OpenSim" version="0.5" />
</Dependencies>
<Extension path = "/OpenSim/Startup">
<Plugin id="RemoteController" type="OpenSim.ApplicationPlugins.RemoteController.RemoteAdminPlugin" />
</Extension>
</Addin>

View File

@ -28,10 +28,8 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Concurrent;
using System.IO;
using System.Reflection;
using System.Threading;
using log4net;
using Nini.Config;
using OpenMetaverse;
@ -50,9 +48,9 @@ namespace OpenSim.Framework.Capabilities
/// </summary>
public delegate IClientAPI GetClientDelegate(UUID agentID);
public class Caps : IDisposable
public class Caps
{
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private string m_httpListenerHostName;
private uint m_httpListenPort;
@ -65,15 +63,14 @@ namespace OpenSim.Framework.Capabilities
private CapsHandlers m_capsHandlers;
private ConcurrentDictionary<string, PollServiceEventArgs> m_pollServiceHandlers
= new ConcurrentDictionary<string, PollServiceEventArgs>();
private Dictionary<string, PollServiceEventArgs> m_pollServiceHandlers
= new Dictionary<string, PollServiceEventArgs>();
private Dictionary<string, string> m_externalCapsHandlers = new Dictionary<string, string>();
private IHttpServer m_httpListener;
private UUID m_agentID;
private string m_regionName;
private ManualResetEvent m_capsActive = new ManualResetEvent(false);
public UUID AgentID
{
@ -120,19 +117,6 @@ namespace OpenSim.Framework.Capabilities
get { return m_externalCapsHandlers; }
}
[Flags]
public enum CapsFlags:uint
{
None = 0,
SentSeeds = 1,
ObjectAnim = 0x100,
WLEnv = 0x200,
AdvEnv = 0x400
}
public CapsFlags Flags { get; set;}
public Caps(IHttpServer httpServer, string httpListen, uint httpPort, string capsPath,
UUID agent, string regionName)
{
@ -150,37 +134,8 @@ namespace OpenSim.Framework.Capabilities
}
m_agentID = agent;
m_capsHandlers = new CapsHandlers(httpServer, httpListen, httpPort);
m_capsHandlers = new CapsHandlers(httpServer, httpListen, httpPort, (httpServer == null) ? false : httpServer.UseSSL);
m_regionName = regionName;
Flags = CapsFlags.None;
m_capsActive.Reset();
}
~Caps()
{
Flags = CapsFlags.None;
if (m_capsActive!= null)
{
m_capsActive.Dispose();
m_capsActive = null;
}
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
public void Dispose(bool disposing)
{
Flags = CapsFlags.None;
if (m_capsActive != null)
{
DeregisterHandlers();
m_capsActive.Dispose();
m_capsActive = null;
}
}
/// <summary>
@ -194,32 +149,20 @@ namespace OpenSim.Framework.Capabilities
m_capsHandlers[capName] = handler;
}
public void RegisterSimpleHandler(string capName, ISimpleStreamHandler handler, bool addToListener = true)
{
//m_log.DebugFormat("[CAPS]: Registering handler for \"{0}\": path {1}", capName, handler.Path);
m_capsHandlers.AddSimpleHandler(capName, handler, addToListener);
}
public void RegisterPollHandler(string capName, PollServiceEventArgs pollServiceHandler)
{
// m_log.DebugFormat(
// "[CAPS]: Registering handler with name {0}, url {1} for {2}",
// "[CAPS]: Registering handler with name {0}, url {1} for {2}",
// capName, pollServiceHandler.Url, m_agentID, m_regionName);
if(!m_pollServiceHandlers.TryAdd(capName, pollServiceHandler))
{
m_log.ErrorFormat(
"[CAPS]: Handler with name {0} already registered (ulr {1}, agent {2}, region {3}",
capName, pollServiceHandler.Url, m_agentID, m_regionName);
return;
}
m_pollServiceHandlers.Add(capName, pollServiceHandler);
m_httpListener.AddPollServiceHTTPHandler(pollServiceHandler);
m_httpListener.AddPollServiceHTTPHandler(pollServiceHandler.Url, pollServiceHandler);
// uint port = (MainServer.Instance == null) ? 0 : MainServer.Instance.Port;
// string protocol = "http";
// string hostName = m_httpListenerHostName;
//
//
// if (MainServer.Instance.UseSSL)
// {
// hostName = MainServer.Instance.SSLCommonName;
@ -254,9 +197,8 @@ namespace OpenSim.Framework.Capabilities
foreach (PollServiceEventArgs handler in m_pollServiceHandlers.Values)
{
m_httpListener.RemovePollServiceHTTPHandler(handler.Url);
m_httpListener.RemovePollServiceHTTPHandler("", handler.Url);
}
m_pollServiceHandlers.Clear();
}
public bool TryGetPollHandler(string name, out PollServiceEventArgs pollHandler)
@ -288,13 +230,16 @@ namespace OpenSim.Framework.Capabilities
string hostName = m_httpListenerHostName;
uint port = (MainServer.Instance == null) ? 0 : MainServer.Instance.Port;
string protocol = "http";
if (MainServer.Instance.UseSSL)
{
hostName = MainServer.Instance.SSLCommonName;
port = MainServer.Instance.SSLPort;
protocol = "https";
}
//
// caps.RegisterHandler("FetchInventoryDescendents2", String.Format("{0}://{1}:{2}{3}", protocol, hostName, port, capUrl));
caps[kvp.Key] = string.Format("{0}://{1}:{2}{3}", protocol, hostName, port, kvp.Value.Url);
}
}
@ -308,19 +253,7 @@ namespace OpenSim.Framework.Capabilities
caps[kvp.Key] = kvp.Value;
}
return caps;
}
public void Activate()
{
m_capsActive.Set();
}
public bool WaitForActivation()
{
// Wait for 30s. If that elapses, return false and run without caps
return m_capsActive.WaitOne(120000);
}
}
}

View File

@ -27,7 +27,6 @@
using System.Collections;
using System.Collections.Generic;
using System.Collections.Concurrent;
using OpenSim.Framework.Servers;
using OpenSim.Framework.Servers.HttpServer;
@ -41,7 +40,6 @@ namespace OpenSim.Framework.Capabilities
public class CapsHandlers
{
private Dictionary<string, IRequestHandler> m_capsHandlers = new Dictionary<string, IRequestHandler>();
private ConcurrentDictionary<string, ISimpleStreamHandler> m_capsSimpleHandlers = new ConcurrentDictionary<string, ISimpleStreamHandler>();
private IHttpServer m_httpListener;
private string m_httpListenerHostName;
private uint m_httpListenerPort;
@ -55,15 +53,31 @@ namespace OpenSim.Framework.Capabilities
/// <param name="httpListener">base HTTP server</param>
/// <param name="httpListenerHostname">host name of the HTTP server</param>
/// <param name="httpListenerPort">HTTP port</param>
public CapsHandlers(IHttpServer httpListener, string httpListenerHostname, uint httpListenerPort)
{
public CapsHandlers(BaseHttpServer httpListener, string httpListenerHostname, uint httpListenerPort)
: this(httpListener,httpListenerHostname,httpListenerPort, false)
{
}
/// <summary></summary>
/// CapsHandlers is a cap handler container but also takes
/// care of adding and removing cap handlers to and from the
/// supplied BaseHttpServer.
/// </summary>
/// <param name="httpListener">base HTTP server</param>
/// <param name="httpListenerHostname">host name of the HTTP
/// server</param>
/// <param name="httpListenerPort">HTTP port</param>
public CapsHandlers(IHttpServer httpListener, string httpListenerHostname, uint httpListenerPort, bool https)
{
m_httpListener = httpListener;
m_httpListenerHostName = httpListenerHostname;
m_httpListenerPort = httpListenerPort;
if (httpListener != null && httpListener.UseSSL)
m_useSSL = true;
else
m_useSSL = false;
m_useSSL = https;
if (httpListener != null && m_useSSL)
{
m_httpListenerHostName = httpListener.SSLCommonName;
m_httpListenerPort = httpListener.SSLPort;
}
}
/// <summary>
@ -75,35 +89,16 @@ namespace OpenSim.Framework.Capabilities
{
lock (m_capsHandlers)
{
if(m_capsHandlers.ContainsKey(capsName))
{
m_httpListener.RemoveStreamHandler("POST", m_capsHandlers[capsName].Path);
m_httpListener.RemoveStreamHandler("PUT", m_capsHandlers[capsName].Path);
m_httpListener.RemoveStreamHandler("GET", m_capsHandlers[capsName].Path);
m_httpListener.RemoveStreamHandler("DELETE", m_capsHandlers[capsName].Path);
m_capsHandlers.Remove(capsName);
}
m_httpListener.RemoveStreamHandler("POST", m_capsHandlers[capsName].Path);
m_httpListener.RemoveStreamHandler("GET", m_capsHandlers[capsName].Path);
m_capsHandlers.Remove(capsName);
}
if(m_capsSimpleHandlers.TryRemove(capsName, out ISimpleStreamHandler hdr))
{
m_httpListener.RemoveSimpleStreamHandler(hdr.Path);
}
}
public void AddSimpleHandler(string capName, ISimpleStreamHandler handler, bool addToListener = true)
{
if(ContainsCap(capName))
Remove(capName);
if(m_capsSimpleHandlers.TryAdd(capName, handler) && addToListener)
m_httpListener.AddSimpleStreamHandler(handler);
}
public bool ContainsCap(string cap)
{
lock (m_capsHandlers)
if (m_capsHandlers.ContainsKey(cap))
return true;
return m_capsSimpleHandlers.ContainsKey(cap);
return m_capsHandlers.ContainsKey(cap);
}
/// <summary>
@ -130,14 +125,11 @@ namespace OpenSim.Framework.Capabilities
if (m_capsHandlers.ContainsKey(idx))
{
m_httpListener.RemoveStreamHandler("POST", m_capsHandlers[idx].Path);
m_httpListener.RemoveStreamHandler("PUT", m_capsHandlers[idx].Path);
m_httpListener.RemoveStreamHandler("GET", m_capsHandlers[idx].Path);
m_httpListener.RemoveStreamHandler("DELETE", m_capsHandlers[idx].Path);
m_capsHandlers.Remove(idx);
}
if (null == value) return;
m_capsHandlers[idx] = value;
m_httpListener.AddStreamHandler(value);
}
@ -154,9 +146,8 @@ namespace OpenSim.Framework.Capabilities
{
lock (m_capsHandlers)
{
string[] __keys = new string[m_capsHandlers.Keys.Count + m_capsSimpleHandlers.Keys.Count];
string[] __keys = new string[m_capsHandlers.Keys.Count];
m_capsHandlers.Keys.CopyTo(__keys, 0);
m_capsSimpleHandlers.Keys.CopyTo(__keys, m_capsHandlers.Keys.Count);
return __keys;
}
}
@ -170,39 +161,24 @@ namespace OpenSim.Framework.Capabilities
public Hashtable GetCapsDetails(bool excludeSeed, List<string> requestedCaps)
{
Hashtable caps = new Hashtable();
string protocol = "http://";
if (m_useSSL)
protocol = "https://";
string protocol = m_useSSL ? "https://" : "http://";
string baseUrl = protocol + m_httpListenerHostName + ":" + m_httpListenerPort.ToString();
if (requestedCaps == null)
{
lock (m_capsHandlers)
{
foreach (KeyValuePair<string, ISimpleStreamHandler> kvp in m_capsSimpleHandlers)
caps[kvp.Key] = baseUrl + kvp.Value.Path;
foreach (KeyValuePair<string, IRequestHandler> kvp in m_capsHandlers)
caps[kvp.Key] = baseUrl + kvp.Value.Path;
}
return caps;
}
lock (m_capsHandlers)
{
for(int i = 0; i < requestedCaps.Count; ++i)
foreach (string capsName in m_capsHandlers.Keys)
{
string capsName = requestedCaps[i];
if (excludeSeed && "SEED" == capsName)
continue;
if (m_capsSimpleHandlers.TryGetValue(capsName, out ISimpleStreamHandler shdr))
{
caps[capsName] = baseUrl + shdr.Path;
if (requestedCaps != null && !requestedCaps.Contains(capsName))
continue;
}
if (m_capsHandlers.TryGetValue(capsName, out IRequestHandler chdr))
{
caps[capsName] = baseUrl + chdr.Path;
}
caps[capsName] = baseUrl + m_capsHandlers[capsName].Path;
}
}

View File

@ -0,0 +1,116 @@
/*
* Copyright (c) Contributors, http://opensimulator.org/
* See CONTRIBUTORS.TXT for a full list of copyright holders.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the OpenSimulator Project nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.IO;
using System.Reflection;
using System.Web;
using log4net;
using Nini.Config;
using OpenMetaverse;
using OpenSim.Framework;
using OpenSim.Framework.Capabilities;
using OpenSim.Framework.Servers;
using OpenSim.Framework.Servers.HttpServer;
//using OpenSim.Region.Framework.Interfaces;
using OpenSim.Services.Interfaces;
using Caps = OpenSim.Framework.Capabilities.Caps;
namespace OpenSim.Capabilities.Handlers
{
public class AvatarPickerSearchHandler : BaseStreamHandler
{
private static readonly ILog m_log =
LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private IPeople m_PeopleService;
public AvatarPickerSearchHandler(string path, IPeople peopleService, string name, string description)
: base("GET", path, name, description)
{
m_PeopleService = peopleService;
}
protected override byte[] ProcessRequest(string path, Stream request, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
{
// Try to parse the texture ID from the request URL
NameValueCollection query = HttpUtility.ParseQueryString(httpRequest.Url.Query);
string names = query.GetOne("names");
string psize = query.GetOne("page_size");
string pnumber = query.GetOne("page");
if (m_PeopleService == null)
return FailureResponse(names, (int)System.Net.HttpStatusCode.InternalServerError, httpResponse);
if (string.IsNullOrEmpty(names) || names.Length < 3)
return FailureResponse(names, (int)System.Net.HttpStatusCode.BadRequest, httpResponse);
m_log.DebugFormat("[AVATAR PICKER SEARCH]: search for {0}", names);
int page_size = (string.IsNullOrEmpty(psize) ? 500 : Int32.Parse(psize));
int page_number = (string.IsNullOrEmpty(pnumber) ? 1 : Int32.Parse(pnumber));
// Full content request
httpResponse.StatusCode = (int)System.Net.HttpStatusCode.OK;
//httpResponse.ContentLength = ??;
httpResponse.ContentType = "application/llsd+xml";
List<UserData> users = m_PeopleService.GetUserData(names, page_size, page_number);
LLSDAvatarPicker osdReply = new LLSDAvatarPicker();
osdReply.next_page_url = httpRequest.RawUrl;
foreach (UserData u in users)
osdReply.agents.Array.Add(ConvertUserData(u));
string reply = LLSDHelpers.SerialiseLLSDReply(osdReply);
return System.Text.Encoding.UTF8.GetBytes(reply);
}
private LLSDPerson ConvertUserData(UserData user)
{
LLSDPerson p = new LLSDPerson();
p.legacy_first_name = user.FirstName;
p.legacy_last_name = user.LastName;
p.display_name = user.FirstName + " " + user.LastName;
if (user.LastName.StartsWith("@"))
p.username = user.FirstName.ToLower() + user.LastName.ToLower();
else
p.username = user.FirstName.ToLower() + "." + user.LastName.ToLower();
p.id = user.Id;
p.is_display_name_default = false;
return p;
}
private byte[] FailureResponse(string names, int statuscode, IOSHttpResponse httpResponse)
{
m_log.Error("[AVATAR PICKER SEARCH]: Error searching for " + names);
httpResponse.StatusCode = (int)System.Net.HttpStatusCode.NotFound;
return System.Text.Encoding.UTF8.GetBytes(string.Empty);
}
}
}

View File

@ -1,449 +0,0 @@
/*
* Copyright (c) Contributors, http://opensimulator.org/
* See CONTRIBUTORS.TXT for a full list of copyright holders.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the OpenSimulator Project nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using log4net;
using Nini.Config;
using OpenMetaverse;
using OpenMetaverse.StructuredData;
using OpenSim.Framework;
using OpenSim.Framework.Capabilities;
using OpenSim.Framework.Servers.HttpServer;
using OpenSim.Services.Interfaces;
using OSDMap = OpenMetaverse.StructuredData.OSDMap;
using OSDArray = OpenMetaverse.StructuredData.OSDArray;
namespace OpenSim.Capabilities.Handlers
{
public class FetchInvDescHandler
{
private static readonly ILog m_log =
LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private static byte[] EmptyResponse = Util.UTF8NBGetbytes("<llsd><map><key>folders</key><array /></map></llsd>");
private IInventoryService m_InventoryService;
private ILibraryService m_LibraryService;
private IScene m_Scene;
public FetchInvDescHandler(IInventoryService invService, ILibraryService libService, IScene s)
{
m_InventoryService = invService;
m_LibraryService = libService;
m_Scene = s;
}
public void FetchInventoryDescendentsRequest(IOSHttpRequest httpRequest, IOSHttpResponse httpResponse, ExpiringKey<UUID> BadRequests)
{
//m_log.DebugFormat("[XXX]: FetchInventoryDescendentsRequest in {0}, {1}", (m_Scene == null) ? "none" : m_Scene.Name, request);
List<LLSDFetchInventoryDescendents> folders = null;
List<UUID> bad_folders = new List<UUID>();
try
{
OSDArray foldersrequested = null;
OSD tmp = OSDParser.DeserializeLLSDXml(httpRequest.InputStream);
OSDMap map = (OSDMap)tmp;
if(map.TryGetValue("folders", out tmp) && tmp is OSDArray)
foldersrequested = tmp as OSDArray;
if (foldersrequested == null || foldersrequested.Count == 0)
{
httpResponse.RawBuffer = EmptyResponse;
return;
}
folders = new List<LLSDFetchInventoryDescendents>(foldersrequested.Count);
for (int i = 0; i < foldersrequested.Count; i++)
{
OSDMap mfolder = foldersrequested[i] as OSDMap;
UUID id = mfolder["folder_id"].AsUUID();
if(BadRequests.ContainsKey(id))
{
bad_folders.Add(id);
}
else
{
LLSDFetchInventoryDescendents llsdRequest = new LLSDFetchInventoryDescendents();
try
{
llsdRequest.folder_id = id;
llsdRequest.owner_id = mfolder["owner_id"].AsUUID();
llsdRequest.sort_order = mfolder["sort_order"].AsInteger();
llsdRequest.fetch_folders = mfolder["fetch_folders"].AsBoolean();
llsdRequest.fetch_items = mfolder["fetch_items"].AsBoolean();
}
catch (Exception e)
{
m_log.Debug("[WEB FETCH INV DESC HANDLER]: caught exception doing OSD deserialize" + e.Message);
continue;
}
folders.Add(llsdRequest);
}
}
foldersrequested = null;
tmp = null;
}
catch (Exception e)
{
m_log.ErrorFormat("[FETCH INV DESC]: fail parsing request: {0}", e.Message);
httpResponse.RawBuffer = EmptyResponse;
return;
}
if (folders == null || folders.Count == 0)
{
if(bad_folders.Count == 0)
{
httpResponse.RawBuffer = EmptyResponse;
return;
}
StringBuilder sb = osStringBuilderCache.Acquire();
sb.Append("<llsd><map><key>folders</key><array /></map><map><key>bad_folders</key><array>");
foreach (UUID bad in bad_folders)
{
sb.Append("<map><key>folder_id</key><uuid>");
sb.Append(bad.ToString());
sb.Append("</uuid><key>error</key><string>Unknown</string></map>");
}
sb.Append("</array></map></llsd>");
httpResponse.RawBuffer = Util.UTF8NBGetbytes(osStringBuilderCache.GetStringAndRelease(sb));
}
int total_folders = 0;
int total_items = 0;
List<InventoryCollection> invcollSet = Fetch(folders, bad_folders, ref total_folders, ref total_items);
//m_log.DebugFormat("[XXX]: Got {0} folders from a request of {1}", invcollSet.Count, folders.Count);
int invcollSetCount = 0;
if (invcollSet != null)
invcollSetCount = invcollSet.Count;
int mem = 8192 + ((256 * invcollSetCount +
384 * total_folders +
1024 * total_items +
128 * bad_folders.Count) & 0x7ffff000);
StringBuilder lastresponse = new StringBuilder(mem);
lastresponse.Append("<llsd>");
if (invcollSetCount > 0)
{
lastresponse.Append("<map><key>folders</key><array>");
int i = 0;
InventoryCollection thiscoll;
for (i = 0; i < invcollSetCount; i++)
{
thiscoll = invcollSet[i];
invcollSet[i] = null;
LLSDxmlEncode.AddMap(lastresponse);
LLSDxmlEncode.AddElem("agent_id", thiscoll.OwnerID, lastresponse);
LLSDxmlEncode.AddElem("descendents", thiscoll.Descendents, lastresponse);
LLSDxmlEncode.AddElem("folder_id", thiscoll.FolderID, lastresponse);
if (thiscoll.Folders == null || thiscoll.Folders.Count == 0)
LLSDxmlEncode.AddEmptyArray("categories", lastresponse);
else
{
LLSDxmlEncode.AddArray("categories", lastresponse);
foreach (InventoryFolderBase invFolder in thiscoll.Folders)
{
LLSDxmlEncode.AddMap(lastresponse);
LLSDxmlEncode.AddElem("folder_id", invFolder.ID, lastresponse);
LLSDxmlEncode.AddElem("parent_id", invFolder.ParentID, lastresponse);
LLSDxmlEncode.AddElem("name", invFolder.Name, lastresponse);
LLSDxmlEncode.AddElem("type", invFolder.Type, lastresponse);
LLSDxmlEncode.AddElem("preferred_type", (int)-1, lastresponse);
LLSDxmlEncode.AddElem("version", invFolder.Version, lastresponse);
LLSDxmlEncode.AddEndMap(lastresponse);
}
LLSDxmlEncode.AddEndArray(lastresponse);
}
if (thiscoll.Items == null || thiscoll.Items.Count == 0)
LLSDxmlEncode.AddEmptyArray("items", lastresponse);
else
{
LLSDxmlEncode.AddArray("items", lastresponse);
foreach (InventoryItemBase invItem in thiscoll.Items)
{
invItem.ToLLSDxml(lastresponse);
}
LLSDxmlEncode.AddEndArray(lastresponse);
}
LLSDxmlEncode.AddElem("owner_id", thiscoll.OwnerID, lastresponse);
LLSDxmlEncode.AddElem("version", thiscoll.Version, lastresponse);
LLSDxmlEncode.AddEndMap(lastresponse);
invcollSet[i] = null;
}
lastresponse.Append("</array></map>");
thiscoll = null;
}
else
{
lastresponse.Append("<map><key>folders</key><array /></map>");
}
//m_log.DebugFormat("[WEB FETCH INV DESC HANDLER]: Bad folders {0}", string.Join(", ", bad_folders));
if (bad_folders.Count > 0)
{
lastresponse.Append("<map><key>bad_folders</key><array>");
foreach (UUID bad in bad_folders)
{
BadRequests.Add(bad);
lastresponse.Append("<map><key>folder_id</key><uuid>");
lastresponse.Append(bad.ToString());
lastresponse.Append("</uuid><key>error</key><string>Unknown</string></map>");
}
lastresponse.Append("</array></map>");
}
lastresponse.Append("</llsd>");
httpResponse.RawBuffer = Util.UTF8NBGetbytes(lastresponse.ToString());
}
private void AddLibraryFolders(List<LLSDFetchInventoryDescendents> libFolders, List<InventoryCollection> result, ref int total_folders, ref int total_items)
{
InventoryFolderImpl fold;
if (m_LibraryService == null || m_LibraryService.LibraryRootFolder == null)
return;
foreach (LLSDFetchInventoryDescendents f in libFolders)
{
if ((fold = m_LibraryService.LibraryRootFolder.FindFolder(f.folder_id)) != null)
{
InventoryCollection Collection = new InventoryCollection();
// ret.Collection.Folders = new List<InventoryFolderBase>();
Collection.Folders = fold.RequestListOfFolders();
Collection.Items = fold.RequestListOfItems();
Collection.OwnerID = m_LibraryService.LibraryRootFolder.Owner;
Collection.FolderID = f.folder_id;
Collection.Version = fold.Version;
Collection.Descendents = Collection.Items.Count + Collection.Folders.Count;
total_folders += Collection.Folders.Count;
total_items += Collection.Items.Count;
result.Add(Collection);
//m_log.DebugFormat("[XXX]: Added libfolder {0} ({1}) {2}", ret.Collection.FolderID, ret.Collection.OwnerID);
}
}
}
private List<InventoryCollection> Fetch(List<LLSDFetchInventoryDescendents> fetchFolders, List<UUID> bad_folders, ref int total_folders, ref int total_items)
{
//m_log.DebugFormat(
// "[WEB FETCH INV DESC HANDLER]: Fetching {0} folders for owner {1}", fetchFolders.Count, fetchFolders[0].owner_id);
// FIXME MAYBE: We're not handling sortOrder!
List<InventoryCollection> result = new List<InventoryCollection>(32);
List<LLSDFetchInventoryDescendents> libFolders = new List<LLSDFetchInventoryDescendents>(32);
List<LLSDFetchInventoryDescendents> otherFolders = new List<LLSDFetchInventoryDescendents>(32);
HashSet<UUID> libIDs = new HashSet<UUID>();
HashSet<UUID> otherIDs = new HashSet<UUID>();
bool dolib = (m_LibraryService != null && m_LibraryService.LibraryRootFolder != null);
UUID libOwner = UUID.Zero;
if(dolib)
libOwner = m_LibraryService.LibraryRootFolder.Owner;
// Filter folder Zero right here. Some viewers (Firestorm) send request for folder Zero, which doesn't make sense
// and can kill the sim (all root folders have parent_id Zero)
// send something.
bool doneZeroID = false;
foreach(LLSDFetchInventoryDescendents f in fetchFolders)
{
if (f.folder_id == UUID.Zero)
{
if(doneZeroID)
continue;
doneZeroID = true;
InventoryCollection Collection = new InventoryCollection();
Collection.OwnerID = f.owner_id;
Collection.Version = 0;
Collection.FolderID = f.folder_id;
Collection.Descendents = 0;
result.Add(Collection);
continue;
}
if(dolib && f.owner_id == libOwner)
{
if(libIDs.Contains(f.folder_id))
continue;
libIDs.Add(f.folder_id);
libFolders.Add(f);
continue;
}
if(otherIDs.Contains(f.folder_id))
continue;
otherIDs.Add(f.folder_id);
otherFolders.Add(f);
}
fetchFolders.Clear();
if(otherFolders.Count > 0)
{
int i = 0;
//m_log.DebugFormat("[XXX]: {0}", string.Join(",", fids));
InventoryCollection[] fetchedContents = m_InventoryService.GetMultipleFoldersContent(otherFolders[0].owner_id, otherIDs.ToArray());
if (fetchedContents == null)
return null;
if (fetchedContents.Length == 0)
{
foreach (LLSDFetchInventoryDescendents freq in otherFolders)
BadFolder(freq, null, bad_folders);
}
else
{
i = 0;
// Do some post-processing. May need to fetch more from inv server for links
foreach (InventoryCollection contents in fetchedContents)
{
// Find the original request
LLSDFetchInventoryDescendents freq = otherFolders[i];
otherFolders[i]=null;
i++;
if (BadFolder(freq, contents, bad_folders))
continue;
if(!freq.fetch_folders)
contents.Folders.Clear();
if(!freq.fetch_items)
contents.Items.Clear();
contents.Descendents = contents.Items.Count + contents.Folders.Count;
// Next: link management
ProcessLinks(freq, contents);
total_folders += contents.Folders.Count;
total_items += contents.Items.Count;
result.Add(contents);
}
}
}
if(dolib && libFolders.Count > 0)
{
AddLibraryFolders(libFolders, result, ref total_folders, ref total_items);
}
return result;
}
private bool BadFolder(LLSDFetchInventoryDescendents freq, InventoryCollection contents, List<UUID> bad_folders)
{
if (contents == null)
{
bad_folders.Add(freq.folder_id);
return true;
}
// The inventory server isn't sending FolderID in the collection...
// Must fetch it individually
if (contents.FolderID == UUID.Zero)
{
InventoryFolderBase containingFolder = m_InventoryService.GetFolder(freq.owner_id, freq.folder_id);
if (containingFolder == null)
{
m_log.WarnFormat("[WEB FETCH INV DESC HANDLER]: Unable to fetch folder {0}", freq.folder_id);
bad_folders.Add(freq.folder_id);
return true;
}
contents.FolderID = containingFolder.ID;
contents.OwnerID = containingFolder.Owner;
contents.Version = containingFolder.Version;
}
return false;
}
private void ProcessLinks(LLSDFetchInventoryDescendents freq, InventoryCollection contents)
{
if (contents.Items == null || contents.Items.Count == 0)
return;
// viewers are lasy and want a copy of the linked item sent before the link to it
// look for item links
List<UUID> itemIDs = new List<UUID>();
foreach (InventoryItemBase item in contents.Items)
{
//m_log.DebugFormat("[XXX]: {0} {1}", item.Name, item.AssetType);
if (item.AssetType == (int)AssetType.Link)
itemIDs.Add(item.AssetID);
}
// get the linked if any
if (itemIDs.Count > 0)
{
InventoryItemBase[] linked = m_InventoryService.GetMultipleItems(freq.owner_id, itemIDs.ToArray());
if (linked != null)
{
List<InventoryItemBase> linkedItems = new List<InventoryItemBase>(linked.Length);
// check for broken
foreach (InventoryItemBase linkedItem in linked)
{
// Take care of genuinely broken links where the target doesn't exist
// HACK: Also, don't follow up links that just point to other links. In theory this is legitimate,
// but no viewer has been observed to set these up and this is the lazy way of avoiding cycles
// rather than having to keep track of every folder requested in the recursion.
if (linkedItem != null && linkedItem.AssetType != (int)AssetType.Link)
{
linkedItems.Add(linkedItem);
//m_log.DebugFormat("[WEB FETCH INV DESC HANDLER]: Added {0} {1} {2}", linkedItem.Name, linkedItem.AssetType, linkedItem.Folder);
}
}
// insert them
if(linkedItems.Count > 0)
contents.Items.InsertRange(0, linkedItems);
}
}
}
}
}

View File

@ -1,166 +0,0 @@
/*
* Copyright (c) Contributors, http://opensimulator.org/
* See CONTRIBUTORS.TXT for a full list of copyright holders.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the OpenSimulator Project nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
using System.Net;
using System.Reflection;
using System.Text;
using OpenMetaverse;
using OpenMetaverse.StructuredData;
using OpenSim.Framework;
using OpenSim.Framework.Servers.HttpServer;
using OpenSim.Services.Interfaces;
using OSDArray = OpenMetaverse.StructuredData.OSDArray;
using OSDMap = OpenMetaverse.StructuredData.OSDMap;
using log4net;
namespace OpenSim.Capabilities.Handlers
{
public class FetchInventory2Handler
{
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private IInventoryService m_inventoryService;
private UUID m_agentID;
public FetchInventory2Handler(IInventoryService invService, UUID agentId)
{
m_inventoryService = invService;
m_agentID = agentId;
}
public string FetchInventoryRequest(string request, string path, string param, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
{
//m_log.DebugFormat("[FETCH INVENTORY HANDLER]: Received FetchInventory capability request {0}", request);
OSDMap requestmap = (OSDMap)OSDParser.DeserializeLLSDXml(Utils.StringToBytes(request));
OSDArray itemsRequested = (OSDArray)requestmap["items"];
UUID[] itemIDs = new UUID[itemsRequested.Count];
int i = 0;
foreach (OSDMap osdItemId in itemsRequested)
{
itemIDs[i++] = osdItemId["item_id"].AsUUID();
}
InventoryItemBase[] items = null;
if (m_agentID != UUID.Zero)
{
items = m_inventoryService.GetMultipleItems(m_agentID, itemIDs);
}
else
{
items = new InventoryItemBase[itemsRequested.Count];
foreach (UUID id in itemIDs)
items[i++] = m_inventoryService.GetItem(UUID.Zero, id);
}
StringBuilder lsl = LLSDxmlEncode.Start(4096);
LLSDxmlEncode.AddMap(lsl);
if(m_agentID == UUID.Zero && items.Length > 0)
LLSDxmlEncode.AddElem("agent_id", items[0].Owner, lsl);
else
LLSDxmlEncode.AddElem("agent_id", m_agentID, lsl);
if(items == null || items.Length == 0)
{
LLSDxmlEncode.AddEmptyArray("items", lsl);
}
else
{
LLSDxmlEncode.AddArray("items", lsl);
foreach (InventoryItemBase item in items)
{
if (item != null)
item.ToLLSDxml(lsl, 0xff);
}
LLSDxmlEncode.AddEndArray(lsl);
}
LLSDxmlEncode.AddEndMap(lsl);
return LLSDxmlEncode.End(lsl);
}
public void FetchInventorySimpleRequest(IOSHttpRequest httpRequest, IOSHttpResponse httpResponse, OSDMap requestmap, ExpiringKey<UUID> BadRequests)
{
//m_log.DebugFormat("[FETCH INVENTORY HANDLER]: Received FetchInventory capability request {0}", request);
if(BadRequests == null)
{
httpResponse.StatusCode = (int)HttpStatusCode.NotFound;
return;
}
OSDArray itemsRequested = (OSDArray)requestmap["items"];
UUID[] itemIDs = new UUID[itemsRequested.Count];
int i = 0;
foreach (OSDMap osdItemId in itemsRequested)
{
UUID id = osdItemId["item_id"].AsUUID();
if(!BadRequests.ContainsKey(id))
itemIDs[i++] = id;
}
InventoryItemBase[] items = null;
try
{
// badrequests still not filled
items = m_inventoryService.GetMultipleItems(m_agentID, itemIDs);
}
catch{ }
StringBuilder lsl = LLSDxmlEncode.Start(4096);
LLSDxmlEncode.AddMap(lsl);
LLSDxmlEncode.AddElem("agent_id", m_agentID, lsl);
if (items == null || items.Length == 0)
{
LLSDxmlEncode.AddEmptyArray("items", lsl);
}
else
{
LLSDxmlEncode.AddArray("items", lsl);
foreach (InventoryItemBase item in items)
{
if (item != null)
item.ToLLSDxml(lsl, 0xff);
}
LLSDxmlEncode.AddEndArray(lsl);
}
LLSDxmlEncode.AddEndMap(lsl);
httpResponse.RawBuffer = Util.UTF8.GetBytes(LLSDxmlEncode.End(lsl));
httpResponse.StatusCode = (int)HttpStatusCode.OK;
}
}
}

View File

@ -1,170 +0,0 @@
/*
* Copyright (c) Contributors, http://opensimulator.org/
* See CONTRIBUTORS.TXT for a full list of copyright holders.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the OpenSimulator Project nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text.RegularExpressions;
using log4net;
using log4net.Config;
using NUnit.Framework;
using OpenMetaverse;
using OpenSim.Capabilities.Handlers;
using OpenSim.Framework;
using OpenSim.Framework.Servers.HttpServer;
using OpenSim.Region.Framework.Scenes;
using OpenSim.Services.Interfaces;
using OpenSim.Tests.Common;
namespace OpenSim.Capabilities.Handlers.FetchInventory.Tests
{
[TestFixture]
public class FetchInventory2HandlerTests : OpenSimTestCase
{
private UUID m_userID = UUID.Random();
private Scene m_scene;
private UUID m_rootFolderID;
private UUID m_notecardsFolder;
private UUID m_objectsFolder;
private void Init()
{
// Create an inventory that looks like this:
//
// /My Inventory
// <other system folders>
// /Objects
// Object 1
// Object 2
// Object 3
// /Notecards
// Notecard 1
// Notecard 2
// Notecard 3
// Notecard 4
// Notecard 5
m_scene = new SceneHelpers().SetupScene();
m_scene.InventoryService.CreateUserInventory(m_userID);
m_rootFolderID = m_scene.InventoryService.GetRootFolder(m_userID).ID;
InventoryFolderBase of = m_scene.InventoryService.GetFolderForType(m_userID, FolderType.Object);
m_objectsFolder = of.ID;
// Add 3 objects
InventoryItemBase item;
for (int i = 1; i <= 3; i++)
{
item = new InventoryItemBase(new UUID("b0000000-0000-0000-0000-0000000000b" + i), m_userID);
item.AssetID = UUID.Random();
item.AssetType = (int)AssetType.Object;
item.Folder = m_objectsFolder;
item.Name = "Object " + i;
m_scene.InventoryService.AddItem(item);
}
InventoryFolderBase ncf = m_scene.InventoryService.GetFolderForType(m_userID, FolderType.Notecard);
m_notecardsFolder = ncf.ID;
// Add 5 notecards
for (int i = 1; i <= 5; i++)
{
item = new InventoryItemBase(new UUID("10000000-0000-0000-0000-00000000000" + i), m_userID);
item.AssetID = UUID.Random();
item.AssetType = (int)AssetType.Notecard;
item.Folder = m_notecardsFolder;
item.Name = "Notecard " + i;
m_scene.InventoryService.AddItem(item);
}
}
[Test]
public void Test_001_RequestOne()
{
TestHelpers.InMethod();
Init();
FetchInventory2Handler handler = new FetchInventory2Handler(m_scene.InventoryService, m_userID);
TestOSHttpRequest req = new TestOSHttpRequest();
TestOSHttpResponse resp = new TestOSHttpResponse();
string request = "<llsd><map><key>items</key><array><map><key>item_id</key><uuid>";
request += "10000000-0000-0000-0000-000000000001"; // Notecard 1
request += "</uuid></map></array></map></llsd>";
string llsdresponse = handler.FetchInventoryRequest(request, "/FETCH", string.Empty, req, resp);
Assert.That(llsdresponse != null, Is.True, "Incorrect null response");
Assert.That(llsdresponse != string.Empty, Is.True, "Incorrect empty response");
Assert.That(llsdresponse.Contains(m_userID.ToString()), Is.True, "Response should contain userID");
Assert.That(llsdresponse.Contains("10000000-0000-0000-0000-000000000001"), Is.True, "Response does not contain item uuid");
Assert.That(llsdresponse.Contains("Notecard 1"), Is.True, "Response does not contain item Name");
Console.WriteLine(llsdresponse);
}
[Test]
public void Test_002_RequestMany()
{
TestHelpers.InMethod();
Init();
FetchInventory2Handler handler = new FetchInventory2Handler(m_scene.InventoryService, m_userID);
TestOSHttpRequest req = new TestOSHttpRequest();
TestOSHttpResponse resp = new TestOSHttpResponse();
string request = "<llsd><map><key>items</key><array>";
request += "<map><key>item_id</key><uuid>10000000-0000-0000-0000-000000000001</uuid></map>"; // Notecard 1
request += "<map><key>item_id</key><uuid>10000000-0000-0000-0000-000000000002</uuid></map>"; // Notecard 2
request += "<map><key>item_id</key><uuid>10000000-0000-0000-0000-000000000003</uuid></map>"; // Notecard 3
request += "<map><key>item_id</key><uuid>10000000-0000-0000-0000-000000000004</uuid></map>"; // Notecard 4
request += "<map><key>item_id</key><uuid>10000000-0000-0000-0000-000000000005</uuid></map>"; // Notecard 5
request += "</array></map></llsd>";
string llsdresponse = handler.FetchInventoryRequest(request, "/FETCH", string.Empty, req, resp);
Assert.That(llsdresponse != null, Is.True, "Incorrect null response");
Assert.That(llsdresponse != string.Empty, Is.True, "Incorrect empty response");
Assert.That(llsdresponse.Contains(m_userID.ToString()), Is.True, "Response should contain userID");
Console.WriteLine(llsdresponse);
Assert.That(llsdresponse.Contains("10000000-0000-0000-0000-000000000001"), Is.True, "Response does not contain notecard 1");
Assert.That(llsdresponse.Contains("10000000-0000-0000-0000-000000000002"), Is.True, "Response does not contain notecard 2");
Assert.That(llsdresponse.Contains("10000000-0000-0000-0000-000000000003"), Is.True, "Response does not contain notecard 3");
Assert.That(llsdresponse.Contains("10000000-0000-0000-0000-000000000004"), Is.True, "Response does not contain notecard 4");
Assert.That(llsdresponse.Contains("10000000-0000-0000-0000-000000000005"), Is.True, "Response does not contain notecard 5");
}
}
}

View File

@ -1,300 +0,0 @@
/*
* Copyright (c) Contributors, http://opensimulator.org/
* See CONTRIBUTORS.TXT for a full list of copyright holders.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the OpenSimulator Project nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
using System;
using System.Collections.Generic;
using System.Linq;
using System.IO;
using System.Text.RegularExpressions;
using log4net;
using log4net.Config;
using NUnit.Framework;
using OpenMetaverse;
using OpenSim.Capabilities.Handlers;
using OpenSim.Framework;
using OpenSim.Framework.Servers.HttpServer;
using OpenSim.Region.Framework.Scenes;
using OpenSim.Services.Interfaces;
using OpenSim.Tests.Common;
namespace OpenSim.Capabilities.Handlers.FetchInventory.Tests
{
[TestFixture]
public class FetchInventoryDescendents2HandlerTests : OpenSimTestCase
{
private UUID m_userID = new UUID("00000000-0000-0000-0000-000000000001");
private Scene m_scene;
private UUID m_rootFolderID;
private int m_rootDescendents;
private UUID m_notecardsFolder;
private UUID m_objectsFolder;
private void Init()
{
// Create an inventory that looks like this:
//
// /My Inventory
// <other system folders>
// /Objects
// Some Object
// /Notecards
// Notecard 1
// Notecard 2
// /Test Folder
// Link to notecard -> /Notecards/Notecard 2
// Link to Objects folder -> /Objects
m_scene = new SceneHelpers().SetupScene();
m_scene.InventoryService.CreateUserInventory(m_userID);
m_rootFolderID = m_scene.InventoryService.GetRootFolder(m_userID).ID;
InventoryFolderBase of = m_scene.InventoryService.GetFolderForType(m_userID, FolderType.Object);
m_objectsFolder = of.ID;
// Add an object
InventoryItemBase item = new InventoryItemBase(new UUID("b0000000-0000-0000-0000-00000000000b"), m_userID);
item.AssetID = UUID.Random();
item.AssetType = (int)AssetType.Object;
item.Folder = m_objectsFolder;
item.Name = "Some Object";
m_scene.InventoryService.AddItem(item);
InventoryFolderBase ncf = m_scene.InventoryService.GetFolderForType(m_userID, FolderType.Notecard);
m_notecardsFolder = ncf.ID;
// Add a notecard
item = new InventoryItemBase(new UUID("10000000-0000-0000-0000-000000000001"), m_userID);
item.AssetID = UUID.Random();
item.AssetType = (int)AssetType.Notecard;
item.Folder = m_notecardsFolder;
item.Name = "Test Notecard 1";
m_scene.InventoryService.AddItem(item);
// Add another notecard
item.ID = new UUID("20000000-0000-0000-0000-000000000002");
item.AssetID = new UUID("a0000000-0000-0000-0000-00000000000a");
item.Name = "Test Notecard 2";
m_scene.InventoryService.AddItem(item);
// Add a folder
InventoryFolderBase folder = new InventoryFolderBase(new UUID("f0000000-0000-0000-0000-00000000000f"), "Test Folder", m_userID, m_rootFolderID);
folder.Type = (short)FolderType.None;
m_scene.InventoryService.AddFolder(folder);
// Add a link to notecard 2 in Test Folder
item.AssetID = item.ID; // use item ID of notecard 2
item.ID = new UUID("40000000-0000-0000-0000-000000000004");
item.AssetType = (int)AssetType.Link;
item.Folder = folder.ID;
item.Name = "Link to notecard";
m_scene.InventoryService.AddItem(item);
// Add a link to the Objects folder in Test Folder
item.AssetID = m_scene.InventoryService.GetFolderForType(m_userID, FolderType.Object).ID; // use item ID of Objects folder
item.ID = new UUID("50000000-0000-0000-0000-000000000005");
item.AssetType = (int)AssetType.LinkFolder;
item.Folder = folder.ID;
item.Name = "Link to Objects folder";
m_scene.InventoryService.AddItem(item);
InventoryCollection coll = m_scene.InventoryService.GetFolderContent(m_userID, m_rootFolderID);
m_rootDescendents = coll.Items.Count + coll.Folders.Count;
Console.WriteLine("Number of descendents: " + m_rootDescendents);
}
private string dorequest(FetchInvDescHandler handler, string request)
{
TestOSHttpRequest req = new TestOSHttpRequest();
TestOSHttpResponse resp = new TestOSHttpResponse();
using(ExpiringKey<UUID> bad = new ExpiringKey<UUID>(5000)) // bad but this is test
using (MemoryStream ms = new MemoryStream(Utils.StringToBytes(request), false))
{
req.InputStream = ms;
handler.FetchInventoryDescendentsRequest(req, resp, bad);
}
return Util.UTF8.GetString(resp.RawBuffer);
}
[Test]
public void Test_001_SimpleFolder()
{
TestHelpers.InMethod();
Init();
FetchInvDescHandler handler = new FetchInvDescHandler(m_scene.InventoryService, null, m_scene);
string request = "<llsd><map><key>folders</key><array><map><key>fetch_folders</key><integer>1</integer><key>fetch_items</key><boolean>1</boolean><key>folder_id</key><uuid>";
request += m_rootFolderID;
request += "</uuid><key>owner_id</key><uuid>";
request += m_userID.ToString();
request += "</uuid><key>sort_order</key><integer>1</integer></map></array></map></llsd>";
string llsdresponse = dorequest(handler, request);
Assert.That(llsdresponse != null, Is.True, "Incorrect null response");
Assert.That(llsdresponse != string.Empty, Is.True, "Incorrect empty response");
Assert.That(llsdresponse.Contains(m_userID.ToString()), Is.True, "Response should contain userID");
string descendents = "descendents</key><integer>" + m_rootDescendents + "</integer>";
Assert.That(llsdresponse.Contains(descendents), Is.True, "Incorrect number of descendents");
Console.WriteLine(llsdresponse);
}
[Test]
public void Test_002_MultipleFolders()
{
TestHelpers.InMethod();
FetchInvDescHandler handler = new FetchInvDescHandler(m_scene.InventoryService, null, m_scene);
string request = "<llsd><map><key>folders</key><array>";
request += "<map><key>fetch_folders</key><integer>1</integer><key>fetch_items</key><boolean>1</boolean><key>folder_id</key><uuid>";
request += m_rootFolderID;
request += "</uuid><key>owner_id</key><uuid>00000000-0000-0000-0000-000000000001</uuid><key>sort_order</key><integer>1</integer></map>";
request += "<map><key>fetch_folders</key><integer>1</integer><key>fetch_items</key><boolean>1</boolean><key>folder_id</key><uuid>";
request += m_notecardsFolder;
request += "</uuid><key>owner_id</key><uuid>00000000-0000-0000-0000-000000000001</uuid><key>sort_order</key><integer>1</integer></map>";
request += "</array></map></llsd>";
string llsdresponse = dorequest(handler, request);
Console.WriteLine(llsdresponse);
string descendents = "descendents</key><integer>" + m_rootDescendents + "</integer>";
Assert.That(llsdresponse.Contains(descendents), Is.True, "Incorrect number of descendents for root folder");
descendents = "descendents</key><integer>2</integer>";
Assert.That(llsdresponse.Contains(descendents), Is.True, "Incorrect number of descendents for Notecard folder");
Assert.That(llsdresponse.Contains("10000000-0000-0000-0000-000000000001"), Is.True, "Notecard 1 is missing from response");
Assert.That(llsdresponse.Contains("20000000-0000-0000-0000-000000000002"), Is.True, "Notecard 2 is missing from response");
}
[Test]
public void Test_003_Links()
{
TestHelpers.InMethod();
FetchInvDescHandler handler = new FetchInvDescHandler(m_scene.InventoryService, null, m_scene);
string request = "<llsd><map><key>folders</key><array><map><key>fetch_folders</key><integer>1</integer><key>fetch_items</key><boolean>1</boolean><key>folder_id</key><uuid>";
request += "f0000000-0000-0000-0000-00000000000f";
request += "</uuid><key>owner_id</key><uuid>00000000-0000-0000-0000-000000000001</uuid><key>sort_order</key><integer>1</integer></map></array></map></llsd>";
string llsdresponse = dorequest(handler, request);
Console.WriteLine(llsdresponse);
string descendents = "descendents</key><integer>2</integer>";
Assert.That(llsdresponse.Contains(descendents), Is.True, "Incorrect number of descendents for Test Folder");
// Make sure that the note card link is included
Assert.That(llsdresponse.Contains("Link to notecard"), Is.True, "Link to notecard is missing");
//Make sure the notecard item itself is included
Assert.That(llsdresponse.Contains("Test Notecard 2"), Is.True, "Notecard 2 item (the source) is missing");
// Make sure that the source item is before the link item
int pos1 = llsdresponse.IndexOf("Test Notecard 2");
int pos2 = llsdresponse.IndexOf("Link to notecard");
Assert.Less(pos1, pos2, "Source of link is after link");
// Make sure the folder link is included
Assert.That(llsdresponse.Contains("Link to Objects folder"), Is.True, "Link to Objects folder is missing");
/* contents of link folder are not supposed to be listed
// Make sure the objects inside the Objects folder are included
// Note: I'm not entirely sure this is needed, but that's what I found in the implementation
Assert.That(llsdresponse.Contains("Some Object"), Is.True, "Some Object item (contents of the source) is missing");
*/
// Make sure that the source item is before the link item
pos1 = llsdresponse.IndexOf("Some Object");
pos2 = llsdresponse.IndexOf("Link to Objects folder");
Assert.Less(pos1, pos2, "Contents of source of folder link is after folder link");
}
[Test]
public void Test_004_DuplicateFolders()
{
TestHelpers.InMethod();
FetchInvDescHandler handler = new FetchInvDescHandler(m_scene.InventoryService, null, m_scene);
string request = "<llsd><map><key>folders</key><array>";
request += "<map><key>fetch_folders</key><integer>1</integer><key>fetch_items</key><boolean>1</boolean><key>folder_id</key><uuid>";
request += m_rootFolderID;
request += "</uuid><key>owner_id</key><uuid>00000000-0000-0000-0000-000000000000</uuid><key>sort_order</key><integer>1</integer></map>";
request += "<map><key>fetch_folders</key><integer>1</integer><key>fetch_items</key><boolean>1</boolean><key>folder_id</key><uuid>";
request += m_notecardsFolder;
request += "</uuid><key>owner_id</key><uuid>00000000-0000-0000-0000-000000000000</uuid><key>sort_order</key><integer>1</integer></map>";
request += "<map><key>fetch_folders</key><integer>1</integer><key>fetch_items</key><boolean>1</boolean><key>folder_id</key><uuid>";
request += m_rootFolderID;
request += "</uuid><key>owner_id</key><uuid>00000000-0000-0000-0000-000000000000</uuid><key>sort_order</key><integer>1</integer></map>";
request += "<map><key>fetch_folders</key><integer>1</integer><key>fetch_items</key><boolean>1</boolean><key>folder_id</key><uuid>";
request += m_notecardsFolder;
request += "</uuid><key>owner_id</key><uuid>00000000-0000-0000-0000-000000000000</uuid><key>sort_order</key><integer>1</integer></map>";
request += "</array></map></llsd>";
string llsdresponse = dorequest(handler, request);
Console.WriteLine(llsdresponse);
string root_folder = "<key>folder_id</key><uuid>" + m_rootFolderID + "</uuid>";
string notecards_folder = "<key>folder_id</key><uuid>" + m_notecardsFolder + "</uuid>";
Assert.That(llsdresponse.Contains(root_folder), "Missing root folder");
Assert.That(llsdresponse.Contains(notecards_folder), "Missing notecards folder");
int count = Regex.Matches(llsdresponse, root_folder).Count;
Assert.AreEqual(1, count, "More than 1 root folder in response");
count = Regex.Matches(llsdresponse, notecards_folder).Count;
Assert.AreEqual(2, count, "More than 1 notecards folder in response"); // Notecards will also be under root, so 2
}
[Test]
public void Test_005_FolderZero()
{
TestHelpers.InMethod();
Init();
FetchInvDescHandler handler = new FetchInvDescHandler(m_scene.InventoryService, null, m_scene);
string request = "<llsd><map><key>folders</key><array><map><key>fetch_folders</key><integer>1</integer><key>fetch_items</key><boolean>1</boolean><key>folder_id</key><uuid>";
request += UUID.Zero;
request += "</uuid><key>owner_id</key><uuid>00000000-0000-0000-0000-000000000000</uuid><key>sort_order</key><integer>1</integer></map></array></map></llsd>";
string llsdresponse = dorequest(handler, request);
Assert.That(llsdresponse != null, Is.True, "Incorrect null response");
Assert.That(llsdresponse != string.Empty, Is.True, "Incorrect empty response");
// we do return a answer now
//Assert.That(llsdresponse.Contains("bad_folders</key><array><uuid>00000000-0000-0000-0000-000000000000"), Is.True, "Folder Zero should be a bad folder");
Console.WriteLine(llsdresponse);
}
}
}

View File

@ -0,0 +1,124 @@
/*
* Copyright (c) Contributors, http://opensimulator.org/
* See CONTRIBUTORS.TXT for a full list of copyright holders.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the OpenSimulator Project nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
using System;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using log4net;
using Nini.Config;
using OpenMetaverse;
using OpenMetaverse.StructuredData;
using OpenSim.Framework;
using OpenSim.Framework.Capabilities;
using OpenSim.Region.Framework.Interfaces;
using OpenSim.Framework.Servers.HttpServer;
using OpenSim.Services.Interfaces;
using Caps = OpenSim.Framework.Capabilities.Caps;
using OSDArray = OpenMetaverse.StructuredData.OSDArray;
using OSDMap = OpenMetaverse.StructuredData.OSDMap;
namespace OpenSim.Capabilities.Handlers
{
public class FetchInventory2Handler
{
// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private IInventoryService m_inventoryService;
public FetchInventory2Handler(IInventoryService invService)
{
m_inventoryService = invService;
}
public string FetchInventoryRequest(string request, string path, string param, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
{
// m_log.DebugFormat("[FETCH INVENTORY HANDLER]: Received FetchInventory capabilty request");
OSDMap requestmap = (OSDMap)OSDParser.DeserializeLLSDXml(Utils.StringToBytes(request));
OSDArray itemsRequested = (OSDArray)requestmap["items"];
string reply;
LLSDFetchInventory llsdReply = new LLSDFetchInventory();
foreach (OSDMap osdItemId in itemsRequested)
{
UUID itemId = osdItemId["item_id"].AsUUID();
InventoryItemBase item = m_inventoryService.GetItem(new InventoryItemBase(itemId));
if (item != null)
{
// We don't know the agent that this request belongs to so we'll use the agent id of the item
// which will be the same for all items.
llsdReply.agent_id = item.Owner;
llsdReply.items.Array.Add(ConvertInventoryItem(item));
}
}
reply = LLSDHelpers.SerialiseLLSDReply(llsdReply);
return reply;
}
/// <summary>
/// Convert an internal inventory item object into an LLSD object.
/// </summary>
/// <param name="invItem"></param>
/// <returns></returns>
private LLSDInventoryItem ConvertInventoryItem(InventoryItemBase invItem)
{
LLSDInventoryItem llsdItem = new LLSDInventoryItem();
llsdItem.asset_id = invItem.AssetID;
llsdItem.created_at = invItem.CreationDate;
llsdItem.desc = invItem.Description;
llsdItem.flags = (int)invItem.Flags;
llsdItem.item_id = invItem.ID;
llsdItem.name = invItem.Name;
llsdItem.parent_id = invItem.Folder;
llsdItem.type = invItem.AssetType;
llsdItem.inv_type = invItem.InvType;
llsdItem.permissions = new LLSDPermissions();
llsdItem.permissions.creator_id = invItem.CreatorIdAsUuid;
llsdItem.permissions.base_mask = (int)invItem.CurrentPermissions;
llsdItem.permissions.everyone_mask = (int)invItem.EveryOnePermissions;
llsdItem.permissions.group_id = invItem.GroupID;
llsdItem.permissions.group_mask = (int)invItem.GroupPermissions;
llsdItem.permissions.is_owner_group = invItem.GroupOwned;
llsdItem.permissions.next_owner_mask = (int)invItem.NextPermissions;
llsdItem.permissions.owner_id = invItem.Owner;
llsdItem.permissions.owner_mask = (int)invItem.CurrentPermissions;
llsdItem.sale_info = new LLSDSaleInfo();
llsdItem.sale_info.sale_price = invItem.SalePrice;
llsdItem.sale_info.sale_type = invItem.SaleType;
return llsdItem;
}
}
}

View File

@ -61,7 +61,7 @@ namespace OpenSim.Capabilities.Handlers
if (m_InventoryService == null)
throw new Exception(String.Format("Failed to load InventoryService from {0}; config is {1}", invService, m_ConfigName));
FetchInventory2Handler fiHandler = new FetchInventory2Handler(m_InventoryService, UUID.Zero);
FetchInventory2Handler fiHandler = new FetchInventory2Handler(m_InventoryService);
IRequestHandler reqHandler
= new RestStreamHandler(
"POST", "/CAPS/FetchInventory/", fiHandler.FetchInventoryRequest, "FetchInventory", null);

View File

@ -1,190 +0,0 @@
/*
* Copyright (c) Contributors, http://opensimulator.org/
* See CONTRIBUTORS.TXT for a full list of copyright holders.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the OpenSimulator Project nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
using System;
using System.Collections;
using System.Collections.Generic;
using System.Net;
using System.Reflection;
using log4net;
using Nini.Config;
using OpenMetaverse;
using OpenMetaverse.StructuredData;
using OpenSim.Framework;
using OpenSim.Framework.Servers;
using OpenSim.Framework.Servers.HttpServer;
using OpenSim.Services.Interfaces;
using Caps = OpenSim.Framework.Capabilities.Caps;
namespace OpenSim.Capabilities.Handlers
{
public class GetAssetsHandler
{
private static readonly ILog m_log =
LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private static readonly Dictionary<string, AssetType> queryTypes = new Dictionary<string, AssetType>()
{
{"texture_id", AssetType.Texture},
{"sound_id", AssetType.Sound},
{"callcard_id", AssetType.CallingCard},
{"landmark_id", AssetType.Landmark},
{"script_id", AssetType.LSLText},
{"clothing_id", AssetType.Clothing},
{"object_id", AssetType.Object},
{"notecard_id", AssetType.Notecard},
{"lsltext_id", AssetType.LSLText},
{"lslbyte_id", AssetType.LSLBytecode},
{"txtr_tga_id", AssetType.TextureTGA},
{"bodypart_id", AssetType.Bodypart},
{"snd_wav_id", AssetType.SoundWAV},
{"img_tga_id", AssetType.ImageTGA},
{"jpeg_id", AssetType.ImageJPEG},
{"animatn_id", AssetType.Animation},
{"gesture_id", AssetType.Gesture},
{"mesh_id", AssetType.Mesh},
{"settings_id", AssetType.Settings}
};
private IAssetService m_assetService;
public GetAssetsHandler(IAssetService assService)
{
m_assetService = assService;
}
public void Handle(OSHttpRequest req, OSHttpResponse response)
{
response.ContentType = "text/plain";
if (m_assetService == null)
{
response.StatusCode = (int)HttpStatusCode.ServiceUnavailable;
response.KeepAlive = false;
return;
}
response.StatusCode = (int)HttpStatusCode.BadRequest;
var queries = req.QueryAsDictionary;
if(queries.Count == 0)
return;
AssetType type = AssetType.Unknown;
string assetStr = string.Empty;
foreach (KeyValuePair<string,string> kvp in queries)
{
if (queryTypes.ContainsKey(kvp.Key))
{
type = queryTypes[kvp.Key];
assetStr = kvp.Value;
break;
}
}
if(type == AssetType.Unknown)
{
//m_log.Warn("[GETASSET]: Unknown type: " + query);
m_log.Warn("[GETASSET]: Unknown type");
response.StatusCode = (int)HttpStatusCode.NotFound;
return;
}
if (String.IsNullOrEmpty(assetStr))
return;
UUID assetID = UUID.Zero;
if(!UUID.TryParse(assetStr, out assetID))
return;
AssetBase asset = m_assetService.Get(assetID.ToString());
if(asset == null)
{
// m_log.Warn("[GETASSET]: not found: " + query + " " + assetStr);
response.StatusCode = (int)HttpStatusCode.NotFound;
return;
}
if (asset.Type != (sbyte)type)
return;
int len = asset.Data.Length;
string range = null;
if (req.Headers["Range"] != null)
range = req.Headers["Range"];
else if (req.Headers["range"] != null)
range = req.Headers["range"];
// range request
int start, end;
if (Util.TryParseHttpRange(range, out start, out end))
{
// Before clamping start make sure we can satisfy it in order to avoid
// sending back the last byte instead of an error status
if (start >= asset.Data.Length)
{
response.StatusCode = (int)HttpStatusCode.RequestedRangeNotSatisfiable;
return;
}
if (end == -1)
end = asset.Data.Length - 1;
else
end = Utils.Clamp(end, 0, asset.Data.Length - 1);
start = Utils.Clamp(start, 0, end);
len = end - start + 1;
//m_log.Debug("Serving " + start + " to " + end + " of " + texture.Data.Length + " bytes for texture " + texture.ID);
response.AddHeader("Content-Range", String.Format("bytes {0}-{1}/{2}", start, end, asset.Data.Length));
response.StatusCode = (int)HttpStatusCode.PartialContent;
response.RawBufferStart = start;
}
else
response.StatusCode = (int)HttpStatusCode.OK;
response.ContentType = asset.Metadata.ContentType;
response.RawBuffer = asset.Data;
response.RawBufferLen = len;
if (type == AssetType.Mesh || type == AssetType.Texture)
{
if(len > 8196)
{
//if(type == AssetType.Texture && ((asset.Flags & AssetFlags.AvatarBake)!= 0))
// responsedata["prio"] = 1;
//else
response.Priority = 2;
}
else
response.Priority = 1;
}
else
response.Priority = -1;
}
}
}

View File

@ -30,6 +30,7 @@ using System.Collections;
using System.Collections.Specialized;
using System.Reflection;
using System.IO;
using System.Text;
using System.Web;
using log4net;
using Nini.Config;
@ -43,113 +44,71 @@ using Caps = OpenSim.Framework.Capabilities.Caps;
namespace OpenSim.Capabilities.Handlers
{
public class GetMeshHandler
public class GetMeshHandler : BaseStreamHandler
{
private static readonly ILog m_log =
LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
// private static readonly ILog m_log =
// LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private IAssetService m_assetService;
public const string DefaultFormat = "vnd.ll.mesh";
public GetMeshHandler(IAssetService assService)
public GetMeshHandler(string path, IAssetService assService, string name, string description)
: base("GET", path, name, description)
{
m_assetService = assService;
}
public Hashtable Handle(Hashtable request)
protected override byte[] ProcessRequest(string path, Stream request, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
{
return ProcessGetMesh(request, UUID.Zero, null); ;
}
// Try to parse the texture ID from the request URL
NameValueCollection query = HttpUtility.ParseQueryString(httpRequest.Url.Query);
string meshStr = query.GetOne("mesh_id");
public Hashtable ProcessGetMesh(Hashtable request, UUID AgentId, Caps cap)
{
Hashtable responsedata = new Hashtable();
if (m_assetService == null)
{
responsedata["int_response_code"] = (int)System.Net.HttpStatusCode.ServiceUnavailable;
responsedata["str_response_string"] = "The asset service is unavailable";
responsedata["keepalive"] = false;
return responsedata;
}
responsedata["int_response_code"] = (int)System.Net.HttpStatusCode.BadRequest;
responsedata["content_type"] = "text/plain";
responsedata["int_bytes"] = 0;
string meshStr = string.Empty;
if (request.ContainsKey("mesh_id"))
meshStr = request["mesh_id"].ToString();
if (String.IsNullOrEmpty(meshStr))
return responsedata;
// m_log.DebugFormat("Fetching mesh {0}", meshStr);
UUID meshID = UUID.Zero;
if(!UUID.TryParse(meshStr, out meshID))
return responsedata;
AssetBase mesh = m_assetService.Get(meshID.ToString());
if(mesh == null)
if (!String.IsNullOrEmpty(meshStr) && UUID.TryParse(meshStr, out meshID))
{
responsedata["int_response_code"] = (int)System.Net.HttpStatusCode.NotFound;
responsedata["str_response_string"] = "Mesh not found.";
return responsedata;
}
if (mesh.Type != (SByte)AssetType.Mesh)
{
responsedata["str_response_string"] = "Asset isn't a mesh.";
return responsedata;
}
string range = String.Empty;
if (((Hashtable)request["headers"])["range"] != null)
range = (string)((Hashtable)request["headers"])["range"];
else if (((Hashtable)request["headers"])["Range"] != null)
range = (string)((Hashtable)request["headers"])["Range"];
responsedata["content_type"] = "application/vnd.ll.mesh";
if (String.IsNullOrEmpty(range))
{
// full mesh
responsedata["str_response_string"] = Convert.ToBase64String(mesh.Data);
responsedata["int_response_code"] = (int)System.Net.HttpStatusCode.OK;
return responsedata;
}
// range request
int start, end;
if (Util.TryParseHttpRange(range, out start, out end))
{
// Before clamping start make sure we can satisfy it in order to avoid
// sending back the last byte instead of an error status
if (start >= mesh.Data.Length)
if (m_assetService == null)
{
responsedata["str_response_string"] = "This range doesnt exist.";
return responsedata;
httpResponse.StatusCode = 404;
httpResponse.ContentType = "text/plain";
byte[] data = Encoding.UTF8.GetBytes("The asset service is unavailable. So is your mesh.");
httpResponse.Body.Write(data, 0, data.Length);
return null;
}
end = Utils.Clamp(end, 0, mesh.Data.Length - 1);
start = Utils.Clamp(start, 0, end);
int len = end - start + 1;
AssetBase mesh = m_assetService.Get(meshID.ToString());
//m_log.Debug("Serving " + start + " to " + end + " of " + texture.Data.Length + " bytes for texture " + texture.ID);
Hashtable headers = new Hashtable();
headers["Content-Range"] = String.Format("bytes {0}-{1}/{2}", start, end, mesh.Data.Length);
responsedata["headers"] = headers;
responsedata["int_response_code"] = (int)System.Net.HttpStatusCode.PartialContent;
byte[] d = new byte[len];
Array.Copy(mesh.Data, start, d, 0, len);
responsedata["bin_response_data"] = d;
responsedata["int_bytes"] = len;
return responsedata;
if (mesh != null)
{
if (mesh.Type == (SByte)AssetType.Mesh)
{
byte[] data = mesh.Data;
httpResponse.Body.Write(data, 0, data.Length);
httpResponse.ContentType = "application/vnd.ll.mesh";
httpResponse.StatusCode = 200;
}
// Optionally add additional mesh types here
else
{
httpResponse.StatusCode = 404;
httpResponse.ContentType = "text/plain";
byte[] data = Encoding.UTF8.GetBytes("Unfortunately, this asset isn't a mesh.");
httpResponse.Body.Write(data, 0, data.Length);
httpResponse.KeepAlive = false;
}
}
else
{
httpResponse.StatusCode = 404;
httpResponse.ContentType = "text/plain";
byte[] data = Encoding.UTF8.GetBytes("Your Mesh wasn't found. Sorry!");
httpResponse.Body.Write(data, 0, data.Length);
httpResponse.KeepAlive = false;
}
}
m_log.Warn("[GETMESH]: Failed to parse a range from GetMesh request, sending full asset: " + (string)request["uri"]);
responsedata["str_response_string"] = Convert.ToBase64String(mesh.Data);
responsedata["int_response_code"] = (int)System.Net.HttpStatusCode.OK;
return responsedata;
return null;
}
}
}

View File

@ -25,13 +25,16 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
using Nini.Config;
using OpenMetaverse;
using OpenSim.Framework.Servers.HttpServer;
using OpenSim.Server.Base;
using OpenSim.Server.Handlers.Base;
using OpenSim.Services.Interfaces;
using System;
using System.Collections;
using Nini.Config;
using OpenSim.Server.Base;
using OpenSim.Services.Interfaces;
using OpenSim.Framework.Servers.HttpServer;
using OpenSim.Server.Handlers.Base;
using OpenSim.Framework.Servers;
using OpenMetaverse;
namespace OpenSim.Capabilities.Handlers
{
@ -62,17 +65,8 @@ namespace OpenSim.Capabilities.Handlers
if (m_AssetService == null)
throw new Exception(String.Format("Failed to load AssetService from {0}; config is {1}", assetService, m_ConfigName));
string rurl = serverConfig.GetString("GetMeshRedirectURL");
GetMeshHandler gmeshHandler = new GetMeshHandler(m_AssetService);
IRequestHandler reqHandler
= new RestHTTPHandler(
"GET",
"/" + UUID.Random(),
httpMethod => gmeshHandler.ProcessGetMesh(httpMethod, UUID.Zero, null),
"GetMesh",
null);
server.AddStreamHandler(reqHandler); ;
server.AddStreamHandler(
new GetMeshHandler("/CAPS/GetMesh/" /*+ UUID.Random() */, m_AssetService, "GetMesh", null));
}
}
}

View File

@ -47,41 +47,46 @@ using Caps = OpenSim.Framework.Capabilities.Caps;
namespace OpenSim.Capabilities.Handlers
{
public class GetTextureHandler
public class GetTextureHandler : BaseStreamHandler
{
private static readonly ILog m_log =
LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private IAssetService m_assetService;
public const string DefaultFormat = "x-j2c";
public GetTextureHandler(IAssetService assService)
// TODO: Change this to a config option
private string m_RedirectURL = null;
public GetTextureHandler(string path, IAssetService assService, string name, string description, string redirectURL)
: base("GET", path, name, description)
{
m_assetService = assService;
m_RedirectURL = redirectURL;
if (m_RedirectURL != null && !m_RedirectURL.EndsWith("/"))
m_RedirectURL += "/";
}
public Hashtable Handle(Hashtable request)
protected override byte[] ProcessRequest(string path, Stream request, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
{
Hashtable ret = new Hashtable();
ret["int_response_code"] = (int)System.Net.HttpStatusCode.NotFound;
ret["content_type"] = "text/plain";
ret["int_bytes"] = 0;
string textureStr = (string)request["texture_id"];
string format = (string)request["format"];
// Try to parse the texture ID from the request URL
NameValueCollection query = HttpUtility.ParseQueryString(httpRequest.Url.Query);
string textureStr = query.GetOne("texture_id");
string format = query.GetOne("format");
//m_log.DebugFormat("[GETTEXTURE]: called {0}", textureStr);
if (m_assetService == null)
{
m_log.Error("[GETTEXTURE]: Cannot fetch texture " + textureStr + " without an asset service");
httpResponse.StatusCode = (int)System.Net.HttpStatusCode.NotFound;
}
UUID textureID;
if (!String.IsNullOrEmpty(textureStr) && UUID.TryParse(textureStr, out textureID))
{
// m_log.DebugFormat("[GETTEXTURE]: Received request for texture id {0}", textureID);
string[] formats;
if (!string.IsNullOrEmpty(format))
{
@ -89,50 +94,41 @@ namespace OpenSim.Capabilities.Handlers
}
else
{
formats = new string[1] { DefaultFormat }; // default
if (((Hashtable)request["headers"])["Accept"] != null)
formats = WebUtil.GetPreferredImageTypes((string)((Hashtable)request["headers"])["Accept"]);
formats = WebUtil.GetPreferredImageTypes(httpRequest.Headers.Get("Accept"));
if (formats.Length == 0)
formats = new string[1] { DefaultFormat }; // default
}
// OK, we have an array with preferred formats, possibly with only one entry
bool foundtexture = false;
httpResponse.StatusCode = (int)System.Net.HttpStatusCode.NotFound;
foreach (string f in formats)
{
foundtexture = FetchTexture(request, ret, textureID, f);
if (foundtexture)
if (FetchTexture(httpRequest, httpResponse, textureID, f))
break;
}
if (!foundtexture)
{
ret["int_response_code"] = 404;
ret["error_status_text"] = "not found";
ret["str_response_string"] = "not found";
ret["content_type"] = "text/plain";
ret["int_bytes"] = 0;
}
}
else
{
m_log.Warn("[GETTEXTURE]: Failed to parse a texture_id from GetTexture request: " + (string)request["uri"]);
m_log.Warn("[GETTEXTURE]: Failed to parse a texture_id from GetTexture request: " + httpRequest.Url);
}
// m_log.DebugFormat(
// "[GETTEXTURE]: For texture {0} sending back response {1}, data length {2}",
// textureID, httpResponse.StatusCode, httpResponse.ContentLength);
return ret;
return null;
}
/// <summary>
///
///
/// </summary>
/// <param name="httpRequest"></param>
/// <param name="httpResponse"></param>
/// <param name="textureID"></param>
/// <param name="format"></param>
/// <returns>False for "caller try another codec"; true otherwise</returns>
private bool FetchTexture(Hashtable request, Hashtable response, UUID textureID, string format)
private bool FetchTexture(IOSHttpRequest httpRequest, IOSHttpResponse httpResponse, UUID textureID, string format)
{
// m_log.DebugFormat("[GETTEXTURE]: {0} with requested format {1}", textureID, format);
AssetBase texture;
@ -141,76 +137,92 @@ namespace OpenSim.Capabilities.Handlers
if (format != DefaultFormat)
fullID = fullID + "-" + format;
// try the cache
texture = m_assetService.GetCached(fullID);
if (texture == null)
if (!String.IsNullOrEmpty(m_RedirectURL))
{
//m_log.DebugFormat("[GETTEXTURE]: texture was not in the cache");
// Fetch locally or remotely. Misses return a 404
texture = m_assetService.Get(textureID.ToString());
// Only try to fetch locally cached textures. Misses are redirected
texture = m_assetService.GetCached(fullID);
if (texture != null)
{
if (texture.Type != (sbyte)AssetType.Texture)
return true;
if (format == DefaultFormat)
{
WriteTextureData(request, response, texture, format);
return true;
}
else
{
AssetBase newTexture = new AssetBase(texture.ID + "-" + format, texture.Name, (sbyte)AssetType.Texture, texture.Metadata.CreatorID);
newTexture.Data = ConvertTextureData(texture, format);
if (newTexture.Data.Length == 0)
return false; // !!! Caller try another codec, please!
newTexture.Flags = AssetFlags.Collectable;
newTexture.Temporary = true;
newTexture.Local = true;
m_assetService.Store(newTexture);
WriteTextureData(request, response, newTexture, format);
httpResponse.StatusCode = (int)System.Net.HttpStatusCode.NotFound;
return true;
}
WriteTextureData(httpRequest, httpResponse, texture, format);
}
}
else // it was on the cache
{
//m_log.DebugFormat("[GETTEXTURE]: texture was in the cache");
WriteTextureData(request, response, texture, format);
return true;
}
else
{
string textureUrl = m_RedirectURL + "?texture_id="+ textureID.ToString();
m_log.Debug("[GETTEXTURE]: Redirecting texture request to " + textureUrl);
httpResponse.StatusCode = (int)OSHttpStatusCode.RedirectMovedPermanently;
httpResponse.RedirectLocation = textureUrl;
return true;
}
}
else // no redirect
{
// try the cache
texture = m_assetService.GetCached(fullID);
//response = new Hashtable();
if (texture == null)
{
// m_log.DebugFormat("[GETTEXTURE]: texture was not in the cache");
// Fetch locally or remotely. Misses return a 404
texture = m_assetService.Get(textureID.ToString());
if (texture != null)
{
if (texture.Type != (sbyte)AssetType.Texture)
{
httpResponse.StatusCode = (int)System.Net.HttpStatusCode.NotFound;
return true;
}
if (format == DefaultFormat)
{
WriteTextureData(httpRequest, httpResponse, texture, format);
return true;
}
else
{
AssetBase newTexture = new AssetBase(texture.ID + "-" + format, texture.Name, (sbyte)AssetType.Texture, texture.Metadata.CreatorID);
newTexture.Data = ConvertTextureData(texture, format);
if (newTexture.Data.Length == 0)
return false; // !!! Caller try another codec, please!
newTexture.Flags = AssetFlags.Collectable;
newTexture.Temporary = true;
newTexture.Local = true;
m_assetService.Store(newTexture);
WriteTextureData(httpRequest, httpResponse, newTexture, format);
return true;
}
}
}
else // it was on the cache
{
// m_log.DebugFormat("[GETTEXTURE]: texture was in the cache");
WriteTextureData(httpRequest, httpResponse, texture, format);
return true;
}
}
//WriteTextureData(request,response,null,format);
// not found
//m_log.Warn("[GETTEXTURE]: Texture " + textureID + " not found");
return false;
// m_log.Warn("[GETTEXTURE]: Texture " + textureID + " not found");
httpResponse.StatusCode = (int)System.Net.HttpStatusCode.NotFound;
return true;
}
private void WriteTextureData(Hashtable request, Hashtable response, AssetBase texture, string format)
private void WriteTextureData(IOSHttpRequest request, IOSHttpResponse response, AssetBase texture, string format)
{
Hashtable headers = new Hashtable();
response["headers"] = headers;
string range = String.Empty;
if (((Hashtable)request["headers"])["range"] != null)
range = (string)((Hashtable)request["headers"])["range"];
else if (((Hashtable)request["headers"])["Range"] != null)
range = (string)((Hashtable)request["headers"])["Range"];
string range = request.Headers.GetOne("Range");
if (!String.IsNullOrEmpty(range)) // JP2's only
{
// Range request
int start, end;
if (Util.TryParseHttpRange(range, out start, out end))
if (TryParseRange(range, out start, out end))
{
// Before clamping start make sure we can satisfy it in order to avoid
// sending back the last byte instead of an error status
@ -232,8 +244,10 @@ namespace OpenSim.Capabilities.Handlers
// However, if we return PartialContent (or OK) instead, the viewer will display that resolution.
// response.StatusCode = (int)System.Net.HttpStatusCode.RequestedRangeNotSatisfiable;
// viewers don't seem to handle RequestedRangeNotSatisfiable and keep retrying with same parameters
response["int_response_code"] = (int)System.Net.HttpStatusCode.NotFound;
// response.AddHeader("Content-Range", String.Format("bytes */{0}", texture.Data.Length));
// response.StatusCode = (int)System.Net.HttpStatusCode.OK;
response.StatusCode = (int)System.Net.HttpStatusCode.PartialContent;
response.ContentType = texture.Metadata.ContentType;
}
else
{
@ -248,35 +262,41 @@ namespace OpenSim.Capabilities.Handlers
// m_log.Debug("Serving " + start + " to " + end + " of " + texture.Data.Length + " bytes for texture " + texture.ID);
response["content-type"] = texture.Metadata.ContentType;
response["int_response_code"] = (int)System.Net.HttpStatusCode.PartialContent;
headers["Content-Range"] = String.Format("bytes {0}-{1}/{2}", start, end, texture.Data.Length);
// Always return PartialContent, even if the range covered the entire data length
// We were accidentally sending back 404 before in this situation
// https://issues.apache.org/bugzilla/show_bug.cgi?id=51878 supports sending 206 even if the
// entire range is requested, and viewer 3.2.2 (and very probably earlier) seems fine with this.
//
// We also do not want to send back OK even if the whole range was satisfiable since this causes
// HTTP textures on at least Imprudence 1.4.0-beta2 to never display the final texture quality.
// if (end > maxEnd)
// response.StatusCode = (int)System.Net.HttpStatusCode.OK;
// else
response.StatusCode = (int)System.Net.HttpStatusCode.PartialContent;
byte[] d = new byte[len];
Array.Copy(texture.Data, start, d, 0, len);
response["bin_response_data"] = d;
response["int_bytes"] = len;
response.ContentLength = len;
response.ContentType = texture.Metadata.ContentType;
response.AddHeader("Content-Range", String.Format("bytes {0}-{1}/{2}", start, end, texture.Data.Length));
response.Body.Write(texture.Data, start, len);
}
}
else
{
m_log.Warn("[GETTEXTURE]: Malformed Range header: " + range);
response["int_response_code"] = (int)System.Net.HttpStatusCode.BadRequest;
response.StatusCode = (int)System.Net.HttpStatusCode.BadRequest;
}
}
else // JP2's or other formats
{
// Full content request
response["int_response_code"] = (int)System.Net.HttpStatusCode.OK;
response.StatusCode = (int)System.Net.HttpStatusCode.OK;
response.ContentLength = texture.Data.Length;
if (format == DefaultFormat)
response["content_type"] = texture.Metadata.ContentType;
response.ContentType = texture.Metadata.ContentType;
else
response["content_type"] = "image/" + format;
response["bin_response_data"] = texture.Data;
response["int_bytes"] = texture.Data.Length;
// response.Body.Write(texture.Data, 0, texture.Data.Length);
response.ContentType = "image/" + format;
response.Body.Write(texture.Data, 0, texture.Data.Length);
}
// if (response.StatusCode < 200 || response.StatusCode > 299)
@ -289,41 +309,86 @@ namespace OpenSim.Capabilities.Handlers
// texture.FullID, range, response.StatusCode, response.ContentLength, texture.Data.Length);
}
/// <summary>
/// Parse a range header.
/// </summary>
/// <remarks>
/// As per http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html,
/// this obeys range headers with two values (e.g. 533-4165) and no second value (e.g. 533-).
/// Where there is no value, -1 is returned.
/// FIXME: Need to cover the case where only a second value is specified (e.g. -4165), probably by returning -1
/// for start.</remarks>
/// <returns></returns>
/// <param name='header'></param>
/// <param name='start'>Start of the range. Undefined if this was not a number.</param>
/// <param name='end'>End of the range. Will be -1 if no end specified. Undefined if there was a raw string but this was not a number.</param>
private bool TryParseRange(string header, out int start, out int end)
{
start = end = 0;
if (header.StartsWith("bytes="))
{
string[] rangeValues = header.Substring(6).Split('-');
if (rangeValues.Length == 2)
{
if (!Int32.TryParse(rangeValues[0], out start))
return false;
string rawEnd = rangeValues[1];
if (rawEnd == "")
{
end = -1;
return true;
}
else if (Int32.TryParse(rawEnd, out end))
{
return true;
}
}
}
start = end = 0;
return false;
}
private byte[] ConvertTextureData(AssetBase texture, string format)
{
m_log.DebugFormat("[GETTEXTURE]: Converting texture {0} to {1}", texture.ID, format);
byte[] data = new byte[0];
MemoryStream imgstream = new MemoryStream();
Bitmap mTexture = null;
ManagedImage managedImage = null;
Image image = null;
Bitmap mTexture = new Bitmap(1, 1);
ManagedImage managedImage;
Image image = (Image)mTexture;
try
{
// Taking our jpeg2000 data, decoding it, then saving it to a byte array with regular data
imgstream = new MemoryStream();
// Decode image to System.Drawing.Image
if (OpenJPEG.DecodeToImage(texture.Data, out managedImage, out image) && image != null)
if (OpenJPEG.DecodeToImage(texture.Data, out managedImage, out image))
{
// Save to bitmap
mTexture = new Bitmap(image);
using(EncoderParameters myEncoderParameters = new EncoderParameters())
{
myEncoderParameters.Param[0] = new EncoderParameter(Encoder.Quality,95L);
EncoderParameters myEncoderParameters = new EncoderParameters();
myEncoderParameters.Param[0] = new EncoderParameter(Encoder.Quality, 95L);
// Save bitmap to stream
ImageCodecInfo codec = GetEncoderInfo("image/" + format);
if (codec != null)
{
mTexture.Save(imgstream, codec, myEncoderParameters);
// Save bitmap to stream
ImageCodecInfo codec = GetEncoderInfo("image/" + format);
if (codec != null)
{
mTexture.Save(imgstream, codec, myEncoderParameters);
// Write the stream to a byte array for output
data = imgstream.ToArray();
}
else
m_log.WarnFormat("[GETTEXTURE]: No such codec {0}", format);
data = imgstream.ToArray();
}
else
m_log.WarnFormat("[GETTEXTURE]: No such codec {0}", format);
}
}
catch (Exception e)
@ -340,10 +405,11 @@ namespace OpenSim.Capabilities.Handlers
if (image != null)
image.Dispose();
if(managedImage != null)
managedImage.Clear();
if (imgstream != null)
{
imgstream.Close();
imgstream.Dispose();
}
}
return data;
@ -362,4 +428,4 @@ namespace OpenSim.Capabilities.Handlers
return null;
}
}
}
}

View File

@ -1,394 +0,0 @@
/*
* Copyright (c) Contributors, http://opensimulator.org/
* See CONTRIBUTORS.TXT for a full list of copyright holders.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the OpenSimulator Project nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
using System;
using System.Collections;
using System.Collections.Specialized;
using System.Drawing;
using System.Drawing.Imaging;
using System.Reflection;
using System.IO;
using System.Net;
using System.Web;
using log4net;
using Nini.Config;
using OpenMetaverse;
using OpenMetaverse.StructuredData;
using OpenMetaverse.Imaging;
using OpenSim.Framework;
using OpenSim.Framework.Servers;
using OpenSim.Framework.Servers.HttpServer;
using OpenSim.Region.Framework.Interfaces;
using OpenSim.Services.Interfaces;
using Caps = OpenSim.Framework.Capabilities.Caps;
namespace OpenSim.Capabilities.Handlers
{
public class GetTextureRobustHandler : BaseStreamHandler
{
private static readonly ILog m_log =
LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private IAssetService m_assetService;
public const string DefaultFormat = "x-j2c";
// TODO: Change this to a config option
private string m_RedirectURL = null;
public GetTextureRobustHandler(string path, IAssetService assService, string name, string description, string redirectURL)
: base("GET", path, name, description)
{
m_assetService = assService;
m_RedirectURL = redirectURL;
if (m_RedirectURL != null && !m_RedirectURL.EndsWith("/"))
m_RedirectURL += "/";
}
protected override byte[] ProcessRequest(string path, Stream request, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
{
// Try to parse the texture ID from the request URL
NameValueCollection query = HttpUtility.ParseQueryString(httpRequest.Url.Query);
string textureStr = query.GetOne("texture_id");
string format = query.GetOne("format");
//m_log.DebugFormat("[GETTEXTURE]: called {0}", textureStr);
if (m_assetService == null)
{
m_log.Error("[GETTEXTURE]: Cannot fetch texture " + textureStr + " without an asset service");
httpResponse.StatusCode = (int)System.Net.HttpStatusCode.NotFound;
return null;
}
UUID textureID;
if (!String.IsNullOrEmpty(textureStr) && UUID.TryParse(textureStr, out textureID))
{
// m_log.DebugFormat("[GETTEXTURE]: Received request for texture id {0}", textureID);
string[] formats;
if (!string.IsNullOrEmpty(format))
{
formats = new string[1] { format.ToLower() };
}
else
{
formats = WebUtil.GetPreferredImageTypes(httpRequest.Headers.Get("Accept"));
if (formats.Length == 0)
formats = new string[1] { DefaultFormat }; // default
}
// OK, we have an array with preferred formats, possibly with only one entry
httpResponse.StatusCode = (int)System.Net.HttpStatusCode.NotFound;
foreach (string f in formats)
{
if (FetchTexture(httpRequest, httpResponse, textureID, f))
break;
}
}
else
{
m_log.Warn("[GETTEXTURE]: Failed to parse a texture_id from GetTexture request: " + httpRequest.Url);
}
// m_log.DebugFormat(
// "[GETTEXTURE]: For texture {0} sending back response {1}, data length {2}",
// textureID, httpResponse.StatusCode, httpResponse.ContentLength);
return null;
}
/// <summary>
///
/// </summary>
/// <param name="httpRequest"></param>
/// <param name="httpResponse"></param>
/// <param name="textureID"></param>
/// <param name="format"></param>
/// <returns>False for "caller try another codec"; true otherwise</returns>
private bool FetchTexture(IOSHttpRequest httpRequest, IOSHttpResponse httpResponse, UUID textureID, string format)
{
// m_log.DebugFormat("[GETTEXTURE]: {0} with requested format {1}", textureID, format);
if(!String.IsNullOrEmpty(m_RedirectURL))
{
string textureUrl = m_RedirectURL + "?texture_id=" + textureID.ToString();
m_log.Debug("[GETTEXTURE]: Redirecting texture request to " + textureUrl);
httpResponse.StatusCode = (int)HttpStatusCode.Moved;
httpResponse.AddHeader("Location:", textureUrl);
return true;
}
// Fetch, Misses or invalid return a 404
AssetBase texture = m_assetService.Get(textureID.ToString());
if (texture != null)
{
if (texture.Type != (sbyte)AssetType.Texture)
{
httpResponse.StatusCode = (int)System.Net.HttpStatusCode.NotFound;
return true;
}
if (format == DefaultFormat)
{
WriteTextureData(httpRequest, httpResponse, texture, format);
return true;
}
// need to convert format
AssetBase newTexture = new AssetBase(texture.ID + "-" + format, texture.Name, (sbyte)AssetType.Texture, texture.Metadata.CreatorID);
newTexture.Data = ConvertTextureData(texture, format);
if (newTexture.Data.Length == 0)
return false; // !!! Caller try another codec, please!
newTexture.Flags = AssetFlags.Collectable;
newTexture.Temporary = true;
newTexture.Local = true;
WriteTextureData(httpRequest, httpResponse, newTexture, format);
return true;
}
// not found
// m_log.Warn("[GETTEXTURE]: Texture " + textureID + " not found");
httpResponse.StatusCode = (int)System.Net.HttpStatusCode.NotFound;
return true;
}
private void WriteTextureData(IOSHttpRequest request, IOSHttpResponse response, AssetBase texture, string format)
{
string range = request.Headers.GetOne("Range");
if (!String.IsNullOrEmpty(range)) // JP2's only
{
// Range request
int start, end;
if (TryParseRange(range, out start, out end))
{
// Before clamping start make sure we can satisfy it in order to avoid
// sending back the last byte instead of an error status
if (start >= texture.Data.Length)
{
// m_log.DebugFormat(
// "[GETTEXTURE]: Client requested range for texture {0} starting at {1} but texture has end of {2}",
// texture.ID, start, texture.Data.Length);
// Stricly speaking, as per http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html, we should be sending back
// Requested Range Not Satisfiable (416) here. However, it appears that at least recent implementations
// of the Linden Lab viewer (3.2.1 and 3.3.4 and probably earlier), a viewer that has previously
// received a very small texture may attempt to fetch bytes from the server past the
// range of data that it received originally. Whether this happens appears to depend on whether
// the viewer's estimation of how large a request it needs to make for certain discard levels
// (http://wiki.secondlife.com/wiki/Image_System#Discard_Level_and_Mip_Mapping), chiefly discard
// level 2. If this estimate is greater than the total texture size, returning a RequestedRangeNotSatisfiable
// here will cause the viewer to treat the texture as bad and never display the full resolution
// However, if we return PartialContent (or OK) instead, the viewer will display that resolution.
// response.StatusCode = (int)System.Net.HttpStatusCode.RequestedRangeNotSatisfiable;
// response.AddHeader("Content-Range", String.Format("bytes */{0}", texture.Data.Length));
// response.StatusCode = (int)System.Net.HttpStatusCode.OK;
response.StatusCode = (int)System.Net.HttpStatusCode.PartialContent;
response.ContentType = texture.Metadata.ContentType;
}
else
{
// Handle the case where no second range value was given. This is equivalent to requesting
// the rest of the entity.
if (end == -1)
end = int.MaxValue;
end = Utils.Clamp(end, 0, texture.Data.Length - 1);
start = Utils.Clamp(start, 0, end);
int len = end - start + 1;
// m_log.Debug("Serving " + start + " to " + end + " of " + texture.Data.Length + " bytes for texture " + texture.ID);
// Always return PartialContent, even if the range covered the entire data length
// We were accidentally sending back 404 before in this situation
// https://issues.apache.org/bugzilla/show_bug.cgi?id=51878 supports sending 206 even if the
// entire range is requested, and viewer 3.2.2 (and very probably earlier) seems fine with this.
//
// We also do not want to send back OK even if the whole range was satisfiable since this causes
// HTTP textures on at least Imprudence 1.4.0-beta2 to never display the final texture quality.
// if (end > maxEnd)
// response.StatusCode = (int)System.Net.HttpStatusCode.OK;
// else
response.StatusCode = (int)System.Net.HttpStatusCode.PartialContent;
response.ContentLength = len;
response.ContentType = texture.Metadata.ContentType;
response.AddHeader("Content-Range", String.Format("bytes {0}-{1}/{2}", start, end, texture.Data.Length));
response.RawBuffer = texture.Data;
response.RawBufferStart = start;
response.RawBufferLen = len;
}
}
else
{
m_log.Warn("[GETTEXTURE]: Malformed Range header: " + range);
response.StatusCode = (int)System.Net.HttpStatusCode.BadRequest;
}
}
else // JP2's or other formats
{
// Full content request
response.StatusCode = (int)System.Net.HttpStatusCode.OK;
response.ContentLength = texture.Data.Length;
if (format == DefaultFormat)
response.ContentType = texture.Metadata.ContentType;
else
response.ContentType = "image/" + format;
response.RawBuffer = texture.Data;
response.RawBufferStart = 0;
response.RawBufferLen = texture.Data.Length;
}
// if (response.StatusCode < 200 || response.StatusCode > 299)
// m_log.WarnFormat(
// "[GETTEXTURE]: For texture {0} requested range {1} responded {2} with content length {3} (actual {4})",
// texture.FullID, range, response.StatusCode, response.ContentLength, texture.Data.Length);
// else
// m_log.DebugFormat(
// "[GETTEXTURE]: For texture {0} requested range {1} responded {2} with content length {3} (actual {4})",
// texture.FullID, range, response.StatusCode, response.ContentLength, texture.Data.Length);
}
/// <summary>
/// Parse a range header.
/// </summary>
/// <remarks>
/// As per http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html,
/// this obeys range headers with two values (e.g. 533-4165) and no second value (e.g. 533-).
/// Where there is no value, -1 is returned.
/// FIXME: Need to cover the case where only a second value is specified (e.g. -4165), probably by returning -1
/// for start.</remarks>
/// <returns></returns>
/// <param name='header'></param>
/// <param name='start'>Start of the range. Undefined if this was not a number.</param>
/// <param name='end'>End of the range. Will be -1 if no end specified. Undefined if there was a raw string but this was not a number.</param>
private bool TryParseRange(string header, out int start, out int end)
{
start = end = 0;
if (header.StartsWith("bytes="))
{
string[] rangeValues = header.Substring(6).Split('-');
if (rangeValues.Length == 2)
{
if (!Int32.TryParse(rangeValues[0], out start))
return false;
string rawEnd = rangeValues[1];
if (rawEnd == "")
{
end = -1;
return true;
}
else if (Int32.TryParse(rawEnd, out end))
{
return true;
}
}
}
start = end = 0;
return false;
}
private byte[] ConvertTextureData(AssetBase texture, string format)
{
m_log.DebugFormat("[GETTEXTURE]: Converting texture {0} to {1}", texture.ID, format);
byte[] data = new byte[0];
MemoryStream imgstream = new MemoryStream();
Bitmap mTexture = null;
ManagedImage managedImage = null;
Image image = null;
try
{
// Taking our jpeg2000 data, decoding it, then saving it to a byte array with regular data
// Decode image to System.Drawing.Image
if (OpenJPEG.DecodeToImage(texture.Data, out managedImage, out image) && image != null)
{
// Save to bitmap
mTexture = new Bitmap(image);
using(EncoderParameters myEncoderParameters = new EncoderParameters())
{
myEncoderParameters.Param[0] = new EncoderParameter(Encoder.Quality,95L);
// Save bitmap to stream
ImageCodecInfo codec = GetEncoderInfo("image/" + format);
if (codec != null)
{
mTexture.Save(imgstream, codec, myEncoderParameters);
// Write the stream to a byte array for output
data = imgstream.ToArray();
}
else
m_log.WarnFormat("[GETTEXTURE]: No such codec {0}", format);
}
}
}
catch (Exception e)
{
m_log.WarnFormat("[GETTEXTURE]: Unable to convert texture {0} to {1}: {2}", texture.ID, format, e.Message);
}
finally
{
// Reclaim memory, these are unmanaged resources
// If we encountered an exception, one or more of these will be null
if (mTexture != null)
mTexture.Dispose();
if (image != null)
image.Dispose();
if(managedImage != null)
managedImage.Clear();
if (imgstream != null)
imgstream.Dispose();
}
return data;
}
// From msdn
private static ImageCodecInfo GetEncoderInfo(String mimeType)
{
ImageCodecInfo[] encoders;
encoders = ImageCodecInfo.GetImageEncoders();
for (int j = 0; j < encoders.Length; ++j)
{
if (encoders[j].MimeType == mimeType)
return encoders[j];
}
return null;
}
}
}

View File

@ -33,7 +33,6 @@ using OpenSim.Framework.Servers.HttpServer;
using OpenSim.Server.Handlers.Base;
using OpenMetaverse;
namespace OpenSim.Capabilities.Handlers
{
public class GetTextureServerConnector : ServiceConnector
@ -66,8 +65,7 @@ namespace OpenSim.Capabilities.Handlers
string rurl = serverConfig.GetString("GetTextureRedirectURL");
;
server.AddStreamHandler(
new GetTextureRobustHandler("/CAPS/GetTexture", m_AssetService, "GetTexture", null, rurl));
new GetTextureHandler("/CAPS/GetTexture/" /*+ UUID.Random() */, m_AssetService, "GetTexture", null, rurl));
}
}
}
}

View File

@ -38,7 +38,6 @@ using OpenSim.Framework.Servers.HttpServer;
using OpenSim.Region.Framework.Scenes;
using OpenSim.Tests.Common;
/*
namespace OpenSim.Capabilities.Handlers.GetTexture.Tests
{
[TestFixture]
@ -60,5 +59,4 @@ namespace OpenSim.Capabilities.Handlers.GetTexture.Tests
Assert.That(resp.StatusCode, Is.EqualTo((int)System.Net.HttpStatusCode.NotFound));
}
}
}
*/
}

View File

@ -2,7 +2,7 @@
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("OpenSim.Capabilities.Handlers")]
@ -14,8 +14,8 @@ using System.Runtime.InteropServices;
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
@ -25,9 +25,9 @@ using System.Runtime.InteropServices;
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Minor Version
// Build Number
// Revision
//
[assembly: AssemblyVersion(OpenSim.VersionInfo.AssemblyVersionNumber)]
[assembly: AssemblyVersion("0.8.1.*")]

View File

@ -0,0 +1,181 @@
/*
* Copyright (c) Contributors, http://opensimulator.org/
* See CONTRIBUTORS.TXT for a full list of copyright holders.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the OpenSimulator Project nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
using System;
using System.Collections;
using System.Collections.Specialized;
using System.Drawing;
using System.Drawing.Imaging;
using System.Reflection;
using System.IO;
using System.Web;
using log4net;
using Nini.Config;
using OpenMetaverse;
using OpenMetaverse.StructuredData;
using OpenMetaverse.Imaging;
using OpenSim.Framework;
using OpenSim.Framework.Capabilities;
using OpenSim.Framework.Servers;
using OpenSim.Framework.Servers.HttpServer;
using OpenSim.Region.Framework.Interfaces;
using OpenSim.Services.Interfaces;
using Caps = OpenSim.Framework.Capabilities.Caps;
namespace OpenSim.Capabilities.Handlers
{
public class UploadBakedTextureHandler
{
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private Caps m_HostCapsObj;
private IAssetService m_assetService;
private bool m_persistBakedTextures;
public UploadBakedTextureHandler(Caps caps, IAssetService assetService, bool persistBakedTextures)
{
m_HostCapsObj = caps;
m_assetService = assetService;
m_persistBakedTextures = persistBakedTextures;
}
/// <summary>
/// Handle a request from the client for a Uri to upload a baked texture.
/// </summary>
/// <param name="request"></param>
/// <param name="path"></param>
/// <param name="param"></param>
/// <param name="httpRequest"></param>
/// <param name="httpResponse"></param>
/// <returns>The upload response if the request is successful, null otherwise.</returns>
public string UploadBakedTexture(
string request, string path, string param, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
{
try
{
string capsBase = "/CAPS/" + m_HostCapsObj.CapsObjectPath;
string uploaderPath = Util.RandomClass.Next(5000, 8000).ToString("0000");
BakedTextureUploader uploader =
new BakedTextureUploader(capsBase + uploaderPath, m_HostCapsObj.HttpListener);
uploader.OnUpLoad += BakedTextureUploaded;
m_HostCapsObj.HttpListener.AddStreamHandler(
new BinaryStreamHandler(
"POST", capsBase + uploaderPath, uploader.uploaderCaps, "UploadBakedTexture", null));
string protocol = "http://";
if (m_HostCapsObj.SSLCaps)
protocol = "https://";
string uploaderURL = protocol + m_HostCapsObj.HostName + ":" +
m_HostCapsObj.Port.ToString() + capsBase + uploaderPath;
LLSDAssetUploadResponse uploadResponse = new LLSDAssetUploadResponse();
uploadResponse.uploader = uploaderURL;
uploadResponse.state = "upload";
return LLSDHelpers.SerialiseLLSDReply(uploadResponse);
}
catch (Exception e)
{
m_log.ErrorFormat("[UPLOAD BAKED TEXTURE HANDLER]: {0}{1}", e.Message, e.StackTrace);
}
return null;
}
/// <summary>
/// Called when a baked texture has been successfully uploaded by a client.
/// </summary>
/// <param name="assetID"></param>
/// <param name="data"></param>
private void BakedTextureUploaded(UUID assetID, byte[] data)
{
// m_log.DebugFormat("[UPLOAD BAKED TEXTURE HANDLER]: Received baked texture {0}", assetID.ToString());
AssetBase asset;
asset = new AssetBase(assetID, "Baked Texture", (sbyte)AssetType.Texture, m_HostCapsObj.AgentID.ToString());
asset.Data = data;
asset.Temporary = true;
asset.Local = !m_persistBakedTextures; // Local assets aren't persisted, non-local are
m_assetService.Store(asset);
}
}
class BakedTextureUploader
{
// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
public event Action<UUID, byte[]> OnUpLoad;
private string uploaderPath = String.Empty;
private UUID newAssetID;
private IHttpServer httpListener;
public BakedTextureUploader(string path, IHttpServer httpServer)
{
newAssetID = UUID.Random();
uploaderPath = path;
httpListener = httpServer;
// m_log.InfoFormat("[CAPS] baked texture upload starting for {0}",newAssetID);
}
/// <summary>
/// Handle raw uploaded baked texture data.
/// </summary>
/// <param name="data"></param>
/// <param name="path"></param>
/// <param name="param"></param>
/// <returns></returns>
public string uploaderCaps(byte[] data, string path, string param)
{
Action<UUID, byte[]> handlerUpLoad = OnUpLoad;
// Don't do this asynchronously, otherwise it's possible for the client to send set appearance information
// on another thread which might send out avatar updates before the asset has been put into the asset
// service.
if (handlerUpLoad != null)
handlerUpLoad(newAssetID, data);
string res = String.Empty;
LLSDAssetUploadComplete uploadComplete = new LLSDAssetUploadComplete();
uploadComplete.new_asset = newAssetID.ToString();
uploadComplete.new_inventory_item = UUID.Zero;
uploadComplete.state = "complete";
res = LLSDHelpers.SerialiseLLSDReply(uploadComplete);
httpListener.RemoveStreamHandler("POST", uploaderPath);
// m_log.DebugFormat("[BAKED TEXTURE UPLOADER]: baked texture upload completed for {0}", newAssetID);
return res;
}
}
}

View File

@ -25,40 +25,52 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
using System;
using Nini.Config;
using OpenSim.Server.Base;
using OpenSim.Services.Interfaces;
using OpenSim.Framework.ServiceAuth;
using OpenSim.Framework.Servers.HttpServer;
using OpenSim.Server.Handlers.Base;
using OpenMetaverse;
namespace OpenSim.Server.Handlers.AgentPreferences
namespace OpenSim.Capabilities.Handlers
{
public class AgentPreferencesServiceConnector : ServiceConnector
public class UploadBakedTextureServerConnector : ServiceConnector
{
private IAgentPreferencesService m_AgentPreferencesService;
private string m_ConfigName = "AgentPreferencesService";
private IAssetService m_AssetService;
private string m_ConfigName = "CapsService";
public AgentPreferencesServiceConnector(IConfigSource config, IHttpServer server, string configName) :
public UploadBakedTextureServerConnector(IConfigSource config, IHttpServer server, string configName) :
base(config, server, configName)
{
if (configName != String.Empty)
m_ConfigName = configName;
IConfig serverConfig = config.Configs[m_ConfigName];
if (serverConfig == null)
throw new Exception(String.Format("No section {0} in config file", m_ConfigName));
throw new Exception(String.Format("No section '{0}' in config file", m_ConfigName));
string service = serverConfig.GetString("LocalServiceModule", String.Empty);
string assetService = serverConfig.GetString("AssetService", String.Empty);
if (String.IsNullOrWhiteSpace(service))
throw new Exception("No LocalServiceModule in config file");
if (assetService == String.Empty)
throw new Exception("No AssetService in config file");
Object[] args = new Object[] { config };
m_AgentPreferencesService = ServerUtils.LoadPlugin<IAgentPreferencesService>(service, args);
m_AssetService =
ServerUtils.LoadPlugin<IAssetService>(assetService, args);
IServiceAuth auth = ServiceAuth.Create(config, m_ConfigName); ;
if (m_AssetService == null)
throw new Exception(String.Format("Failed to load AssetService from {0}; config is {1}", assetService, m_ConfigName));
server.AddStreamHandler(new AgentPreferencesServerPostHandler(m_AgentPreferencesService, auth));
}
// NEED TO FIX THIS
OpenSim.Framework.Capabilities.Caps caps = new OpenSim.Framework.Capabilities.Caps(server, "", server.Port, "", UUID.Zero, "");
server.AddStreamHandler(new RestStreamHandler(
"POST",
"/CAPS/UploadBakedTexture/",
new UploadBakedTextureHandler(caps, m_AssetService, true).UploadBakedTexture,
"UploadBakedTexture",
"Upload Baked Texture Capability"));
}
}
}
}

View File

@ -0,0 +1,446 @@
/*
* Copyright (c) Contributors, http://opensimulator.org/
* See CONTRIBUTORS.TXT for a full list of copyright holders.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the OpenSimulator Project nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
using System;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using log4net;
using Nini.Config;
using OpenMetaverse;
using OpenMetaverse.StructuredData;
using OpenSim.Framework;
using OpenSim.Framework.Capabilities;
using OpenSim.Region.Framework.Interfaces;
using OpenSim.Framework.Servers.HttpServer;
using OpenSim.Services.Interfaces;
using Caps = OpenSim.Framework.Capabilities.Caps;
namespace OpenSim.Capabilities.Handlers
{
public class WebFetchInvDescHandler
{
private static readonly ILog m_log =
LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private IInventoryService m_InventoryService;
private ILibraryService m_LibraryService;
// private object m_fetchLock = new Object();
public WebFetchInvDescHandler(IInventoryService invService, ILibraryService libService)
{
m_InventoryService = invService;
m_LibraryService = libService;
}
public string FetchInventoryDescendentsRequest(string request, string path, string param, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
{
// lock (m_fetchLock)
// {
// m_log.DebugFormat("[WEB FETCH INV DESC HANDLER]: Received request {0}", request);
// nasty temporary hack here, the linden client falsely
// identifies the uuid 00000000-0000-0000-0000-000000000000
// as a string which breaks us
//
// correctly mark it as a uuid
//
request = request.Replace("<string>00000000-0000-0000-0000-000000000000</string>", "<uuid>00000000-0000-0000-0000-000000000000</uuid>");
// another hack <integer>1</integer> results in a
// System.ArgumentException: Object type System.Int32 cannot
// be converted to target type: System.Boolean
//
request = request.Replace("<key>fetch_folders</key><integer>0</integer>", "<key>fetch_folders</key><boolean>0</boolean>");
request = request.Replace("<key>fetch_folders</key><integer>1</integer>", "<key>fetch_folders</key><boolean>1</boolean>");
Hashtable hash = new Hashtable();
try
{
hash = (Hashtable)LLSD.LLSDDeserialize(Utils.StringToBytes(request));
}
catch (LLSD.LLSDParseException e)
{
m_log.ErrorFormat("[WEB FETCH INV DESC HANDLER]: Fetch error: {0}{1}" + e.Message, e.StackTrace);
m_log.Error("Request: " + request);
}
ArrayList foldersrequested = (ArrayList)hash["folders"];
string response = "";
for (int i = 0; i < foldersrequested.Count; i++)
{
string inventoryitemstr = "";
Hashtable inventoryhash = (Hashtable)foldersrequested[i];
LLSDFetchInventoryDescendents llsdRequest = new LLSDFetchInventoryDescendents();
try
{
LLSDHelpers.DeserialiseOSDMap(inventoryhash, llsdRequest);
}
catch (Exception e)
{
m_log.Debug("[WEB FETCH INV DESC HANDLER]: caught exception doing OSD deserialize" + e);
}
LLSDInventoryDescendents reply = FetchInventoryReply(llsdRequest);
inventoryitemstr = LLSDHelpers.SerialiseLLSDReply(reply);
inventoryitemstr = inventoryitemstr.Replace("<llsd><map><key>folders</key><array>", "");
inventoryitemstr = inventoryitemstr.Replace("</array></map></llsd>", "");
response += inventoryitemstr;
}
if (response.Length == 0)
{
// Ter-guess: If requests fail a lot, the client seems to stop requesting descendants.
// Therefore, I'm concluding that the client only has so many threads available to do requests
// and when a thread stalls.. is stays stalled.
// Therefore we need to return something valid
response = "<llsd><map><key>folders</key><array /></map></llsd>";
}
else
{
response = "<llsd><map><key>folders</key><array>" + response + "</array></map></llsd>";
}
// m_log.DebugFormat("[WEB FETCH INV DESC HANDLER]: Replying to CAPS fetch inventory request");
//m_log.Debug("[WEB FETCH INV DESC HANDLER] "+response);
return response;
// }
}
/// <summary>
/// Construct an LLSD reply packet to a CAPS inventory request
/// </summary>
/// <param name="invFetch"></param>
/// <returns></returns>
private LLSDInventoryDescendents FetchInventoryReply(LLSDFetchInventoryDescendents invFetch)
{
LLSDInventoryDescendents reply = new LLSDInventoryDescendents();
LLSDInventoryFolderContents contents = new LLSDInventoryFolderContents();
contents.agent_id = invFetch.owner_id;
contents.owner_id = invFetch.owner_id;
contents.folder_id = invFetch.folder_id;
reply.folders.Array.Add(contents);
InventoryCollection inv = new InventoryCollection();
inv.Folders = new List<InventoryFolderBase>();
inv.Items = new List<InventoryItemBase>();
int version = 0;
int descendents = 0;
inv
= Fetch(
invFetch.owner_id, invFetch.folder_id, invFetch.owner_id,
invFetch.fetch_folders, invFetch.fetch_items, invFetch.sort_order, out version, out descendents);
if (inv != null && inv.Folders != null)
{
foreach (InventoryFolderBase invFolder in inv.Folders)
{
contents.categories.Array.Add(ConvertInventoryFolder(invFolder));
}
descendents += inv.Folders.Count;
}
if (inv != null && inv.Items != null)
{
foreach (InventoryItemBase invItem in inv.Items)
{
contents.items.Array.Add(ConvertInventoryItem(invItem));
}
}
contents.descendents = descendents;
contents.version = version;
// m_log.DebugFormat(
// "[WEB FETCH INV DESC HANDLER]: Replying to request for folder {0} (fetch items {1}, fetch folders {2}) with {3} items and {4} folders for agent {5}",
// invFetch.folder_id,
// invFetch.fetch_items,
// invFetch.fetch_folders,
// contents.items.Array.Count,
// contents.categories.Array.Count,
// invFetch.owner_id);
return reply;
}
/// <summary>
/// Handle the caps inventory descendents fetch.
/// </summary>
/// <param name="agentID"></param>
/// <param name="folderID"></param>
/// <param name="ownerID"></param>
/// <param name="fetchFolders"></param>
/// <param name="fetchItems"></param>
/// <param name="sortOrder"></param>
/// <param name="version"></param>
/// <returns>An empty InventoryCollection if the inventory look up failed</returns>
private InventoryCollection Fetch(
UUID agentID, UUID folderID, UUID ownerID,
bool fetchFolders, bool fetchItems, int sortOrder, out int version, out int descendents)
{
// m_log.DebugFormat(
// "[WEB FETCH INV DESC HANDLER]: Fetching folders ({0}), items ({1}) from {2} for agent {3}",
// fetchFolders, fetchItems, folderID, agentID);
// FIXME MAYBE: We're not handling sortOrder!
version = 0;
descendents = 0;
InventoryFolderImpl fold;
if (m_LibraryService != null && m_LibraryService.LibraryRootFolder != null && agentID == m_LibraryService.LibraryRootFolder.Owner)
{
if ((fold = m_LibraryService.LibraryRootFolder.FindFolder(folderID)) != null)
{
InventoryCollection ret = new InventoryCollection();
ret.Folders = new List<InventoryFolderBase>();
ret.Items = fold.RequestListOfItems();
descendents = ret.Folders.Count + ret.Items.Count;
return ret;
}
}
InventoryCollection contents = new InventoryCollection();
if (folderID != UUID.Zero)
{
InventoryCollection fetchedContents = m_InventoryService.GetFolderContent(agentID, folderID);
if (fetchedContents == null)
{
m_log.WarnFormat("[WEB FETCH INV DESC HANDLER]: Could not get contents of folder {0} for user {1}", folderID, agentID);
return contents;
}
contents = fetchedContents;
InventoryFolderBase containingFolder = new InventoryFolderBase();
containingFolder.ID = folderID;
containingFolder.Owner = agentID;
containingFolder = m_InventoryService.GetFolder(containingFolder);
if (containingFolder != null)
{
// m_log.DebugFormat(
// "[WEB FETCH INV DESC HANDLER]: Retrieved folder {0} {1} for agent id {2}",
// containingFolder.Name, containingFolder.ID, agentID);
version = containingFolder.Version;
if (fetchItems)
{
List<InventoryItemBase> itemsToReturn = contents.Items;
List<InventoryItemBase> originalItems = new List<InventoryItemBase>(itemsToReturn);
// descendents must only include the links, not the linked items we add
descendents = originalItems.Count;
// Add target items for links in this folder before the links themselves.
foreach (InventoryItemBase item in originalItems)
{
if (item.AssetType == (int)AssetType.Link)
{
InventoryItemBase linkedItem = m_InventoryService.GetItem(new InventoryItemBase(item.AssetID));
// Take care of genuinely broken links where the target doesn't exist
// HACK: Also, don't follow up links that just point to other links. In theory this is legitimate,
// but no viewer has been observed to set these up and this is the lazy way of avoiding cycles
// rather than having to keep track of every folder requested in the recursion.
if (linkedItem != null && linkedItem.AssetType != (int)AssetType.Link)
itemsToReturn.Insert(0, linkedItem);
}
}
// Now scan for folder links and insert the items they target and those links at the head of the return data
foreach (InventoryItemBase item in originalItems)
{
if (item.AssetType == (int)AssetType.LinkFolder)
{
InventoryCollection linkedFolderContents = m_InventoryService.GetFolderContent(ownerID, item.AssetID);
List<InventoryItemBase> links = linkedFolderContents.Items;
itemsToReturn.InsertRange(0, links);
foreach (InventoryItemBase link in linkedFolderContents.Items)
{
// Take care of genuinely broken links where the target doesn't exist
// HACK: Also, don't follow up links that just point to other links. In theory this is legitimate,
// but no viewer has been observed to set these up and this is the lazy way of avoiding cycles
// rather than having to keep track of every folder requested in the recursion.
if (link != null)
{
// m_log.DebugFormat(
// "[WEB FETCH INV DESC HANDLER]: Adding item {0} {1} from folder {2} linked from {3}",
// link.Name, (AssetType)link.AssetType, item.AssetID, containingFolder.Name);
InventoryItemBase linkedItem
= m_InventoryService.GetItem(new InventoryItemBase(link.AssetID));
if (linkedItem != null)
itemsToReturn.Insert(0, linkedItem);
}
}
}
}
}
// foreach (InventoryItemBase item in contents.Items)
// {
// m_log.DebugFormat(
// "[WEB FETCH INV DESC HANDLER]: Returning item {0}, type {1}, parent {2} in {3} {4}",
// item.Name, (AssetType)item.AssetType, item.Folder, containingFolder.Name, containingFolder.ID);
// }
// =====
//
// foreach (InventoryItemBase linkedItem in linkedItemsToAdd)
// {
// m_log.DebugFormat(
// "[WEB FETCH INV DESC HANDLER]: Inserted linked item {0} for link in folder {1} for agent {2}",
// linkedItem.Name, folderID, agentID);
//
// contents.Items.Add(linkedItem);
// }
//
// // If the folder requested contains links, then we need to send those folders first, otherwise the links
// // will be broken in the viewer.
// HashSet<UUID> linkedItemFolderIdsToSend = new HashSet<UUID>();
// foreach (InventoryItemBase item in contents.Items)
// {
// if (item.AssetType == (int)AssetType.Link)
// {
// InventoryItemBase linkedItem = m_InventoryService.GetItem(new InventoryItemBase(item.AssetID));
//
// // Take care of genuinely broken links where the target doesn't exist
// // HACK: Also, don't follow up links that just point to other links. In theory this is legitimate,
// // but no viewer has been observed to set these up and this is the lazy way of avoiding cycles
// // rather than having to keep track of every folder requested in the recursion.
// if (linkedItem != null && linkedItem.AssetType != (int)AssetType.Link)
// {
// // We don't need to send the folder if source and destination of the link are in the same
// // folder.
// if (linkedItem.Folder != containingFolder.ID)
// linkedItemFolderIdsToSend.Add(linkedItem.Folder);
// }
// }
// }
//
// foreach (UUID linkedItemFolderId in linkedItemFolderIdsToSend)
// {
// m_log.DebugFormat(
// "[WEB FETCH INV DESC HANDLER]: Recursively fetching folder {0} linked by item in folder {1} for agent {2}",
// linkedItemFolderId, folderID, agentID);
//
// int dummyVersion;
// InventoryCollection linkedCollection
// = Fetch(
// agentID, linkedItemFolderId, ownerID, fetchFolders, fetchItems, sortOrder, out dummyVersion);
//
// InventoryFolderBase linkedFolder = new InventoryFolderBase(linkedItemFolderId);
// linkedFolder.Owner = agentID;
// linkedFolder = m_InventoryService.GetFolder(linkedFolder);
//
//// contents.Folders.AddRange(linkedCollection.Folders);
//
// contents.Folders.Add(linkedFolder);
// contents.Items.AddRange(linkedCollection.Items);
// }
// }
}
}
else
{
// Lost items don't really need a version
version = 1;
}
return contents;
}
/// <summary>
/// Convert an internal inventory folder object into an LLSD object.
/// </summary>
/// <param name="invFolder"></param>
/// <returns></returns>
private LLSDInventoryFolder ConvertInventoryFolder(InventoryFolderBase invFolder)
{
LLSDInventoryFolder llsdFolder = new LLSDInventoryFolder();
llsdFolder.folder_id = invFolder.ID;
llsdFolder.parent_id = invFolder.ParentID;
llsdFolder.name = invFolder.Name;
llsdFolder.type = invFolder.Type;
llsdFolder.preferred_type = -1;
return llsdFolder;
}
/// <summary>
/// Convert an internal inventory item object into an LLSD object.
/// </summary>
/// <param name="invItem"></param>
/// <returns></returns>
private LLSDInventoryItem ConvertInventoryItem(InventoryItemBase invItem)
{
LLSDInventoryItem llsdItem = new LLSDInventoryItem();
llsdItem.asset_id = invItem.AssetID;
llsdItem.created_at = invItem.CreationDate;
llsdItem.desc = invItem.Description;
llsdItem.flags = (int)invItem.Flags;
llsdItem.item_id = invItem.ID;
llsdItem.name = invItem.Name;
llsdItem.parent_id = invItem.Folder;
llsdItem.type = invItem.AssetType;
llsdItem.inv_type = invItem.InvType;
llsdItem.permissions = new LLSDPermissions();
llsdItem.permissions.creator_id = invItem.CreatorIdAsUuid;
llsdItem.permissions.base_mask = (int)invItem.CurrentPermissions;
llsdItem.permissions.everyone_mask = (int)invItem.EveryOnePermissions;
llsdItem.permissions.group_id = invItem.GroupID;
llsdItem.permissions.group_mask = (int)invItem.GroupPermissions;
llsdItem.permissions.is_owner_group = invItem.GroupOwned;
llsdItem.permissions.next_owner_mask = (int)invItem.NextPermissions;
llsdItem.permissions.owner_id = invItem.Owner;
llsdItem.permissions.owner_mask = (int)invItem.CurrentPermissions;
llsdItem.sale_info = new LLSDSaleInfo();
llsdItem.sale_info.sale_price = invItem.SalePrice;
llsdItem.sale_info.sale_type = invItem.SaleType;
return llsdItem;
}
}
}

View File

@ -29,22 +29,19 @@ using System;
using Nini.Config;
using OpenSim.Server.Base;
using OpenSim.Services.Interfaces;
using OpenSim.Framework;
using OpenSim.Framework.Servers.HttpServer;
using OpenSim.Server.Handlers.Base;
using OpenMetaverse;
using OpenMetaverse.StructuredData;
namespace OpenSim.Capabilities.Handlers
{
public class FetchInvDescServerConnector : ServiceConnector
public class WebFetchInvDescServerConnector : ServiceConnector
{
private IInventoryService m_InventoryService;
private ILibraryService m_LibraryService;
private string m_ConfigName = "CapsService";
public FetchInvDescServerConnector(IConfigSource config, IHttpServer server, string configName) :
public WebFetchInvDescServerConnector(IConfigSource config, IHttpServer server, string configName) :
base(config, server, configName)
{
if (configName != String.Empty)
@ -70,16 +67,16 @@ namespace OpenSim.Capabilities.Handlers
m_LibraryService =
ServerUtils.LoadPlugin<ILibraryService>(libService, args);
ExpiringKey<UUID> m_badRequests = new ExpiringKey<UUID>(30000);
FetchInvDescHandler webFetchHandler = new FetchInvDescHandler(m_InventoryService, m_LibraryService, null);
ISimpleStreamHandler reqHandler
= new SimpleStreamHandler("/CAPS/WebFetchInvDesc/", delegate(IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
{
webFetchHandler.FetchInventoryDescendentsRequest(httpRequest, httpResponse, m_badRequests);
});
server.AddSimpleStreamHandler(reqHandler);
WebFetchInvDescHandler webFetchHandler = new WebFetchInvDescHandler(m_InventoryService, m_LibraryService);
IRequestHandler reqHandler
= new RestStreamHandler(
"POST",
"/CAPS/WebFetchInvDesc/" /*+ UUID.Random()*/,
webFetchHandler.FetchInventoryDescendentsRequest,
"WebFetchInvDesc",
null);
server.AddStreamHandler(reqHandler);
}
}
}

View File

@ -107,17 +107,17 @@ namespace OpenSim.Framework.Capabilities
/// <returns></returns>
public static byte[] LLSDSerialize(object obj)
{
using(StringWriter sw = new StringWriter())
using(XmlTextWriter writer = new XmlTextWriter(sw))
{
writer.Formatting = Formatting.None;
StringWriter sw = new StringWriter();
XmlTextWriter writer = new XmlTextWriter(sw);
writer.Formatting = Formatting.None;
writer.WriteStartElement(String.Empty, "llsd", String.Empty);
LLSDWriteOne(writer, obj);
writer.WriteEndElement();
writer.Flush();
return Util.UTF8.GetBytes(sw.ToString());
}
writer.WriteStartElement(String.Empty, "llsd", String.Empty);
LLSDWriteOne(writer, obj);
writer.WriteEndElement();
writer.Close();
return Util.UTF8.GetBytes(sw.ToString());
}
/// <summary>
@ -566,7 +566,7 @@ namespace OpenSim.Framework.Capabilities
endPos = FindEnd(llsd, 1);
if (Double.TryParse(llsd.Substring(1, endPos - 1), NumberStyles.Float,
Culture.NumberFormatInfo, out value))
Utils.EnUsCulture.NumberFormat, out value))
return value;
else
throw new LLSDParseException("Failed to parse double value type");

View File

@ -30,20 +30,13 @@ using OpenMetaverse;
namespace OpenSim.Framework.Capabilities
{
[LLSDType("MAP")]
public class LLSDAssetUploadComplete
{
public string new_asset = String.Empty;
public UUID new_inventory_item = UUID.Zero;
// public UUID new_texture_folder_id = UUID.Zero;
public string state = String.Empty;
public LLSDAssetUploadError error = null;
//public bool success = false;
public int new_next_owner_mask = 0;
public int new_group_mask = 0;
public int new_everyone_mask = 0;
public int inventory_item_flags = 0;
public LLSDAssetUploadComplete()
{

View File

@ -30,28 +30,15 @@ using OpenMetaverse;
namespace OpenSim.Framework.Capabilities
{
[OSDMap]
public class LLSDAssetResource
{
public OSDArray instance_list = new OSDArray();
public OSDArray texture_list = new OSDArray();
public OSDArray mesh_list = new OSDArray();
public string metric = String.Empty;
}
[OSDMap]
public class LLSDAssetUploadRequest
{
public string asset_type = String.Empty;
public string description = String.Empty;
public UUID folder_id = UUID.Zero;
public UUID texture_folder_id = UUID.Zero;
public int next_owner_mask = 0;
public int group_mask = 0;
public int everyone_mask = 0;
public string inventory_type = String.Empty;
public string name = String.Empty;
public LLSDAssetResource asset_resources = new LLSDAssetResource();
public LLSDAssetUploadRequest()
{
}

View File

@ -26,51 +26,20 @@
*/
using System;
using OpenMetaverse;
namespace OpenSim.Framework.Capabilities
{
[OSDMap]
public class LLSDAssetUploadError
{
public string message = String.Empty;
public UUID identifier = UUID.Zero;
}
[OSDMap]
public class LLSDAssetUploadResponsePricebrkDown
{
public int mesh_streaming;
public int mesh_physics;
public int mesh_instance;
public int texture;
public int model;
}
[OSDMap]
public class LLSDAssetUploadResponseData
{
public double resource_cost;
public double model_streaming_cost;
public double simulation_cost;
public double physics_cost;
public LLSDAssetUploadResponsePricebrkDown upload_price_breakdown = new LLSDAssetUploadResponsePricebrkDown();
}
[OSDMap]
public class LLSDAssetUploadResponse
{
public string uploader = String.Empty;
public string state = String.Empty;
public int upload_price = 0;
public LLSDAssetUploadResponseData data = null;
public LLSDAssetUploadError error = null;
public LLSDAssetUploadResponse()
{
}
}
[OSDMap]
public class LLSDNewFileAngentInventoryVariablePriceReplyResponse
{
@ -78,7 +47,7 @@ namespace OpenSim.Framework.Capabilities
public string state;
public int upload_price;
public string rsvp;
public LLSDNewFileAngentInventoryVariablePriceReplyResponse()
{
state = "confirm_upload";

View File

@ -42,7 +42,7 @@ namespace OpenSim.Framework.Capabilities
{
public string username;
public string display_name;
//'display_name_next_update':d"1970-01-01T00:00:00Z"
//'display_name_next_update':d"1970-01-01T00:00:00Z"
public string legacy_first_name;
public string legacy_last_name;
public UUID id;

View File

@ -0,0 +1,68 @@
/*
* Copyright (c) Contributors, http://opensimulator.org/
* See CONTRIBUTORS.TXT for a full list of copyright holders.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the OpenSimulator Project nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
using System;
using System.Collections.Generic;
using OpenMetaverse;
namespace OpenSim.Framework.Capabilities
{
[OSDMap]
public class LLSDEnvironmentRequest
{
public UUID messageID;
public UUID regionID;
}
[OSDMap]
public class LLSDEnvironmentSetResponse
{
public UUID regionID;
public UUID messageID;
public Boolean success;
public String fail_reason;
}
public class EnvironmentSettings
{
/// <summary>
/// generates a empty llsd settings response for viewer
/// </summary>
/// <param name="messageID">the message UUID</param>
/// <param name="regionID">the region UUID</param>
public static string EmptySettings(UUID messageID, UUID regionID)
{
OSDArray arr = new OSDArray();
LLSDEnvironmentRequest msg = new LLSDEnvironmentRequest();
msg.messageID = messageID;
msg.regionID = regionID;
arr.Array.Add(msg);
return LLSDHelpers.SerialiseLLSDReply(arr);
}
}
}

View File

@ -30,7 +30,6 @@ using System.Collections;
using System.IO;
using System.Reflection;
using System.Xml;
using OpenMetaverse;
namespace OpenSim.Framework.Capabilities
{
@ -41,32 +40,17 @@ namespace OpenSim.Framework.Capabilities
public static string SerialiseLLSDReply(object obj)
{
using(StringWriter sw = new StringWriter())
using(XmlTextWriter writer = new XmlTextWriter(sw))
{
writer.Formatting = Formatting.None;
writer.WriteStartElement(String.Empty, "llsd", String.Empty);
SerializeOSDType(writer, obj);
writer.WriteEndElement();
writer.Flush();
StringWriter sw = new StringWriter();
XmlTextWriter writer = new XmlTextWriter(sw);
writer.Formatting = Formatting.None;
writer.WriteStartElement(String.Empty, "llsd", String.Empty);
SerializeOSDType(writer, obj);
writer.WriteEndElement();
writer.Close();
//m_log.DebugFormat("[LLSD Helpers]: Generated serialized LLSD reply {0}", sw.ToString());
return sw.ToString();
}
}
public static string SerialiseLLSDReplyNoHeader(object obj)
{
using(StringWriter sw = new StringWriter())
using(XmlTextWriter writer = new XmlTextWriter(sw))
{
writer.Formatting = Formatting.None;
SerializeOSDType(writer, obj);
writer.Flush();
//m_log.DebugFormat("[LLSD Helpers]: Generated serialized LLSD reply {0}", sw.ToString());
return sw.ToString();
}
return sw.ToString();
}
private static void SerializeOSDType(XmlTextWriter writer, object obj)
@ -173,22 +157,6 @@ namespace OpenSim.Framework.Capabilities
// the LLSD map/array types in the array need to be deserialised
// but first we need to know the right class to deserialise them into.
}
else if(enumerator.Value is Boolean && field.FieldType == typeof(int) )
{
int i = (bool)enumerator.Value ? 1 : 0;
field.SetValue(obj, i);
}
else if(field.FieldType == typeof(bool) && enumerator.Value is int)
{
bool b = (int)enumerator.Value != 0;
field.SetValue(obj, b);
}
else if(field.FieldType == typeof(UUID) && enumerator.Value is string)
{
UUID u;
UUID.TryParse((string)enumerator.Value, out u);
field.SetValue(obj, u);
}
else
{
field.SetValue(obj, enumerator.Value);

View File

@ -37,6 +37,5 @@ namespace OpenSim.Framework.Capabilities
public string name;
public int type;
public int preferred_type;
public int version;
}
}

View File

@ -87,12 +87,12 @@ namespace OpenSim.Framework.Capabilities
[OSDMap]
public class LLSDInventoryFolderContents
{
public UUID agent_id;
public UUID agent_id;
public int descendents;
public UUID folder_id;
public UUID folder_id;
public OSDArray categories = new OSDArray();
public OSDArray items = new OSDArray();
public UUID owner_id;
public UUID owner_id;
public int version;
}

View File

@ -25,11 +25,17 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
using OpenSim.Region.Framework.Scenes;
using OpenMetaverse;
public interface IUserAccountCacheModule
namespace OpenSim.Framework.Capabilities
{
void Remove(string name);
void Remove(UUID id);
[OSDMap]
public class LLSDItemUpdate
{
public UUID item_id;
public LLSDItemUpdate()
{
}
}
}

View File

@ -0,0 +1,51 @@
/*
* Copyright (c) Contributors, http://opensimulator.org/
* See CONTRIBUTORS.TXT for a full list of copyright holders.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the OpenSimulator Project nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
using System.Collections;
namespace OpenSim.Framework.Capabilities
{
[OSDMap]
public class LLSDParcelVoiceInfoResponse
{
public int parcel_local_id;
public string region_name;
public Hashtable voice_credentials;
public LLSDParcelVoiceInfoResponse()
{
}
public LLSDParcelVoiceInfoResponse(string region, int localID, Hashtable creds)
{
region_name = region;
parcel_local_id = localID;
voice_credentials = creds;
}
}
}

View File

@ -0,0 +1,42 @@
/*
* Copyright (c) Contributors, http://opensimulator.org/
* See CONTRIBUTORS.TXT for a full list of copyright holders.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the OpenSimulator Project nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
using OpenMetaverse;
namespace OpenSim.Framework.Capabilities
{
[LLSDType("MAP")]
public class LLSDRemoteParcelResponse
{
public UUID parcel_id;
public LLSDRemoteParcelResponse()
{
}
}
}

View File

@ -61,9 +61,6 @@ namespace OpenSim.Framework.Capabilities
// OpenMetaverse.StructuredData.LLSDParser.DeserializeXml(new XmlTextReader(request));
Hashtable hash = (Hashtable) LLSD.LLSDDeserialize(request);
if(hash == null)
return new byte[0];
TRequest llsdRequest = new TRequest();
LLSDHelpers.DeserialiseOSDMap(hash, llsdRequest);

View File

@ -0,0 +1,50 @@
/*
* Copyright (c) Contributors, http://opensimulator.org/
* See CONTRIBUTORS.TXT for a full list of copyright holders.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the OpenSimulator Project nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
using OpenMetaverse;
namespace OpenSim.Framework.Capabilities
{
[OSDMap]
public class LLSDTaskScriptUpdate
{
/// <summary>
/// The item containing the script to update
/// </summary>
public UUID item_id;
/// <summary>
/// The task containing the script
/// </summary>
public UUID task_id;
/// <summary>
/// Signals whether the script is currently active
/// </summary>
public int is_script_running;
}
}

View File

@ -0,0 +1,57 @@
/*
* Copyright (c) Contributors, http://opensimulator.org/
* See CONTRIBUTORS.TXT for a full list of copyright holders.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the OpenSimulator Project nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
namespace OpenSim.Framework.Capabilities
{
[OSDMap]
public class LLSDVoiceAccountResponse
{
public string username;
public string password;
public string voice_sip_uri_hostname;
public string voice_account_server_name;
public LLSDVoiceAccountResponse()
{
}
public LLSDVoiceAccountResponse(string user, string pass)
{
username = user;
password = pass;
}
public LLSDVoiceAccountResponse(string user, string pass, string sipUriHost, string accountServer)
{
username = user;
password = pass;
voice_sip_uri_hostname = sipUriHost;
voice_account_server_name = accountServer;
}
}
}

View File

@ -2,7 +2,7 @@
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("OpenSim.Capabilities")]
@ -14,8 +14,8 @@ using System.Runtime.InteropServices;
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
@ -25,7 +25,7 @@ using System.Runtime.InteropServices;
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Minor Version
// Build Number
// Revision
//

View File

@ -80,7 +80,7 @@ namespace OpenSim.ConsoleClient
while (m_Server.Running)
{
System.Threading.Thread.Sleep(500);
MainConsole.Instance.Prompt();
// MainConsole.Instance.Prompt();
}
if (pidFile != String.Empty)
@ -178,7 +178,7 @@ namespace OpenSim.ConsoleClient
Requester.MakeRequest(requestUrl, requestData, ReadResponses);
return;
}
List<string> lines = new List<string>();
foreach (XmlNode part in rootNodeL[0].ChildNodes)
@ -202,7 +202,7 @@ namespace OpenSim.ConsoleClient
string[] parts = l.Split(new char[] {':'}, 3);
if (parts.Length != 3)
continue;
if (parts[2].StartsWith("+++") || parts[2].StartsWith("-++"))
prompt = parts[2];
else

View File

@ -2,7 +2,7 @@
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("OpenSim.ConsoleClient")]
@ -14,8 +14,8 @@ using System.Runtime.InteropServices;
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
@ -25,7 +25,7 @@ using System.Runtime.InteropServices;
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Minor Version
// Build Number
// Revision
//

View File

@ -37,7 +37,7 @@ namespace OpenSim.Data
public abstract class AssetDataBase : IAssetDataPlugin
{
public abstract AssetBase GetAsset(UUID uuid);
public abstract bool StoreAsset(AssetBase asset);
public abstract void StoreAsset(AssetBase asset);
public abstract bool[] AssetsExist(UUID[] uuids);
public abstract List<AssetMetadata> FetchAssetMetadataSet(int start, int count);

View File

@ -38,7 +38,7 @@ namespace OpenSim.Data
/// <summary>This function converts a value returned from the database in one of the
/// supported formats into a UUID. This function is not actually DBMS-specific right
/// now
///
///
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
@ -47,25 +47,24 @@ namespace OpenSim.Data
if ((id == null) || (id == DBNull.Value))
return UUID.Zero;
Type idtype = id.GetType();
if (idtype == typeof(Guid))
if (id.GetType() == typeof(Guid))
return new UUID((Guid)id);
if (id.GetType() == typeof(string))
if (id.GetType() == typeof(byte[]))
{
Guid gg;
if (Guid.TryParse((string)id, out gg))
return new UUID(gg);
return UUID.Zero;
if (((byte[])id).Length == 0)
return UUID.Zero;
else if (((byte[])id).Length == 16)
return new UUID((byte[])id, 0);
}
else if (id.GetType() == typeof(string))
{
if (((string)id).Length == 0)
return UUID.Zero;
else if (((string)id).Length == 36)
return new UUID((string)id);
}
if (idtype == typeof(byte[]))
{
if (((byte[])id).Length < 16)
return UUID.Zero;
return new UUID((byte[])id, 0);
}
throw new Exception("Failed to convert db value to UUID: " + id.ToString());
}
}

View File

@ -34,7 +34,7 @@ namespace OpenSim.Data
public interface IAssetDataPlugin : IPlugin
{
AssetBase GetAsset(UUID uuid);
bool StoreAsset(AssetBase asset);
void StoreAsset(AssetBase asset);
bool[] AssetsExist(UUID[] uuids);
List<AssetMetadata> FetchAssetMetadataSet(int start, int count);
void Initialise(string connect);

View File

@ -39,7 +39,7 @@ namespace OpenSim.Data
public Dictionary<string, string> Data;
}
public interface IAvatarData
public interface IAvatarData
{
AvatarBaseData[] Get(string field, string val);
bool Store(AvatarBaseData data);

View File

@ -46,14 +46,14 @@ namespace OpenSim.Data
/// <param name="create">If true, then an estate is created if one is not found.</param>
/// <returns></returns>
EstateSettings LoadEstateSettings(UUID regionID, bool create);
/// <summary>
/// Load estate settings for an estate ID.
/// </summary>
/// <param name="estateID"></param>
/// <returns></returns>
EstateSettings LoadEstateSettings(int estateID);
/// <summary>
/// Create a new estate.
/// </summary>
@ -67,7 +67,7 @@ namespace OpenSim.Data
/// </summary>
/// <returns>An empty list if no estates were found.</returns>
List<EstateSettings> LoadEstateSettingsAll();
/// <summary>
/// Store estate settings.
/// </summary>
@ -75,7 +75,7 @@ namespace OpenSim.Data
/// This is also called by EstateSettings.Save()</remarks>
/// <param name="es"></param>
void StoreEstateSettings(EstateSettings es);
/// <summary>
/// Get estate IDs.
/// </summary>
@ -88,13 +88,13 @@ namespace OpenSim.Data
/// </summary>
/// <returns>An empty list if no estates were found.</returns>
List<int> GetEstatesByOwner(UUID ownerID);
/// <summary>
/// Get the IDs of all estates.
/// </summary>
/// <returns>An empty list if no estates were found.</returns>
List<int> GetEstatesAll();
/// <summary>
/// Link a region to an estate.
/// </summary>
@ -102,14 +102,14 @@ namespace OpenSim.Data
/// <param name="estateID"></param>
/// <returns>true if the link succeeded, false otherwise</returns>
bool LinkRegion(UUID regionID, int estateID);
/// <summary>
/// Get the UUIDs of all the regions in an estate.
/// </summary>
/// <param name="estateID"></param>
/// <returns></returns>
List<UUID> GetRegions(int estateID);
/// <summary>
/// Delete an estate
/// </summary>

View File

@ -1,47 +0,0 @@
/*
* Copyright (c) Contributors, http://opensimulator.org/
* See CONTRIBUTORS.TXT for a full list of copyright holders.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the OpenSimulator Project nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
using System.Collections.Generic;
using OpenMetaverse;
using OpenSim.Framework;
namespace OpenSim.Data
{
public delegate string FSStoreDelegate(AssetBase asset, bool force);
public interface IFSAssetDataPlugin : IPlugin
{
bool[] AssetsExist(UUID[] uuids);
void Initialise(string connect, string realm, int SkipAccessTimeDays);
bool Delete(string id);
AssetMetadata Get(string id, out string hash);
bool Store(AssetMetadata metadata, string hash);
void Import(string conn, string table, int start, int count, bool force, FSStoreDelegate store);
int Count();
}
}

View File

@ -47,7 +47,7 @@ namespace OpenSim.Data
/// <summary>
/// An interface for connecting to the user grid datastore
/// </summary>
public interface IGridUserData
public interface IGridUserData
{
GridUserData Get(string userID);
GridUserData[] GetAll(string query);

View File

@ -81,7 +81,7 @@ namespace OpenSim.Data
}
public interface IGroupsData
public interface IGroupsData
{
// groups table
bool StoreGroup(GroupData data);

View File

@ -48,7 +48,7 @@ namespace OpenSim.Data
/// <summary>
/// An interface for connecting to the user grid datastore
/// </summary>
public interface IHGTravelingData
public interface IHGTravelingData
{
HGTravelingData Get(UUID sessionID);
HGTravelingData[] GetSessions(UUID userID);

View File

@ -39,7 +39,7 @@ namespace OpenSim.Data
}
public interface IOfflineIMData
public interface IOfflineIMData
{
OfflineIMData[] Get(string field, string val);
long GetCount(string field, string key);

View File

@ -44,7 +44,7 @@ namespace OpenSim.Data
/// <summary>
/// An interface for connecting to the presence datastore
/// </summary>
public interface IPresenceData
public interface IPresenceData
{
bool Store(PresenceData data);

View File

@ -48,7 +48,7 @@ namespace OpenSim.Data
bool UpdateAvatarProperties(ref UserProfileProperties props, ref string result);
bool UpdateAvatarInterests(UserProfileProperties up, ref string result);
bool GetClassifiedInfo(ref UserClassifiedAdd ad, ref string result);
bool UpdateUserPreferences(ref UserPreferences pref, ref string result);
bool UpdateUserPreferences(ref UserPreferences pref, ref string result);
bool GetUserPreferences(ref UserPreferences pref, ref string result);
bool GetUserAppData(ref UserAppData props, ref string result);
bool SetUserAppData(UserAppData props, ref string result);

View File

@ -67,12 +67,10 @@ namespace OpenSim.Data
/// <summary>
/// An interface for connecting to the authentication datastore
/// </summary>
public interface IRegionData
public interface IRegionData
{
RegionData Get(UUID regionID, UUID ScopeID);
List<RegionData> Get(string regionName, UUID ScopeID);
RegionData GetSpecific(string regionName, UUID ScopeID);
RegionData Get(int x, int y, UUID ScopeID);
List<RegionData> Get(int xStart, int yStart, int xEnd, int yEnd, UUID ScopeID);

View File

@ -50,6 +50,5 @@ namespace OpenSim.Data
bool Store(UserAccountData data);
bool Delete(string field, string val);
UserAccountData[] GetUsers(UUID scopeID, string query);
UserAccountData[] GetUsersWhere(UUID scopeID, string where);
}
}

View File

@ -38,12 +38,12 @@ namespace OpenSim.Data
public UUID ownerRoleID;
public string name;
public string charter;
public bool showInList;
public UUID insigniaID;
public bool showInList;
public UUID insigniaID;
public int membershipFee;
public bool openEnrollment;
public bool allowPublish;
public bool maturePublish;
public bool maturePublish;
public UUID founderID;
public ulong everyonePowers;
public ulong ownersPowers;

View File

@ -0,0 +1,314 @@
/*
* Copyright (c) Contributors, http://opensimulator.org/
* See CONTRIBUTORS.TXT for a full list of copyright holders.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the OpenSimulator Project nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
using System;
using System.Data;
using System.Data.SqlClient;
using System.Reflection;
using System.Collections.Generic;
using OpenMetaverse;
using log4net;
using OpenSim.Framework;
namespace OpenSim.Data.MSSQL
{
/// <summary>
/// A MSSQL Interface for the Asset server
/// </summary>
public class MSSQLAssetData : AssetDataBase
{
private const string _migrationStore = "AssetStore";
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private long m_ticksToEpoch;
/// <summary>
/// Database manager
/// </summary>
private MSSQLManager m_database;
private string m_connectionString;
#region IPlugin Members
override public void Dispose() { }
/// <summary>
/// <para>Initialises asset interface</para>
/// </summary>
// [Obsolete("Cannot be default-initialized!")]
override public void Initialise()
{
m_log.Info("[MSSQLAssetData]: " + Name + " cannot be default-initialized!");
throw new PluginNotInitialisedException(Name);
}
/// <summary>
/// Initialises asset interface
/// </summary>
/// <para>
/// a string instead of file, if someone writes the support
/// </para>
/// <param name="connectionString">connect string</param>
override public void Initialise(string connectionString)
{
m_ticksToEpoch = new System.DateTime(1970, 1, 1).Ticks;
m_database = new MSSQLManager(connectionString);
m_connectionString = connectionString;
//New migration to check for DB changes
m_database.CheckMigration(_migrationStore);
}
/// <summary>
/// Database provider version.
/// </summary>
override public string Version
{
get { return m_database.getVersion(); }
}
/// <summary>
/// The name of this DB provider.
/// </summary>
override public string Name
{
get { return "MSSQL Asset storage engine"; }
}
#endregion
#region IAssetDataPlugin Members
/// <summary>
/// Fetch Asset from m_database
/// </summary>
/// <param name="assetID">the asset UUID</param>
/// <returns></returns>
override public AssetBase GetAsset(UUID assetID)
{
string sql = "SELECT * FROM assets WHERE id = @id";
using (SqlConnection conn = new SqlConnection(m_connectionString))
using (SqlCommand cmd = new SqlCommand(sql, conn))
{
cmd.Parameters.Add(m_database.CreateParameter("id", assetID));
conn.Open();
using (SqlDataReader reader = cmd.ExecuteReader())
{
if (reader.Read())
{
AssetBase asset = new AssetBase(
DBGuid.FromDB(reader["id"]),
(string)reader["name"],
Convert.ToSByte(reader["assetType"]),
reader["creatorid"].ToString()
);
// Region Main
asset.Description = (string)reader["description"];
asset.Local = Convert.ToBoolean(reader["local"]);
asset.Temporary = Convert.ToBoolean(reader["temporary"]);
asset.Flags = (AssetFlags)(Convert.ToInt32(reader["asset_flags"]));
asset.Data = (byte[])reader["data"];
return asset;
}
return null; // throw new Exception("No rows to return");
}
}
}
/// <summary>
/// Create asset in m_database
/// </summary>
/// <param name="asset">the asset</param>
override public void StoreAsset(AssetBase asset)
{
string sql =
@"IF EXISTS(SELECT * FROM assets WHERE id=@id)
UPDATE assets set name = @name, description = @description, assetType = @assetType,
local = @local, temporary = @temporary, creatorid = @creatorid, data = @data
WHERE id=@id
ELSE
INSERT INTO assets
([id], [name], [description], [assetType], [local],
[temporary], [create_time], [access_time], [creatorid], [asset_flags], [data])
VALUES
(@id, @name, @description, @assetType, @local,
@temporary, @create_time, @access_time, @creatorid, @asset_flags, @data)";
string assetName = asset.Name;
if (asset.Name.Length > AssetBase.MAX_ASSET_NAME)
{
assetName = asset.Name.Substring(0, AssetBase.MAX_ASSET_NAME);
m_log.WarnFormat(
"[ASSET DB]: Name '{0}' for asset {1} truncated from {2} to {3} characters on add",
asset.Name, asset.ID, asset.Name.Length, assetName.Length);
}
string assetDescription = asset.Description;
if (asset.Description.Length > AssetBase.MAX_ASSET_DESC)
{
assetDescription = asset.Description.Substring(0, AssetBase.MAX_ASSET_DESC);
m_log.WarnFormat(
"[ASSET DB]: Description '{0}' for asset {1} truncated from {2} to {3} characters on add",
asset.Description, asset.ID, asset.Description.Length, assetDescription.Length);
}
using (SqlConnection conn = new SqlConnection(m_connectionString))
using (SqlCommand command = new SqlCommand(sql, conn))
{
int now = (int)((System.DateTime.Now.Ticks - m_ticksToEpoch) / 10000000);
command.Parameters.Add(m_database.CreateParameter("id", asset.FullID));
command.Parameters.Add(m_database.CreateParameter("name", assetName));
command.Parameters.Add(m_database.CreateParameter("description", assetDescription));
command.Parameters.Add(m_database.CreateParameter("assetType", asset.Type));
command.Parameters.Add(m_database.CreateParameter("local", asset.Local));
command.Parameters.Add(m_database.CreateParameter("temporary", asset.Temporary));
command.Parameters.Add(m_database.CreateParameter("access_time", now));
command.Parameters.Add(m_database.CreateParameter("create_time", now));
command.Parameters.Add(m_database.CreateParameter("asset_flags", (int)asset.Flags));
command.Parameters.Add(m_database.CreateParameter("creatorid", asset.Metadata.CreatorID));
command.Parameters.Add(m_database.CreateParameter("data", asset.Data));
conn.Open();
try
{
command.ExecuteNonQuery();
}
catch(Exception e)
{
m_log.Error("[ASSET DB]: Error storing item :" + e.Message);
}
}
}
// Commented out since currently unused - this probably should be called in GetAsset()
// private void UpdateAccessTime(AssetBase asset)
// {
// using (AutoClosingSqlCommand cmd = m_database.Query("UPDATE assets SET access_time = @access_time WHERE id=@id"))
// {
// int now = (int)((System.DateTime.Now.Ticks - m_ticksToEpoch) / 10000000);
// cmd.Parameters.AddWithValue("@id", asset.FullID.ToString());
// cmd.Parameters.AddWithValue("@access_time", now);
// try
// {
// cmd.ExecuteNonQuery();
// }
// catch (Exception e)
// {
// m_log.Error(e.ToString());
// }
// }
// }
/// <summary>
/// Check if the assets exist in the database.
/// </summary>
/// <param name="uuids">The assets' IDs</param>
/// <returns>For each asset: true if it exists, false otherwise</returns>
public override bool[] AssetsExist(UUID[] uuids)
{
if (uuids.Length == 0)
return new bool[0];
HashSet<UUID> exist = new HashSet<UUID>();
string ids = "'" + string.Join("','", uuids) + "'";
string sql = string.Format("SELECT id FROM assets WHERE id IN ({0})", ids);
using (SqlConnection conn = new SqlConnection(m_connectionString))
using (SqlCommand cmd = new SqlCommand(sql, conn))
{
conn.Open();
using (SqlDataReader reader = cmd.ExecuteReader())
{
while (reader.Read())
{
UUID id = DBGuid.FromDB(reader["id"]);
exist.Add(id);
}
}
}
bool[] results = new bool[uuids.Length];
for (int i = 0; i < uuids.Length; i++)
results[i] = exist.Contains(uuids[i]);
return results;
}
/// <summary>
/// Returns a list of AssetMetadata objects. The list is a subset of
/// the entire data set offset by <paramref name="start" /> containing
/// <paramref name="count" /> elements.
/// </summary>
/// <param name="start">The number of results to discard from the total data set.</param>
/// <param name="count">The number of rows the returned list should contain.</param>
/// <returns>A list of AssetMetadata objects.</returns>
public override List<AssetMetadata> FetchAssetMetadataSet(int start, int count)
{
List<AssetMetadata> retList = new List<AssetMetadata>(count);
string sql = @"WITH OrderedAssets AS
(
SELECT id, name, description, assetType, temporary, creatorid,
RowNumber = ROW_NUMBER() OVER (ORDER BY id)
FROM assets
)
SELECT *
FROM OrderedAssets
WHERE RowNumber BETWEEN @start AND @stop;";
using (SqlConnection conn = new SqlConnection(m_connectionString))
using (SqlCommand cmd = new SqlCommand(sql, conn))
{
cmd.Parameters.Add(m_database.CreateParameter("start", start));
cmd.Parameters.Add(m_database.CreateParameter("stop", start + count - 1));
conn.Open();
using (SqlDataReader reader = cmd.ExecuteReader())
{
while (reader.Read())
{
AssetMetadata metadata = new AssetMetadata();
metadata.FullID = DBGuid.FromDB(reader["id"]);
metadata.Name = (string)reader["name"];
metadata.Description = (string)reader["description"];
metadata.Type = Convert.ToSByte(reader["assetType"]);
metadata.Temporary = Convert.ToBoolean(reader["temporary"]);
metadata.CreatorID = (string)reader["creatorid"];
retList.Add(metadata);
}
}
}
return retList;
}
public override bool Delete(string id)
{
return false;
}
#endregion
}
}

View File

@ -0,0 +1,227 @@
/*
* Copyright (c) Contributors, http://opensimulator.org/
* See CONTRIBUTORS.TXT for a full list of copyright holders.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the OpenSimulator Project nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ''AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using OpenMetaverse;
using OpenSim.Framework;
using System.Data.SqlClient;
using System.Reflection;
using System.Text;
namespace OpenSim.Data.MSSQL
{
public class MSSQLAuthenticationData : IAuthenticationData
{
private string m_Realm;
private List<string> m_ColumnNames = null;
private int m_LastExpire = 0;
private string m_ConnectionString;
private MSSQLManager m_database;
public MSSQLAuthenticationData(string connectionString, string realm)
{
m_Realm = realm;
m_ConnectionString = connectionString;
using (SqlConnection conn = new SqlConnection(m_ConnectionString))
{
conn.Open();
Migration m = new Migration(conn, GetType().Assembly, "AuthStore");
m_database = new MSSQLManager(m_ConnectionString);
m.Update();
}
}
public AuthenticationData Get(UUID principalID)
{
AuthenticationData ret = new AuthenticationData();
ret.Data = new Dictionary<string, object>();
string sql = string.Format("select * from {0} where UUID = @principalID", m_Realm);
using (SqlConnection conn = new SqlConnection(m_ConnectionString))
using (SqlCommand cmd = new SqlCommand(sql, conn))
{
cmd.Parameters.Add(m_database.CreateParameter("@principalID", principalID));
conn.Open();
using (SqlDataReader result = cmd.ExecuteReader())
{
if (result.Read())
{
ret.PrincipalID = principalID;
if (m_ColumnNames == null)
{
m_ColumnNames = new List<string>();
DataTable schemaTable = result.GetSchemaTable();
foreach (DataRow row in schemaTable.Rows)
m_ColumnNames.Add(row["ColumnName"].ToString());
}
foreach (string s in m_ColumnNames)
{
if (s == "UUID")
continue;
ret.Data[s] = result[s].ToString();
}
return ret;
}
}
}
return null;
}
public bool Store(AuthenticationData data)
{
if (data.Data.ContainsKey("UUID"))
data.Data.Remove("UUID");
string[] fields = new List<string>(data.Data.Keys).ToArray();
StringBuilder updateBuilder = new StringBuilder();
using (SqlConnection conn = new SqlConnection(m_ConnectionString))
using (SqlCommand cmd = new SqlCommand())
{
updateBuilder.AppendFormat("update {0} set ", m_Realm);
bool first = true;
foreach (string field in fields)
{
if (!first)
updateBuilder.Append(", ");
updateBuilder.AppendFormat("{0} = @{0}",field);
first = false;
cmd.Parameters.Add(m_database.CreateParameter("@" + field, data.Data[field]));
}
updateBuilder.Append(" where UUID = @principalID");
cmd.CommandText = updateBuilder.ToString();
cmd.Connection = conn;
cmd.Parameters.Add(m_database.CreateParameter("@principalID", data.PrincipalID));
conn.Open();
if (cmd.ExecuteNonQuery() < 1)
{
StringBuilder insertBuilder = new StringBuilder();
insertBuilder.AppendFormat("insert into {0} (UUID, ", m_Realm);
insertBuilder.Append(String.Join(", ", fields));
insertBuilder.Append(") values (@principalID, @");
insertBuilder.Append(String.Join(", @", fields));
insertBuilder.Append(")");
cmd.CommandText = insertBuilder.ToString();
if (cmd.ExecuteNonQuery() < 1)
{
return false;
}
}
}
return true;
}
public bool SetDataItem(UUID principalID, string item, string value)
{
string sql = string.Format("update {0} set {1} = @{1} where UUID = @UUID", m_Realm, item);
using (SqlConnection conn = new SqlConnection(m_ConnectionString))
using (SqlCommand cmd = new SqlCommand(sql, conn))
{
cmd.Parameters.Add(m_database.CreateParameter("@" + item, value));
conn.Open();
if (cmd.ExecuteNonQuery() > 0)
return true;
}
return false;
}
public bool SetToken(UUID principalID, string token, int lifetime)
{
if (System.Environment.TickCount - m_LastExpire > 30000)
DoExpire();
string sql = "insert into tokens (UUID, token, validity) values (@principalID, @token, @lifetime)";
using (SqlConnection conn = new SqlConnection(m_ConnectionString))
using (SqlCommand cmd = new SqlCommand(sql, conn))
{
cmd.Parameters.Add(m_database.CreateParameter("@principalID", principalID));
cmd.Parameters.Add(m_database.CreateParameter("@token", token));
cmd.Parameters.Add(m_database.CreateParameter("@lifetime", DateTime.Now.AddMinutes(lifetime)));
conn.Open();
if (cmd.ExecuteNonQuery() > 0)
{
return true;
}
}
return false;
}
public bool CheckToken(UUID principalID, string token, int lifetime)
{
if (System.Environment.TickCount - m_LastExpire > 30000)
DoExpire();
DateTime validDate = DateTime.Now.AddMinutes(lifetime);
string sql = "update tokens set validity = @validDate where UUID = @principalID and token = @token and validity > GetDate()";
using (SqlConnection conn = new SqlConnection(m_ConnectionString))
using (SqlCommand cmd = new SqlCommand(sql, conn))
{
cmd.Parameters.Add(m_database.CreateParameter("@principalID", principalID));
cmd.Parameters.Add(m_database.CreateParameter("@token", token));
cmd.Parameters.Add(m_database.CreateParameter("@validDate", validDate));
conn.Open();
if (cmd.ExecuteNonQuery() > 0)
{
return true;
}
}
return false;
}
private void DoExpire()
{
DateTime currentDateTime = DateTime.Now;
string sql = "delete from tokens where validity < @currentDateTime";
using (SqlConnection conn = new SqlConnection(m_ConnectionString))
using (SqlCommand cmd = new SqlCommand(sql, conn))
{
conn.Open();
cmd.Parameters.Add(m_database.CreateParameter("@currentDateTime", currentDateTime));
cmd.ExecuteNonQuery();
}
m_LastExpire = System.Environment.TickCount;
}
}
}

View File

@ -26,46 +26,46 @@
*/
using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Reflection;
using System.Threading;
using log4net;
using OpenMetaverse;
using OpenSim.Framework;
#if CSharpSqlite
using Community.CsharpSqlite.Sqlite;
#else
using Mono.Data.Sqlite;
#endif
using System.Data.SqlClient;
namespace OpenSim.Data.SQLite
namespace OpenSim.Data.MSSQL
{
public class SQLiteMuteListData : SQLiteGenericTableHandler<MuteData>, IMuteListData
/// <summary>
/// A MSSQL Interface for Avatar Storage
/// </summary>
public class MSSQLAvatarData : MSSQLGenericTableHandler<AvatarBaseData>,
IAvatarData
{
public SQLiteMuteListData(string connectionString)
: base(connectionString, "MuteList", "MuteListStore")
// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
public MSSQLAvatarData(string connectionString, string realm) :
base(connectionString, realm, "Avatar")
{
}
public MuteData[] Get(UUID agentID)
public bool Delete(UUID principalID, string name)
{
MuteData[] data = base.Get("AgentID", agentID.ToString());
return data;
}
public bool Delete(UUID agentID, UUID muteID, string muteName)
{
using (SqliteCommand cmd = new SqliteCommand())
using (SqlConnection conn = new SqlConnection(m_ConnectionString))
using (SqlCommand cmd = new SqlCommand())
{
cmd.CommandText = "delete from MuteList where `AgentID` = :AgentID and `MuteID` = :MuteID and `MuteName` = :MuteName";
cmd.Parameters.AddWithValue(":AgentID", agentID.ToString());
cmd.Parameters.AddWithValue(":MuteID", muteID.ToString());
cmd.Parameters.AddWithValue(":MuteName", muteName);
if (ExecuteNonQuery(cmd, m_Connection) > 0)
cmd.CommandText = String.Format("DELETE FROM {0} where [PrincipalID] = @PrincipalID and [Name] = @Name", m_Realm);
cmd.Parameters.Add(m_database.CreateParameter("@PrincipalID", principalID.ToString()));
cmd.Parameters.Add(m_database.CreateParameter("@Name", name));
cmd.Connection = conn;
conn.Open();
if (cmd.ExecuteNonQuery() > 0)
return true;
return false;
}
}
}
}
}

View File

@ -0,0 +1,577 @@
/*
* Copyright (c) Contributors, http://opensimulator.org/
* See CONTRIBUTORS.TXT for a full list of copyright holders.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the OpenSimulator Project nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.Reflection;
using log4net;
using OpenMetaverse;
using OpenSim.Framework;
using OpenSim.Region.Framework.Interfaces;
namespace OpenSim.Data.MSSQL
{
public class MSSQLEstateStore : IEstateDataStore
{
private const string _migrationStore = "EstateStore";
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private MSSQLManager _Database;
private string m_connectionString;
private FieldInfo[] _Fields;
private Dictionary<string, FieldInfo> _FieldMap = new Dictionary<string, FieldInfo>();
#region Public methods
public MSSQLEstateStore()
{
}
public MSSQLEstateStore(string connectionString)
{
Initialise(connectionString);
}
/// <summary>
/// Initialises the estatedata class.
/// </summary>
/// <param name="connectionString">connectionString.</param>
public void Initialise(string connectionString)
{
if (!string.IsNullOrEmpty(connectionString))
{
m_connectionString = connectionString;
_Database = new MSSQLManager(connectionString);
}
//Migration settings
using (SqlConnection conn = new SqlConnection(m_connectionString))
{
conn.Open();
Migration m = new Migration(conn, GetType().Assembly, "EstateStore");
m.Update();
}
//Interesting way to get parameters! Maybe implement that also with other types
Type t = typeof(EstateSettings);
_Fields = t.GetFields(BindingFlags.NonPublic |
BindingFlags.Instance |
BindingFlags.DeclaredOnly);
foreach (FieldInfo f in _Fields)
{
if (f.Name.Substring(0, 2) == "m_")
_FieldMap[f.Name.Substring(2)] = f;
}
}
/// <summary>
/// Loads the estate settings.
/// </summary>
/// <param name="regionID">region ID.</param>
/// <returns></returns>
public EstateSettings LoadEstateSettings(UUID regionID, bool create)
{
EstateSettings es = new EstateSettings();
string sql = "select estate_settings." + String.Join(",estate_settings.", FieldList) + " from estate_map left join estate_settings on estate_map.EstateID = estate_settings.EstateID where estate_settings.EstateID is not null and RegionID = @RegionID";
bool insertEstate = false;
using (SqlConnection conn = new SqlConnection(m_connectionString))
using (SqlCommand cmd = new SqlCommand(sql, conn))
{
cmd.Parameters.Add(_Database.CreateParameter("@RegionID", regionID));
conn.Open();
using (SqlDataReader reader = cmd.ExecuteReader())
{
if (reader.Read())
{
foreach (string name in FieldList)
{
FieldInfo f = _FieldMap[name];
object v = reader[name];
if (f.FieldType == typeof(bool))
{
f.SetValue(es, Convert.ToInt32(v) != 0);
}
else if (f.FieldType == typeof(UUID))
{
f.SetValue(es, new UUID((Guid)v)); // uuid);
}
else if (f.FieldType == typeof(string))
{
f.SetValue(es, v.ToString());
}
else if (f.FieldType == typeof(UInt32))
{
f.SetValue(es, Convert.ToUInt32(v));
}
else if (f.FieldType == typeof(Single))
{
f.SetValue(es, Convert.ToSingle(v));
}
else
f.SetValue(es, v);
}
}
else
{
insertEstate = true;
}
}
}
if (insertEstate && create)
{
DoCreate(es);
LinkRegion(regionID, (int)es.EstateID);
}
LoadBanList(es);
es.EstateManagers = LoadUUIDList(es.EstateID, "estate_managers");
es.EstateAccess = LoadUUIDList(es.EstateID, "estate_users");
es.EstateGroups = LoadUUIDList(es.EstateID, "estate_groups");
//Set event
es.OnSave += StoreEstateSettings;
return es;
}
public EstateSettings CreateNewEstate()
{
EstateSettings es = new EstateSettings();
es.OnSave += StoreEstateSettings;
DoCreate(es);
LoadBanList(es);
es.EstateManagers = LoadUUIDList(es.EstateID, "estate_managers");
es.EstateAccess = LoadUUIDList(es.EstateID, "estate_users");
es.EstateGroups = LoadUUIDList(es.EstateID, "estate_groups");
return es;
}
private void DoCreate(EstateSettings es)
{
List<string> names = new List<string>(FieldList);
names.Remove("EstateID");
string sql = string.Format("insert into estate_settings ({0}) values ( @{1})", String.Join(",", names.ToArray()), String.Join(", @", names.ToArray()));
//_Log.Debug("[DB ESTATE]: SQL: " + sql);
using (SqlConnection conn = new SqlConnection(m_connectionString))
using (SqlCommand insertCommand = new SqlCommand(sql, conn))
{
insertCommand.CommandText = sql + " SET @ID = SCOPE_IDENTITY()";
foreach (string name in names)
{
insertCommand.Parameters.Add(_Database.CreateParameter("@" + name, _FieldMap[name].GetValue(es)));
}
SqlParameter idParameter = new SqlParameter("@ID", SqlDbType.Int);
idParameter.Direction = ParameterDirection.Output;
insertCommand.Parameters.Add(idParameter);
conn.Open();
insertCommand.ExecuteNonQuery();
es.EstateID = Convert.ToUInt32(idParameter.Value);
}
//TODO check if this is needed??
es.Save();
}
/// <summary>
/// Stores the estate settings.
/// </summary>
/// <param name="es">estate settings</param>
public void StoreEstateSettings(EstateSettings es)
{
List<string> names = new List<string>(FieldList);
names.Remove("EstateID");
string sql = string.Format("UPDATE estate_settings SET ");
foreach (string name in names)
{
sql += name + " = @" + name + ", ";
}
sql = sql.Remove(sql.LastIndexOf(","));
sql += " WHERE EstateID = @EstateID";
using (SqlConnection conn = new SqlConnection(m_connectionString))
using (SqlCommand cmd = new SqlCommand(sql, conn))
{
foreach (string name in names)
{
cmd.Parameters.Add(_Database.CreateParameter("@" + name, _FieldMap[name].GetValue(es)));
}
cmd.Parameters.Add(_Database.CreateParameter("@EstateID", es.EstateID));
conn.Open();
cmd.ExecuteNonQuery();
}
SaveBanList(es);
SaveUUIDList(es.EstateID, "estate_managers", es.EstateManagers);
SaveUUIDList(es.EstateID, "estate_users", es.EstateAccess);
SaveUUIDList(es.EstateID, "estate_groups", es.EstateGroups);
}
#endregion
#region Private methods
private string[] FieldList
{
get { return new List<string>(_FieldMap.Keys).ToArray(); }
}
private void LoadBanList(EstateSettings es)
{
es.ClearBans();
string sql = "select bannedUUID from estateban where EstateID = @EstateID";
using (SqlConnection conn = new SqlConnection(m_connectionString))
using (SqlCommand cmd = new SqlCommand(sql, conn))
{
SqlParameter idParameter = new SqlParameter("@EstateID", SqlDbType.Int);
idParameter.Value = es.EstateID;
cmd.Parameters.Add(idParameter);
conn.Open();
using (SqlDataReader reader = cmd.ExecuteReader())
{
while (reader.Read())
{
EstateBan eb = new EstateBan();
eb.BannedUserID = new UUID((Guid)reader["bannedUUID"]); //uuid;
eb.BannedHostAddress = "0.0.0.0";
eb.BannedHostIPMask = "0.0.0.0";
es.AddBan(eb);
}
}
}
}
private UUID[] LoadUUIDList(uint estateID, string table)
{
List<UUID> uuids = new List<UUID>();
string sql = string.Format("select uuid from {0} where EstateID = @EstateID", table);
using (SqlConnection conn = new SqlConnection(m_connectionString))
using (SqlCommand cmd = new SqlCommand(sql, conn))
{
cmd.Parameters.Add(_Database.CreateParameter("@EstateID", estateID));
conn.Open();
using (SqlDataReader reader = cmd.ExecuteReader())
{
while (reader.Read())
{
uuids.Add(new UUID((Guid)reader["uuid"])); //uuid);
}
}
}
return uuids.ToArray();
}
private void SaveBanList(EstateSettings es)
{
//Delete first
using (SqlConnection conn = new SqlConnection(m_connectionString))
{
conn.Open();
using (SqlCommand cmd = conn.CreateCommand())
{
cmd.CommandText = "delete from estateban where EstateID = @EstateID";
cmd.Parameters.AddWithValue("@EstateID", (int)es.EstateID);
cmd.ExecuteNonQuery();
//Insert after
cmd.CommandText = "insert into estateban (EstateID, bannedUUID,bannedIp, bannedIpHostMask, bannedNameMask) values ( @EstateID, @bannedUUID, '','','' )";
cmd.Parameters.AddWithValue("@bannedUUID", Guid.Empty);
foreach (EstateBan b in es.EstateBans)
{
cmd.Parameters["@bannedUUID"].Value = b.BannedUserID.Guid;
cmd.ExecuteNonQuery();
}
}
}
}
private void SaveUUIDList(uint estateID, string table, UUID[] data)
{
using (SqlConnection conn = new SqlConnection(m_connectionString))
{
conn.Open();
using (SqlCommand cmd = conn.CreateCommand())
{
cmd.Parameters.AddWithValue("@EstateID", (int)estateID);
cmd.CommandText = string.Format("delete from {0} where EstateID = @EstateID", table);
cmd.ExecuteNonQuery();
cmd.CommandText = string.Format("insert into {0} (EstateID, uuid) values ( @EstateID, @uuid )", table);
cmd.Parameters.AddWithValue("@uuid", Guid.Empty);
foreach (UUID uuid in data)
{
cmd.Parameters["@uuid"].Value = uuid.Guid; //.ToString(); //TODO check if this works
cmd.ExecuteNonQuery();
}
}
}
}
public EstateSettings LoadEstateSettings(int estateID)
{
EstateSettings es = new EstateSettings();
string sql = "select estate_settings." + String.Join(",estate_settings.", FieldList) + " from estate_settings where EstateID = @EstateID";
using (SqlConnection conn = new SqlConnection(m_connectionString))
{
conn.Open();
using (SqlCommand cmd = new SqlCommand(sql, conn))
{
cmd.Parameters.AddWithValue("@EstateID", (int)estateID);
using (SqlDataReader reader = cmd.ExecuteReader())
{
if (reader.Read())
{
foreach (string name in FieldList)
{
FieldInfo f = _FieldMap[name];
object v = reader[name];
if (f.FieldType == typeof(bool))
{
f.SetValue(es, Convert.ToInt32(v) != 0);
}
else if (f.FieldType == typeof(UUID))
{
f.SetValue(es, new UUID((Guid)v)); // uuid);
}
else if (f.FieldType == typeof(string))
{
f.SetValue(es, v.ToString());
}
else if (f.FieldType == typeof(UInt32))
{
f.SetValue(es, Convert.ToUInt32(v));
}
else if (f.FieldType == typeof(Single))
{
f.SetValue(es, Convert.ToSingle(v));
}
else
f.SetValue(es, v);
}
}
}
}
}
LoadBanList(es);
es.EstateManagers = LoadUUIDList(es.EstateID, "estate_managers");
es.EstateAccess = LoadUUIDList(es.EstateID, "estate_users");
es.EstateGroups = LoadUUIDList(es.EstateID, "estate_groups");
//Set event
es.OnSave += StoreEstateSettings;
return es;
}
public List<EstateSettings> LoadEstateSettingsAll()
{
List<EstateSettings> allEstateSettings = new List<EstateSettings>();
List<int> allEstateIds = GetEstatesAll();
foreach (int estateId in allEstateIds)
allEstateSettings.Add(LoadEstateSettings(estateId));
return allEstateSettings;
}
public List<int> GetEstates(string search)
{
List<int> result = new List<int>();
string sql = "select estateID from estate_settings where EstateName = @EstateName";
using (SqlConnection conn = new SqlConnection(m_connectionString))
{
conn.Open();
using (SqlCommand cmd = new SqlCommand(sql, conn))
{
cmd.Parameters.AddWithValue("@EstateName", search);
using (IDataReader reader = cmd.ExecuteReader())
{
while (reader.Read())
{
result.Add(Convert.ToInt32(reader["EstateID"]));
}
reader.Close();
}
}
}
return result;
}
public List<int> GetEstatesAll()
{
List<int> result = new List<int>();
string sql = "select estateID from estate_settings";
using (SqlConnection conn = new SqlConnection(m_connectionString))
{
conn.Open();
using (SqlCommand cmd = new SqlCommand(sql, conn))
{
using (IDataReader reader = cmd.ExecuteReader())
{
while (reader.Read())
{
result.Add(Convert.ToInt32(reader["EstateID"]));
}
reader.Close();
}
}
}
return result;
}
public List<int> GetEstatesByOwner(UUID ownerID)
{
List<int> result = new List<int>();
string sql = "select estateID from estate_settings where EstateOwner = @EstateOwner";
using (SqlConnection conn = new SqlConnection(m_connectionString))
{
conn.Open();
using (SqlCommand cmd = new SqlCommand(sql, conn))
{
cmd.Parameters.AddWithValue("@EstateOwner", ownerID);
using (IDataReader reader = cmd.ExecuteReader())
{
while (reader.Read())
{
result.Add(Convert.ToInt32(reader["EstateID"]));
}
reader.Close();
}
}
}
return result;
}
public bool LinkRegion(UUID regionID, int estateID)
{
string deleteSQL = "delete from estate_map where RegionID = @RegionID";
string insertSQL = "insert into estate_map values (@RegionID, @EstateID)";
using (SqlConnection conn = new SqlConnection(m_connectionString))
{
conn.Open();
SqlTransaction transaction = conn.BeginTransaction();
try
{
using (SqlCommand cmd = new SqlCommand(deleteSQL, conn))
{
cmd.Transaction = transaction;
cmd.Parameters.AddWithValue("@RegionID", regionID.Guid);
cmd.ExecuteNonQuery();
}
using (SqlCommand cmd = new SqlCommand(insertSQL, conn))
{
cmd.Transaction = transaction;
cmd.Parameters.AddWithValue("@RegionID", regionID.Guid);
cmd.Parameters.AddWithValue("@EstateID", estateID);
int ret = cmd.ExecuteNonQuery();
if (ret != 0)
transaction.Commit();
else
transaction.Rollback();
return (ret != 0);
}
}
catch (Exception ex)
{
m_log.Error("[REGION DB]: LinkRegion failed: " + ex.Message);
transaction.Rollback();
}
}
return false;
}
public List<UUID> GetRegions(int estateID)
{
List<UUID> result = new List<UUID>();
string sql = "select RegionID from estate_map where EstateID = @EstateID";
using (SqlConnection conn = new SqlConnection(m_connectionString))
{
conn.Open();
using (SqlCommand cmd = new SqlCommand(sql, conn))
{
cmd.Parameters.AddWithValue("@EstateID", estateID);
using (IDataReader reader = cmd.ExecuteReader())
{
while (reader.Read())
{
result.Add(DBGuid.FromDB(reader["RegionID"]));
}
reader.Close();
}
}
}
return result;
}
public bool DeleteEstate(int estateID)
{
// TODO: Implementation!
return false;
}
#endregion
}
}

View File

@ -0,0 +1,99 @@
/*
* Copyright (c) Contributors, http://opensimulator.org/
* See CONTRIBUTORS.TXT for a full list of copyright holders.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the OpenSimulator Project nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ''AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using OpenMetaverse;
using OpenSim.Framework;
using System.Data.SqlClient;
using System.Reflection;
using System.Text;
namespace OpenSim.Data.MSSQL
{
public class MSSQLFriendsData : MSSQLGenericTableHandler<FriendsData>, IFriendsData
{
public MSSQLFriendsData(string connectionString, string realm)
: base(connectionString, realm, "FriendsStore")
{
using (SqlConnection conn = new SqlConnection(m_ConnectionString))
{
conn.Open();
Migration m = new Migration(conn, GetType().Assembly, "FriendsStore");
m.Update();
}
}
public bool Delete(UUID principalID, string friend)
{
return Delete(principalID.ToString(), friend);
}
public override bool Delete(string principalID, string friend)
{
using (SqlConnection conn = new SqlConnection(m_ConnectionString))
using (SqlCommand cmd = new SqlCommand())
{
cmd.CommandText = String.Format("delete from {0} where PrincipalID = @PrincipalID and Friend = @Friend", m_Realm);
cmd.Parameters.Add(m_database.CreateParameter("@PrincipalID", principalID.ToString()));
cmd.Parameters.Add(m_database.CreateParameter("@Friend", friend));
cmd.Connection = conn;
conn.Open();
cmd.ExecuteNonQuery();
return true;
}
}
public FriendsData[] GetFriends(UUID principalID)
{
return GetFriends(principalID.ToString());
}
public FriendsData[] GetFriends(string principalID)
{
using (SqlConnection conn = new SqlConnection(m_ConnectionString))
using (SqlCommand cmd = new SqlCommand())
{
cmd.CommandText = String.Format("select a.*,case when b.Flags is null then -1 else b.Flags end as TheirFlags from {0} as a left join {0} as b on a.PrincipalID = b.Friend and a.Friend = b.PrincipalID where a.PrincipalID = @PrincipalID", m_Realm);
cmd.Parameters.Add(m_database.CreateParameter("@PrincipalID", principalID.ToString()));
cmd.Connection = conn;
conn.Open();
return DoQuery(cmd);
}
}
public FriendsData[] GetFriends(Guid principalID)
{
return GetFriends(principalID.ToString());
}
}
}

View File

@ -0,0 +1,384 @@
/*
* Copyright (c) Contributors, http://opensimulator.org/
* See CONTRIBUTORS.TXT for a full list of copyright holders.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the OpenSimulator Project nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
using System;
using System.Collections.Generic;
using System.Data;
using System.Reflection;
using log4net;
using System.Data.SqlClient;
using OpenMetaverse;
using OpenSim.Framework;
using OpenSim.Region.Framework.Interfaces;
using System.Text;
namespace OpenSim.Data.MSSQL
{
public class MSSQLGenericTableHandler<T> where T : class, new()
{
// private static readonly ILog m_log =
// LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
protected string m_ConnectionString;
protected MSSQLManager m_database; //used for parameter type translation
protected Dictionary<string, FieldInfo> m_Fields =
new Dictionary<string, FieldInfo>();
protected List<string> m_ColumnNames = null;
protected string m_Realm;
protected FieldInfo m_DataField = null;
public MSSQLGenericTableHandler(string connectionString,
string realm, string storeName)
{
m_Realm = realm;
m_ConnectionString = connectionString;
if (storeName != String.Empty)
{
using (SqlConnection conn = new SqlConnection(m_ConnectionString))
{
conn.Open();
Migration m = new Migration(conn, GetType().Assembly, storeName);
m.Update();
}
}
m_database = new MSSQLManager(m_ConnectionString);
Type t = typeof(T);
FieldInfo[] fields = t.GetFields(BindingFlags.Public |
BindingFlags.Instance |
BindingFlags.DeclaredOnly);
if (fields.Length == 0)
return;
foreach (FieldInfo f in fields)
{
if (f.Name != "Data")
m_Fields[f.Name] = f;
else
m_DataField = f;
}
}
private void CheckColumnNames(SqlDataReader reader)
{
if (m_ColumnNames != null)
return;
m_ColumnNames = new List<string>();
DataTable schemaTable = reader.GetSchemaTable();
foreach (DataRow row in schemaTable.Rows)
{
if (row["ColumnName"] != null &&
(!m_Fields.ContainsKey(row["ColumnName"].ToString())))
m_ColumnNames.Add(row["ColumnName"].ToString());
}
}
private List<string> GetConstraints()
{
List<string> constraints = new List<string>();
string query = string.Format(@"SELECT
COL_NAME(ic.object_id,ic.column_id) AS column_name
FROM sys.indexes AS i
INNER JOIN sys.index_columns AS ic
ON i.object_id = ic.object_id AND i.index_id = ic.index_id
WHERE i.is_primary_key = 1
AND i.object_id = OBJECT_ID('{0}');", m_Realm);
using (SqlConnection conn = new SqlConnection(m_ConnectionString))
using (SqlCommand cmd = new SqlCommand(query, conn))
{
conn.Open();
using (SqlDataReader rdr = cmd.ExecuteReader())
{
while (rdr.Read())
{
// query produces 0 to many rows of single column, so always add the first item in each row
constraints.Add((string)rdr[0]);
}
}
return constraints;
}
}
public virtual T[] Get(string field, string key)
{
return Get(new string[] { field }, new string[] { key });
}
public virtual T[] Get(string[] fields, string[] keys)
{
if (fields.Length != keys.Length)
return new T[0];
List<string> terms = new List<string>();
using (SqlConnection conn = new SqlConnection(m_ConnectionString))
using (SqlCommand cmd = new SqlCommand())
{
for (int i = 0; i < fields.Length; i++)
{
cmd.Parameters.Add(m_database.CreateParameter(fields[i], keys[i]));
terms.Add("[" + fields[i] + "] = @" + fields[i]);
}
string where = String.Join(" AND ", terms.ToArray());
string query = String.Format("SELECT * FROM {0} WHERE {1}",
m_Realm, where);
cmd.Connection = conn;
cmd.CommandText = query;
conn.Open();
return DoQuery(cmd);
}
}
protected T[] DoQuery(SqlCommand cmd)
{
List<T> result = new List<T>();
using (SqlDataReader reader = cmd.ExecuteReader())
{
if (reader == null)
return new T[0];
CheckColumnNames(reader);
while (reader.Read())
{
T row = new T();
foreach (string name in m_Fields.Keys)
{
if (m_Fields[name].GetValue(row) is bool)
{
int v = Convert.ToInt32(reader[name]);
m_Fields[name].SetValue(row, v != 0 ? true : false);
}
else if (m_Fields[name].GetValue(row) is UUID)
{
UUID uuid = UUID.Zero;
UUID.TryParse(reader[name].ToString(), out uuid);
m_Fields[name].SetValue(row, uuid);
}
else if (m_Fields[name].GetValue(row) is int)
{
int v = Convert.ToInt32(reader[name]);
m_Fields[name].SetValue(row, v);
}
else
{
m_Fields[name].SetValue(row, reader[name]);
}
}
if (m_DataField != null)
{
Dictionary<string, string> data =
new Dictionary<string, string>();
foreach (string col in m_ColumnNames)
{
data[col] = reader[col].ToString();
if (data[col] == null)
data[col] = String.Empty;
}
m_DataField.SetValue(row, data);
}
result.Add(row);
}
return result.ToArray();
}
}
public virtual T[] Get(string where)
{
using (SqlConnection conn = new SqlConnection(m_ConnectionString))
using (SqlCommand cmd = new SqlCommand())
{
string query = String.Format("SELECT * FROM {0} WHERE {1}",
m_Realm, where);
cmd.Connection = conn;
cmd.CommandText = query;
//m_log.WarnFormat("[MSSQLGenericTable]: SELECT {0} WHERE {1}", m_Realm, where);
conn.Open();
return DoQuery(cmd);
}
}
public virtual bool Store(T row)
{
List<string> constraintFields = GetConstraints();
List<KeyValuePair<string, string>> constraints = new List<KeyValuePair<string, string>>();
using (SqlConnection conn = new SqlConnection(m_ConnectionString))
using (SqlCommand cmd = new SqlCommand())
{
StringBuilder query = new StringBuilder();
List<String> names = new List<String>();
List<String> values = new List<String>();
foreach (FieldInfo fi in m_Fields.Values)
{
names.Add(fi.Name);
values.Add("@" + fi.Name);
// Temporarily return more information about what field is unexpectedly null for
// http://opensimulator.org/mantis/view.php?id=5403. This might be due to a bug in the
// InventoryTransferModule or we may be required to substitute a DBNull here.
if (fi.GetValue(row) == null)
throw new NullReferenceException(
string.Format(
"[MSSQL GENERIC TABLE HANDLER]: Trying to store field {0} for {1} which is unexpectedly null",
fi.Name, row));
if (constraintFields.Count > 0 && constraintFields.Contains(fi.Name))
{
constraints.Add(new KeyValuePair<string, string>(fi.Name, fi.GetValue(row).ToString()));
}
cmd.Parameters.Add(m_database.CreateParameter(fi.Name, fi.GetValue(row).ToString()));
}
if (m_DataField != null)
{
Dictionary<string, string> data =
(Dictionary<string, string>)m_DataField.GetValue(row);
foreach (KeyValuePair<string, string> kvp in data)
{
if (constraintFields.Count > 0 && constraintFields.Contains(kvp.Key))
{
constraints.Add(new KeyValuePair<string, string>(kvp.Key, kvp.Key));
}
names.Add(kvp.Key);
values.Add("@" + kvp.Key);
cmd.Parameters.Add(m_database.CreateParameter("@" + kvp.Key, kvp.Value));
}
}
query.AppendFormat("UPDATE {0} SET ", m_Realm);
int i = 0;
for (i = 0; i < names.Count - 1; i++)
{
query.AppendFormat("[{0}] = {1}, ", names[i], values[i]);
}
query.AppendFormat("[{0}] = {1} ", names[i], values[i]);
if (constraints.Count > 0)
{
List<string> terms = new List<string>();
for (int j = 0; j < constraints.Count; j++)
{
terms.Add(" [" + constraints[j].Key + "] = @" + constraints[j].Key);
}
string where = String.Join(" AND ", terms.ToArray());
query.AppendFormat(" WHERE {0} ", where);
}
cmd.Connection = conn;
cmd.CommandText = query.ToString();
conn.Open();
if (cmd.ExecuteNonQuery() > 0)
{
//m_log.WarnFormat("[MSSQLGenericTable]: Updating {0}", m_Realm);
return true;
}
else
{
// assume record has not yet been inserted
query = new StringBuilder();
query.AppendFormat("INSERT INTO {0} ([", m_Realm);
query.Append(String.Join("],[", names.ToArray()));
query.Append("]) values (" + String.Join(",", values.ToArray()) + ")");
cmd.Connection = conn;
cmd.CommandText = query.ToString();
//m_log.WarnFormat("[MSSQLGenericTable]: Inserting into {0}", m_Realm);
if (conn.State != ConnectionState.Open)
conn.Open();
if (cmd.ExecuteNonQuery() > 0)
return true;
}
return false;
}
}
public virtual bool Delete(string field, string key)
{
return Delete(new string[] { field }, new string[] { key });
}
public virtual bool Delete(string[] fields, string[] keys)
{
if (fields.Length != keys.Length)
return false;
List<string> terms = new List<string>();
using (SqlConnection conn = new SqlConnection(m_ConnectionString))
using (SqlCommand cmd = new SqlCommand())
{
for (int i = 0; i < fields.Length; i++)
{
cmd.Parameters.Add(m_database.CreateParameter(fields[i], keys[i]));
terms.Add("[" + fields[i] + "] = @" + fields[i]);
}
string where = String.Join(" AND ", terms.ToArray());
string query = String.Format("DELETE FROM {0} WHERE {1}", m_Realm, where);
cmd.Connection = conn;
cmd.CommandText = query;
conn.Open();
if (cmd.ExecuteNonQuery() > 0)
{
//m_log.Warn("[MSSQLGenericTable]: " + deleteCommand);
return true;
}
return false;
}
}
}
}

View File

@ -1,4 +1,4 @@
/*
/*
* Copyright (c) Contributors, http://opensimulator.org/
* See CONTRIBUTORS.TXT for a full list of copyright holders.
*
@ -26,29 +26,33 @@
*/
using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Reflection;
using System.Threading;
using log4net;
using OpenMetaverse;
using OpenSim.Framework;
#if CSharpSqlite
using Community.CsharpSqlite.Sqlite;
#else
using Mono.Data.Sqlite;
#endif
using System.Data.SqlClient;
namespace OpenSim.Data.SQLite
namespace OpenSim.Data.MSSQL
{
public class SQLiteAgentPreferencesData : SQLiteGenericTableHandler<AgentPreferencesData>, IAgentPreferencesData
/// <summary>
/// A MSSQL Interface for Avatar Storage
/// </summary>
public class MSSQLGridUserData : MSSQLGenericTableHandler<GridUserData>,
IGridUserData
{
public SQLiteAgentPreferencesData(string connectionString, string realm)
: base(connectionString, realm, "AgentPrefs")
// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
public MSSQLGridUserData(string connectionString, string realm) :
base(connectionString, realm, "GridUserStore")
{
}
public AgentPreferencesData GetPrefs(UUID agentID)
public new GridUserData Get(string userID)
{
AgentPreferencesData[] ret = Get("PrincipalID", agentID.ToString());
GridUserData[] ret = Get("UserID", userID);
if (ret.Length == 0)
return null;
@ -56,5 +60,10 @@ namespace OpenSim.Data.SQLite
return ret[0];
}
public GridUserData[] GetAll(string userID)
{
return base.Get(String.Format("UserID LIKE '{0}%'", userID));
}
}
}

View File

@ -0,0 +1,831 @@
/*
* Copyright (c) Contributors, http://opensimulator.org/
* See CONTRIBUTORS.TXT for a full list of copyright holders.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the OpenSimulator Project nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.Reflection;
using log4net;
using OpenMetaverse;
using OpenSim.Framework;
namespace OpenSim.Data.MSSQL
{
/// <summary>
/// A MSSQL interface for the inventory server
/// </summary>
public class MSSQLInventoryData : IInventoryDataPlugin
{
private const string _migrationStore = "InventoryStore";
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
/// <summary>
/// The database manager
/// </summary>
private MSSQLManager database;
private string m_connectionString;
#region IPlugin members
[Obsolete("Cannot be default-initialized!")]
public void Initialise()
{
m_log.Info("[MSSQLInventoryData]: " + Name + " cannot be default-initialized!");
throw new PluginNotInitialisedException(Name);
}
/// <summary>
/// Loads and initialises the MSSQL inventory storage interface
/// </summary>
/// <param name="connectionString">connect string</param>
/// <remarks>use mssql_connection.ini</remarks>
public void Initialise(string connectionString)
{
m_connectionString = connectionString;
database = new MSSQLManager(connectionString);
//New migrations check of store
database.CheckMigration(_migrationStore);
}
/// <summary>
/// The name of this DB provider
/// </summary>
/// <returns>A string containing the name of the DB provider</returns>
public string Name
{
get { return "MSSQL Inventory Data Interface"; }
}
/// <summary>
/// Closes this DB provider
/// </summary>
public void Dispose()
{
database = null;
}
/// <summary>
/// Returns the version of this DB provider
/// </summary>
/// <returns>A string containing the DB provider</returns>
public string Version
{
get { return database.getVersion(); }
}
#endregion
#region Folder methods
/// <summary>
/// Returns a list of the root folders within a users inventory
/// </summary>
/// <param name="user">The user whos inventory is to be searched</param>
/// <returns>A list of folder objects</returns>
public List<InventoryFolderBase> getUserRootFolders(UUID user)
{
if (user == UUID.Zero)
return new List<InventoryFolderBase>();
return getInventoryFolders(UUID.Zero, user);
}
/// <summary>
/// see InventoryItemBase.getUserRootFolder
/// </summary>
/// <param name="user">the User UUID</param>
/// <returns></returns>
public InventoryFolderBase getUserRootFolder(UUID user)
{
List<InventoryFolderBase> items = getUserRootFolders(user);
InventoryFolderBase rootFolder = null;
// There should only ever be one root folder for a user. However, if there's more
// than one we'll simply use the first one rather than failing. It would be even
// nicer to print some message to this effect, but this feels like it's too low a
// to put such a message out, and it's too minor right now to spare the time to
// suitably refactor.
if (items.Count > 0)
{
rootFolder = items[0];
}
return rootFolder;
}
/// <summary>
/// Returns a list of folders in a users inventory contained within the specified folder
/// </summary>
/// <param name="parentID">The folder to search</param>
/// <returns>A list of inventory folders</returns>
public List<InventoryFolderBase> getInventoryFolders(UUID parentID)
{
return getInventoryFolders(parentID, UUID.Zero);
}
/// <summary>
/// Returns a specified inventory folder
/// </summary>
/// <param name="folderID">The folder to return</param>
/// <returns>A folder class</returns>
public InventoryFolderBase getInventoryFolder(UUID folderID)
{
string sql = "SELECT * FROM inventoryfolders WHERE folderID = @folderID";
using (SqlConnection conn = new SqlConnection(m_connectionString))
using (SqlCommand cmd = new SqlCommand(sql, conn))
{
cmd.Parameters.Add(database.CreateParameter("folderID", folderID));
conn.Open();
using (SqlDataReader reader = cmd.ExecuteReader())
{
if (reader.Read())
{
return readInventoryFolder(reader);
}
}
}
m_log.InfoFormat("[INVENTORY DB] : Found no inventory folder with ID : {0}", folderID);
return null;
}
/// <summary>
/// Returns all child folders in the hierarchy from the parent folder and down.
/// Does not return the parent folder itself.
/// </summary>
/// <param name="parentID">The folder to get subfolders for</param>
/// <returns>A list of inventory folders</returns>
public List<InventoryFolderBase> getFolderHierarchy(UUID parentID)
{
//Note maybe change this to use a Dataset that loading in all folders of a user and then go throw it that way.
//Note this is changed so it opens only one connection to the database and not everytime it wants to get data.
/* NOTE: the implementation below is very inefficient (makes a separate request to get subfolders for
* every found folder, recursively). Inventory code for other DBs has been already rewritten to get ALL
* inventory for a specific user at once.
*
* Meanwhile, one little thing is corrected: getFolderHierarchy(UUID.Zero) doesn't make sense and should never
* be used, so check for that and return an empty list.
*/
List<InventoryFolderBase> folders = new List<InventoryFolderBase>();
if (parentID == UUID.Zero)
return folders;
string sql = "SELECT * FROM inventoryfolders WHERE parentFolderID = @parentID";
using (SqlConnection conn = new SqlConnection(m_connectionString))
using (SqlCommand cmd = new SqlCommand(sql, conn))
{
cmd.Parameters.Add(database.CreateParameter("@parentID", parentID));
conn.Open();
folders.AddRange(getInventoryFolders(cmd));
List<InventoryFolderBase> tempFolders = new List<InventoryFolderBase>();
foreach (InventoryFolderBase folderBase in folders)
{
tempFolders.AddRange(getFolderHierarchy(folderBase.ID, cmd));
}
if (tempFolders.Count > 0)
{
folders.AddRange(tempFolders);
}
}
return folders;
}
/// <summary>
/// Creates a new inventory folder
/// </summary>
/// <param name="folder">Folder to create</param>
public void addInventoryFolder(InventoryFolderBase folder)
{
string sql = @"INSERT INTO inventoryfolders ([folderID], [agentID], [parentFolderID], [folderName], [type], [version])
VALUES (@folderID, @agentID, @parentFolderID, @folderName, @type, @version);";
string folderName = folder.Name;
if (folderName.Length > 64)
{
folderName = folderName.Substring(0, 64);
m_log.Warn("[INVENTORY DB]: Name field truncated from " + folder.Name.Length.ToString() + " to " + folderName.Length + " characters on add");
}
using (SqlConnection conn = new SqlConnection(m_connectionString))
using (SqlCommand cmd = new SqlCommand(sql, conn))
{
cmd.Parameters.Add(database.CreateParameter("folderID", folder.ID));
cmd.Parameters.Add(database.CreateParameter("agentID", folder.Owner));
cmd.Parameters.Add(database.CreateParameter("parentFolderID", folder.ParentID));
cmd.Parameters.Add(database.CreateParameter("folderName", folderName));
cmd.Parameters.Add(database.CreateParameter("type", folder.Type));
cmd.Parameters.Add(database.CreateParameter("version", folder.Version));
conn.Open();
try
{
cmd.ExecuteNonQuery();
}
catch (Exception e)
{
m_log.ErrorFormat("[INVENTORY DB]: Error : {0}", e.Message);
}
}
}
/// <summary>
/// Updates an inventory folder
/// </summary>
/// <param name="folder">Folder to update</param>
public void updateInventoryFolder(InventoryFolderBase folder)
{
string sql = @"UPDATE inventoryfolders SET agentID = @agentID,
parentFolderID = @parentFolderID,
folderName = @folderName,
type = @type,
version = @version
WHERE folderID = @folderID";
string folderName = folder.Name;
if (folderName.Length > 64)
{
folderName = folderName.Substring(0, 64);
m_log.Warn("[INVENTORY DB]: Name field truncated from " + folder.Name.Length.ToString() + " to " + folderName.Length + " characters on update");
}
using (SqlConnection conn = new SqlConnection(m_connectionString))
using (SqlCommand cmd = new SqlCommand(sql, conn))
{
cmd.Parameters.Add(database.CreateParameter("folderID", folder.ID));
cmd.Parameters.Add(database.CreateParameter("agentID", folder.Owner));
cmd.Parameters.Add(database.CreateParameter("parentFolderID", folder.ParentID));
cmd.Parameters.Add(database.CreateParameter("folderName", folderName));
cmd.Parameters.Add(database.CreateParameter("type", folder.Type));
cmd.Parameters.Add(database.CreateParameter("version", folder.Version));
conn.Open();
try
{
cmd.ExecuteNonQuery();
}
catch (Exception e)
{
m_log.ErrorFormat("[INVENTORY DB]: Error : {0}", e.Message);
}
}
}
/// <summary>
/// Updates an inventory folder
/// </summary>
/// <param name="folder">Folder to update</param>
public void moveInventoryFolder(InventoryFolderBase folder)
{
string sql = @"UPDATE inventoryfolders SET parentFolderID = @parentFolderID WHERE folderID = @folderID";
using (SqlConnection conn = new SqlConnection(m_connectionString))
using (SqlCommand cmd = new SqlCommand(sql, conn))
{
cmd.Parameters.Add(database.CreateParameter("parentFolderID", folder.ParentID));
cmd.Parameters.Add(database.CreateParameter("folderID", folder.ID));
conn.Open();
try
{
cmd.ExecuteNonQuery();
}
catch (Exception e)
{
m_log.ErrorFormat("[INVENTORY DB]: Error : {0}", e.Message);
}
}
}
/// <summary>
/// Delete an inventory folder
/// </summary>
/// <param name="folderID">Id of folder to delete</param>
public void deleteInventoryFolder(UUID folderID)
{
string sql = "SELECT * FROM inventoryfolders WHERE parentFolderID = @parentID";
using (SqlConnection conn = new SqlConnection(m_connectionString))
using (SqlCommand cmd = new SqlCommand(sql, conn))
{
List<InventoryFolderBase> subFolders;
cmd.Parameters.Add(database.CreateParameter("@parentID", UUID.Zero));
conn.Open();
subFolders = getFolderHierarchy(folderID, cmd);
//Delete all sub-folders
foreach (InventoryFolderBase f in subFolders)
{
DeleteOneFolder(f.ID, conn);
DeleteItemsInFolder(f.ID, conn);
}
//Delete the actual row
DeleteOneFolder(folderID, conn);
DeleteItemsInFolder(folderID, conn);
}
}
#endregion
#region Item Methods
/// <summary>
/// Returns a list of items in a specified folder
/// </summary>
/// <param name="folderID">The folder to search</param>
/// <returns>A list containing inventory items</returns>
public List<InventoryItemBase> getInventoryInFolder(UUID folderID)
{
string sql = "SELECT * FROM inventoryitems WHERE parentFolderID = @parentFolderID";
using (SqlConnection conn = new SqlConnection(m_connectionString))
using (SqlCommand cmd = new SqlCommand(sql, conn))
{
cmd.Parameters.Add(database.CreateParameter("parentFolderID", folderID));
conn.Open();
List<InventoryItemBase> items = new List<InventoryItemBase>();
using (SqlDataReader reader = cmd.ExecuteReader())
{
while (reader.Read())
{
items.Add(readInventoryItem(reader));
}
}
return items;
}
}
/// <summary>
/// Returns a specified inventory item
/// </summary>
/// <param name="itemID">The item ID</param>
/// <returns>An inventory item</returns>
public InventoryItemBase getInventoryItem(UUID itemID)
{
string sql = "SELECT * FROM inventoryitems WHERE inventoryID = @inventoryID";
using (SqlConnection conn = new SqlConnection(m_connectionString))
using (SqlCommand cmd = new SqlCommand(sql, conn))
{
cmd.Parameters.Add(database.CreateParameter("inventoryID", itemID));
conn.Open();
using (SqlDataReader reader = cmd.ExecuteReader())
{
if (reader.Read())
{
return readInventoryItem(reader);
}
}
}
m_log.InfoFormat("[INVENTORY DB]: Found no inventory item with ID : {0}", itemID);
return null;
}
/// <summary>
/// Adds a specified item to the database
/// </summary>
/// <param name="item">The inventory item</param>
public void addInventoryItem(InventoryItemBase item)
{
if (getInventoryItem(item.ID) != null)
{
updateInventoryItem(item);
return;
}
string sql = @"INSERT INTO inventoryitems
([inventoryID], [assetID], [assetType], [parentFolderID], [avatarID], [inventoryName],
[inventoryDescription], [inventoryNextPermissions], [inventoryCurrentPermissions],
[invType], [creatorID], [inventoryBasePermissions], [inventoryEveryOnePermissions], [inventoryGroupPermissions],
[salePrice], [saleType], [creationDate], [groupID], [groupOwned], [flags])
VALUES
(@inventoryID, @assetID, @assetType, @parentFolderID, @avatarID, @inventoryName, @inventoryDescription,
@inventoryNextPermissions, @inventoryCurrentPermissions, @invType, @creatorID,
@inventoryBasePermissions, @inventoryEveryOnePermissions, @inventoryGroupPermissions, @salePrice, @saleType,
@creationDate, @groupID, @groupOwned, @flags)";
string itemName = item.Name;
if (item.Name.Length > 64)
{
itemName = item.Name.Substring(0, 64);
m_log.Warn("[INVENTORY DB]: Name field truncated from " + item.Name.Length.ToString() + " to " + itemName.Length.ToString() + " characters");
}
string itemDesc = item.Description;
if (item.Description.Length > 128)
{
itemDesc = item.Description.Substring(0, 128);
m_log.Warn("[INVENTORY DB]: Description field truncated from " + item.Description.Length.ToString() + " to " + itemDesc.Length.ToString() + " characters");
}
using (SqlConnection conn = new SqlConnection(m_connectionString))
using (SqlCommand command = new SqlCommand(sql, conn))
{
command.Parameters.Add(database.CreateParameter("inventoryID", item.ID));
command.Parameters.Add(database.CreateParameter("assetID", item.AssetID));
command.Parameters.Add(database.CreateParameter("assetType", item.AssetType));
command.Parameters.Add(database.CreateParameter("parentFolderID", item.Folder));
command.Parameters.Add(database.CreateParameter("avatarID", item.Owner));
command.Parameters.Add(database.CreateParameter("inventoryName", itemName));
command.Parameters.Add(database.CreateParameter("inventoryDescription", itemDesc));
command.Parameters.Add(database.CreateParameter("inventoryNextPermissions", item.NextPermissions));
command.Parameters.Add(database.CreateParameter("inventoryCurrentPermissions", item.CurrentPermissions));
command.Parameters.Add(database.CreateParameter("invType", item.InvType));
command.Parameters.Add(database.CreateParameter("creatorID", item.CreatorId));
command.Parameters.Add(database.CreateParameter("inventoryBasePermissions", item.BasePermissions));
command.Parameters.Add(database.CreateParameter("inventoryEveryOnePermissions", item.EveryOnePermissions));
command.Parameters.Add(database.CreateParameter("inventoryGroupPermissions", item.GroupPermissions));
command.Parameters.Add(database.CreateParameter("salePrice", item.SalePrice));
command.Parameters.Add(database.CreateParameter("saleType", item.SaleType));
command.Parameters.Add(database.CreateParameter("creationDate", item.CreationDate));
command.Parameters.Add(database.CreateParameter("groupID", item.GroupID));
command.Parameters.Add(database.CreateParameter("groupOwned", item.GroupOwned));
command.Parameters.Add(database.CreateParameter("flags", item.Flags));
conn.Open();
try
{
command.ExecuteNonQuery();
}
catch (Exception e)
{
m_log.Error("[INVENTORY DB]: Error inserting item :" + e.Message);
}
}
sql = "UPDATE inventoryfolders SET version = version + 1 WHERE folderID = @folderID";
using (SqlConnection conn = new SqlConnection(m_connectionString))
using (SqlCommand command = new SqlCommand(sql, conn))
{
command.Parameters.Add(database.CreateParameter("folderID", item.Folder.ToString()));
conn.Open();
try
{
command.ExecuteNonQuery();
}
catch (Exception e)
{
m_log.Error("[INVENTORY DB] Error updating inventory folder for new item :" + e.Message);
}
}
}
/// <summary>
/// Updates the specified inventory item
/// </summary>
/// <param name="item">Inventory item to update</param>
public void updateInventoryItem(InventoryItemBase item)
{
string sql = @"UPDATE inventoryitems SET assetID = @assetID,
assetType = @assetType,
parentFolderID = @parentFolderID,
avatarID = @avatarID,
inventoryName = @inventoryName,
inventoryDescription = @inventoryDescription,
inventoryNextPermissions = @inventoryNextPermissions,
inventoryCurrentPermissions = @inventoryCurrentPermissions,
invType = @invType,
creatorID = @creatorID,
inventoryBasePermissions = @inventoryBasePermissions,
inventoryEveryOnePermissions = @inventoryEveryOnePermissions,
inventoryGroupPermissions = @inventoryGroupPermissions,
salePrice = @salePrice,
saleType = @saleType,
creationDate = @creationDate,
groupID = @groupID,
groupOwned = @groupOwned,
flags = @flags
WHERE inventoryID = @inventoryID";
string itemName = item.Name;
if (item.Name.Length > 64)
{
itemName = item.Name.Substring(0, 64);
m_log.Warn("[INVENTORY DB]: Name field truncated from " + item.Name.Length.ToString() + " to " + itemName.Length.ToString() + " characters on update");
}
string itemDesc = item.Description;
if (item.Description.Length > 128)
{
itemDesc = item.Description.Substring(0, 128);
m_log.Warn("[INVENTORY DB]: Description field truncated from " + item.Description.Length.ToString() + " to " + itemDesc.Length.ToString() + " characters on update");
}
using (SqlConnection conn = new SqlConnection(m_connectionString))
using (SqlCommand command = new SqlCommand(sql, conn))
{
command.Parameters.Add(database.CreateParameter("inventoryID", item.ID));
command.Parameters.Add(database.CreateParameter("assetID", item.AssetID));
command.Parameters.Add(database.CreateParameter("assetType", item.AssetType));
command.Parameters.Add(database.CreateParameter("parentFolderID", item.Folder));
command.Parameters.Add(database.CreateParameter("avatarID", item.Owner));
command.Parameters.Add(database.CreateParameter("inventoryName", itemName));
command.Parameters.Add(database.CreateParameter("inventoryDescription", itemDesc));
command.Parameters.Add(database.CreateParameter("inventoryNextPermissions", item.NextPermissions));
command.Parameters.Add(database.CreateParameter("inventoryCurrentPermissions", item.CurrentPermissions));
command.Parameters.Add(database.CreateParameter("invType", item.InvType));
command.Parameters.Add(database.CreateParameter("creatorID", item.CreatorId));
command.Parameters.Add(database.CreateParameter("inventoryBasePermissions", item.BasePermissions));
command.Parameters.Add(database.CreateParameter("inventoryEveryOnePermissions", item.EveryOnePermissions));
command.Parameters.Add(database.CreateParameter("inventoryGroupPermissions", item.GroupPermissions));
command.Parameters.Add(database.CreateParameter("salePrice", item.SalePrice));
command.Parameters.Add(database.CreateParameter("saleType", item.SaleType));
command.Parameters.Add(database.CreateParameter("creationDate", item.CreationDate));
command.Parameters.Add(database.CreateParameter("groupID", item.GroupID));
command.Parameters.Add(database.CreateParameter("groupOwned", item.GroupOwned));
command.Parameters.Add(database.CreateParameter("flags", item.Flags));
conn.Open();
try
{
command.ExecuteNonQuery();
}
catch (Exception e)
{
m_log.Error("[INVENTORY DB]: Error updating item :" + e.Message);
}
}
}
// See IInventoryDataPlugin
/// <summary>
/// Delete an item in inventory database
/// </summary>
/// <param name="itemID">the item UUID</param>
public void deleteInventoryItem(UUID itemID)
{
string sql = "DELETE FROM inventoryitems WHERE inventoryID=@inventoryID";
using (SqlConnection conn = new SqlConnection(m_connectionString))
using (SqlCommand cmd = new SqlCommand(sql, conn))
{
cmd.Parameters.Add(database.CreateParameter("inventoryID", itemID));
try
{
conn.Open();
cmd.ExecuteNonQuery();
}
catch (Exception e)
{
m_log.Error("[INVENTORY DB]: Error deleting item :" + e.Message);
}
}
}
public InventoryItemBase queryInventoryItem(UUID itemID)
{
return getInventoryItem(itemID);
}
public InventoryFolderBase queryInventoryFolder(UUID folderID)
{
return getInventoryFolder(folderID);
}
/// <summary>
/// Returns all activated gesture-items in the inventory of the specified avatar.
/// </summary>
/// <param name="avatarID">The <see cref="UUID"/> of the avatar</param>
/// <returns>
/// The list of gestures (<see cref="InventoryItemBase"/>s)
/// </returns>
public List<InventoryItemBase> fetchActiveGestures(UUID avatarID)
{
string sql = "SELECT * FROM inventoryitems WHERE avatarId = @uuid AND assetType = @assetType and flags = 1";
using (SqlConnection conn = new SqlConnection(m_connectionString))
using (SqlCommand cmd = new SqlCommand(sql, conn))
{
cmd.Parameters.Add(database.CreateParameter("uuid", avatarID));
cmd.Parameters.Add(database.CreateParameter("assetType", (int)AssetType.Gesture));
conn.Open();
using (SqlDataReader reader = cmd.ExecuteReader())
{
List<InventoryItemBase> gestureList = new List<InventoryItemBase>();
while (reader.Read())
{
gestureList.Add(readInventoryItem(reader));
}
return gestureList;
}
}
}
#endregion
#region Private methods
/// <summary>
/// Delete an item in inventory database
/// </summary>
/// <param name="folderID">the item ID</param>
/// <param name="connection">connection to the database</param>
private void DeleteItemsInFolder(UUID folderID, SqlConnection connection)
{
using (SqlCommand command = new SqlCommand("DELETE FROM inventoryitems WHERE folderID=@folderID", connection))
{
command.Parameters.Add(database.CreateParameter("folderID", folderID));
try
{
command.ExecuteNonQuery();
}
catch (Exception e)
{
m_log.Error("[INVENTORY DB] Error deleting item :" + e.Message);
}
}
}
/// <summary>
/// Gets the folder hierarchy in a loop.
/// </summary>
/// <param name="parentID">parent ID.</param>
/// <param name="command">SQL command/connection to database</param>
/// <returns></returns>
private static List<InventoryFolderBase> getFolderHierarchy(UUID parentID, SqlCommand command)
{
command.Parameters["@parentID"].Value = parentID.Guid; //.ToString();
List<InventoryFolderBase> folders = getInventoryFolders(command);
if (folders.Count > 0)
{
List<InventoryFolderBase> tempFolders = new List<InventoryFolderBase>();
foreach (InventoryFolderBase folderBase in folders)
{
tempFolders.AddRange(getFolderHierarchy(folderBase.ID, command));
}
if (tempFolders.Count > 0)
{
folders.AddRange(tempFolders);
}
}
return folders;
}
/// <summary>
/// Gets the inventory folders.
/// </summary>
/// <param name="parentID">parentID, use UUID.Zero to get root</param>
/// <param name="user">user id, use UUID.Zero, if you want all folders from a parentID.</param>
/// <returns></returns>
private List<InventoryFolderBase> getInventoryFolders(UUID parentID, UUID user)
{
string sql = "SELECT * FROM inventoryfolders WHERE parentFolderID = @parentID AND agentID LIKE @uuid";
using (SqlConnection conn = new SqlConnection(m_connectionString))
using (SqlCommand command = new SqlCommand(sql, conn))
{
if (user == UUID.Zero)
{
command.Parameters.Add(database.CreateParameter("uuid", "%"));
}
else
{
command.Parameters.Add(database.CreateParameter("uuid", user));
}
command.Parameters.Add(database.CreateParameter("parentID", parentID));
conn.Open();
return getInventoryFolders(command);
}
}
/// <summary>
/// Gets the inventory folders.
/// </summary>
/// <param name="command">SQLcommand.</param>
/// <returns></returns>
private static List<InventoryFolderBase> getInventoryFolders(SqlCommand command)
{
using (SqlDataReader reader = command.ExecuteReader())
{
List<InventoryFolderBase> items = new List<InventoryFolderBase>();
while (reader.Read())
{
items.Add(readInventoryFolder(reader));
}
return items;
}
}
/// <summary>
/// Reads a list of inventory folders returned by a query.
/// </summary>
/// <param name="reader">A MSSQL Data Reader</param>
/// <returns>A List containing inventory folders</returns>
protected static InventoryFolderBase readInventoryFolder(SqlDataReader reader)
{
try
{
InventoryFolderBase folder = new InventoryFolderBase();
folder.Owner = DBGuid.FromDB(reader["agentID"]);
folder.ParentID = DBGuid.FromDB(reader["parentFolderID"]);
folder.ID = DBGuid.FromDB(reader["folderID"]);
folder.Name = (string)reader["folderName"];
folder.Type = (short)reader["type"];
folder.Version = Convert.ToUInt16(reader["version"]);
return folder;
}
catch (Exception e)
{
m_log.Error("[INVENTORY DB] Error reading inventory folder :" + e.Message);
}
return null;
}
/// <summary>
/// Reads a one item from an SQL result
/// </summary>
/// <param name="reader">The SQL Result</param>
/// <returns>the item read</returns>
private static InventoryItemBase readInventoryItem(IDataRecord reader)
{
try
{
InventoryItemBase item = new InventoryItemBase();
item.ID = DBGuid.FromDB(reader["inventoryID"]);
item.AssetID = DBGuid.FromDB(reader["assetID"]);
item.AssetType = Convert.ToInt32(reader["assetType"].ToString());
item.Folder = DBGuid.FromDB(reader["parentFolderID"]);
item.Owner = DBGuid.FromDB(reader["avatarID"]);
item.Name = reader["inventoryName"].ToString();
item.Description = reader["inventoryDescription"].ToString();
item.NextPermissions = Convert.ToUInt32(reader["inventoryNextPermissions"]);
item.CurrentPermissions = Convert.ToUInt32(reader["inventoryCurrentPermissions"]);
item.InvType = Convert.ToInt32(reader["invType"].ToString());
item.CreatorId = reader["creatorID"].ToString();
item.BasePermissions = Convert.ToUInt32(reader["inventoryBasePermissions"]);
item.EveryOnePermissions = Convert.ToUInt32(reader["inventoryEveryOnePermissions"]);
item.GroupPermissions = Convert.ToUInt32(reader["inventoryGroupPermissions"]);
item.SalePrice = Convert.ToInt32(reader["salePrice"]);
item.SaleType = Convert.ToByte(reader["saleType"]);
item.CreationDate = Convert.ToInt32(reader["creationDate"]);
item.GroupID = DBGuid.FromDB(reader["groupID"]);
item.GroupOwned = Convert.ToBoolean(reader["groupOwned"]);
item.Flags = Convert.ToUInt32(reader["flags"]);
return item;
}
catch (SqlException e)
{
m_log.Error("[INVENTORY DB]: Error reading inventory item :" + e.Message);
}
return null;
}
/// <summary>
/// Delete a folder in inventory databasae
/// </summary>
/// <param name="folderID">the folder UUID</param>
/// <param name="connection">connection to database</param>
private void DeleteOneFolder(UUID folderID, SqlConnection connection)
{
try
{
using (SqlCommand command = new SqlCommand("DELETE FROM inventoryfolders WHERE folderID=@folderID and type=-1", connection))
{
command.Parameters.Add(database.CreateParameter("folderID", folderID));
command.ExecuteNonQuery();
}
}
catch (SqlException e)
{
m_log.Error("[INVENTORY DB]: Error deleting folder :" + e.Message);
}
}
#endregion
}
}

View File

@ -0,0 +1,219 @@
/*
* Copyright (c) Contributors, http://opensimulator.org/
* See CONTRIBUTORS.TXT for a full list of copyright holders.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the OpenSimulator Project nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.IO;
using System.Reflection;
using log4net;
using OpenMetaverse;
namespace OpenSim.Data.MSSQL
{
/// <summary>
/// A management class for the MS SQL Storage Engine
/// </summary>
public class MSSQLManager
{
// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
/// <summary>
/// Connection string for ADO.net
/// </summary>
private readonly string connectionString;
/// <summary>
/// Initialize the manager and set the connectionstring
/// </summary>
/// <param name="connection"></param>
public MSSQLManager(string connection)
{
connectionString = connection;
}
/// <summary>
/// Type conversion to a SQLDbType functions
/// </summary>
/// <param name="type"></param>
/// <returns></returns>
internal SqlDbType DbtypeFromType(Type type)
{
if (type == typeof(string))
{
return SqlDbType.VarChar;
}
if (type == typeof(double))
{
return SqlDbType.Float;
}
if (type == typeof(Single))
{
return SqlDbType.Float;
}
if (type == typeof(int))
{
return SqlDbType.Int;
}
if (type == typeof(bool))
{
return SqlDbType.Bit;
}
if (type == typeof(UUID))
{
return SqlDbType.UniqueIdentifier;
}
if (type == typeof(sbyte))
{
return SqlDbType.Int;
}
if (type == typeof(Byte[]))
{
return SqlDbType.Image;
}
if (type == typeof(uint) || type == typeof(ushort))
{
return SqlDbType.Int;
}
if (type == typeof(ulong))
{
return SqlDbType.BigInt;
}
if (type == typeof(DateTime))
{
return SqlDbType.DateTime;
}
return SqlDbType.VarChar;
}
/// <summary>
/// Creates value for parameter.
/// </summary>
/// <param name="value">The value.</param>
/// <returns></returns>
private static object CreateParameterValue(object value)
{
Type valueType = value.GetType();
if (valueType == typeof(UUID)) //TODO check if this works
{
return ((UUID) value).Guid;
}
if (valueType == typeof(UUID))
{
return ((UUID)value).Guid;
}
if (valueType == typeof(bool))
{
return (bool)value ? 1 : 0;
}
if (valueType == typeof(Byte[]))
{
return value;
}
if (valueType == typeof(int))
{
return value;
}
return value;
}
/// <summary>
/// Create a parameter for a command
/// </summary>
/// <param name="parameterName">Name of the parameter.</param>
/// <param name="parameterObject">parameter object.</param>
/// <returns></returns>
internal SqlParameter CreateParameter(string parameterName, object parameterObject)
{
return CreateParameter(parameterName, parameterObject, false);
}
/// <summary>
/// Creates the parameter for a command.
/// </summary>
/// <param name="parameterName">Name of the parameter.</param>
/// <param name="parameterObject">parameter object.</param>
/// <param name="parameterOut">if set to <c>true</c> parameter is a output parameter</param>
/// <returns></returns>
internal SqlParameter CreateParameter(string parameterName, object parameterObject, bool parameterOut)
{
//Tweak so we dont always have to add @ sign
if (!parameterName.StartsWith("@")) parameterName = "@" + parameterName;
//HACK if object is null, it is turned into a string, there are no nullable type till now
if (parameterObject == null) parameterObject = "";
SqlParameter parameter = new SqlParameter(parameterName, DbtypeFromType(parameterObject.GetType()));
if (parameterOut)
{
parameter.Direction = ParameterDirection.Output;
}
else
{
parameter.Direction = ParameterDirection.Input;
parameter.Value = CreateParameterValue(parameterObject);
}
return parameter;
}
/// <summary>
/// Checks if we need to do some migrations to the database
/// </summary>
/// <param name="migrationStore">migrationStore.</param>
public void CheckMigration(string migrationStore)
{
using (SqlConnection connection = new SqlConnection(connectionString))
{
connection.Open();
Assembly assem = GetType().Assembly;
MSSQLMigration migration = new MSSQLMigration(connection, assem, migrationStore);
migration.Update();
}
}
/// <summary>
/// Returns the version of this DB provider
/// </summary>
/// <returns>A string containing the DB provider</returns>
public string getVersion()
{
Module module = GetType().Module;
// string dllName = module.Assembly.ManifestModule.Name;
Version dllVersion = module.Assembly.GetName().Version;
return
string.Format("{0}.{1}.{2}.{3}", dllVersion.Major, dllVersion.Minor, dllVersion.Build,
dllVersion.Revision);
}
}
}

View File

@ -24,70 +24,76 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
using System;
using System.Data;
using System.Data.Common;
using System.Reflection;
using System.Data.SqlClient;
using OpenSim.Region.CoreModules.World.Terrain;
using OpenSim.Region.Framework.Interfaces;
namespace OpenSim.Region.CoreModules.World.Terrain.Modifiers
namespace OpenSim.Data.MSSQL
{
public class FillModifier : TerrainModifier
public class MSSQLMigration : Migration
{
public FillModifier(ITerrainModule module) : base(module)
public MSSQLMigration(DbConnection conn, Assembly assem, string type)
: base(conn, assem, type)
{
}
public override string ModifyTerrain(ITerrainChannel map, string[] args)
public MSSQLMigration(DbConnection conn, Assembly assem, string subtype, string type)
: base(conn, assem, subtype, type)
{
string result;
if (args.Length < 3)
{
result = "Usage: " + GetUsage();
}
else
{
TerrainModifierData data;
result = this.parseParameters(args, out data);
}
// Context-specific validation
if (result == String.Empty)
protected override int FindVersion(DbConnection conn, string type)
{
int version = 0;
using (DbCommand cmd = conn.CreateCommand())
{
try
{
if (data.shape == String.Empty)
cmd.CommandText = "select top 1 version from migrations where name = '" + type + "' order by version desc"; //Must be
using (IDataReader reader = cmd.ExecuteReader())
{
data.shape = "rectangle";
data.x0 = 0;
data.y0 = 0;
data.dx = map.Width;
data.dy = map.Height;
if (reader.Read())
{
version = Convert.ToInt32(reader["version"]);
}
reader.Close();
}
}
// if it's all good, then do the work
if (result == String.Empty)
catch
{
this.applyModification(map, data);
// Return -1 to indicate table does not exist
return -1;
}
}
return result;
return version;
}
public override string GetUsage()
protected override void ExecuteScript(DbConnection conn, string[] script)
{
string val = "fill <height> [ -rec=x1,y1,dx[,dy] | -ell=x0,y0,rx[,ry] ] [-taper=<height2>]"
+ "\nSets all points within the specified range to the specified value.";
return val;
}
if (!(conn is SqlConnection))
{
base.ExecuteScript(conn, script);
return;
}
public override float operate(float[,] map, TerrainModifierData data, int x, int y)
{
float factor = this.computeBevel(data, x, y);
float result = data.elevation - (data.elevation - data.bevelevation) * factor;
return result;
}
foreach (string sql in script)
{
try
{
using (SqlCommand cmd = new SqlCommand(sql, (SqlConnection)conn))
{
cmd.ExecuteNonQuery();
}
}
catch (Exception)
{
throw new Exception(sql);
}
}
}
}
}

View File

@ -0,0 +1,117 @@
/*
* Copyright (c) Contributors, http://opensimulator.org/
* See CONTRIBUTORS.TXT for a full list of copyright holders.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the OpenSimulator Project nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
using System;
using System.Collections.Generic;
using System.Data;
using System.Reflection;
using System.Threading;
using log4net;
using OpenMetaverse;
using OpenSim.Framework;
using System.Data.SqlClient;
namespace OpenSim.Data.MSSQL
{
/// <summary>
/// A MySQL Interface for the Presence Server
/// </summary>
public class MSSQLPresenceData : MSSQLGenericTableHandler<PresenceData>,
IPresenceData
{
// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
public MSSQLPresenceData(string connectionString, string realm) :
base(connectionString, realm, "Presence")
{
}
public PresenceData Get(UUID sessionID)
{
PresenceData[] ret = Get("SessionID",
sessionID.ToString());
if (ret.Length == 0)
return null;
return ret[0];
}
public void LogoutRegionAgents(UUID regionID)
{
using (SqlConnection conn = new SqlConnection(m_ConnectionString))
using (SqlCommand cmd = new SqlCommand())
{
cmd.CommandText = String.Format("DELETE FROM {0} WHERE [RegionID]=@RegionID", m_Realm);
cmd.Parameters.Add(m_database.CreateParameter("@RegionID", regionID.ToString()));
cmd.Connection = conn;
conn.Open();
cmd.ExecuteNonQuery();
}
}
public bool ReportAgent(UUID sessionID, UUID regionID)
{
PresenceData[] pd = Get("SessionID", sessionID.ToString());
if (pd.Length == 0)
return false;
using (SqlConnection conn = new SqlConnection(m_ConnectionString))
using (SqlCommand cmd = new SqlCommand())
{
cmd.CommandText = String.Format(@"UPDATE {0} SET
[RegionID] = @RegionID
WHERE [SessionID] = @SessionID", m_Realm);
cmd.Parameters.Add(m_database.CreateParameter("@SessionID", sessionID.ToString()));
cmd.Parameters.Add(m_database.CreateParameter("@RegionID", regionID.ToString()));
cmd.Connection = conn;
conn.Open();
if (cmd.ExecuteNonQuery() == 0)
return false;
}
return true;
}
public bool VerifyAgent(UUID agentId, UUID secureSessionID)
{
PresenceData[] ret = Get("SecureSessionID",
secureSessionID.ToString());
if (ret.Length == 0)
return false;
if(ret[0].UserID != agentId.ToString())
return false;
return true;
}
}
}

View File

@ -0,0 +1,352 @@
/*
* Copyright (c) Contributors, http://opensimulator.org/
* See CONTRIBUTORS.TXT for a full list of copyright holders.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the OpenSimulator Project nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ''AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.Drawing;
using System.IO;
using System.Reflection;
using log4net;
using OpenMetaverse;
using OpenSim.Framework;
using OpenSim.Region.Framework.Interfaces;
using OpenSim.Region.Framework.Scenes;
using RegionFlags = OpenSim.Framework.RegionFlags;
namespace OpenSim.Data.MSSQL
{
/// <summary>
/// A MSSQL Interface for the Region Server.
/// </summary>
public class MSSQLRegionData : IRegionData
{
private string m_Realm;
private List<string> m_ColumnNames = null;
private string m_ConnectionString;
private MSSQLManager m_database;
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
public MSSQLRegionData(string connectionString, string realm)
{
m_Realm = realm;
m_ConnectionString = connectionString;
m_database = new MSSQLManager(connectionString);
using (SqlConnection conn = new SqlConnection(m_ConnectionString))
{
conn.Open();
Migration m = new Migration(conn, GetType().Assembly, "GridStore");
m.Update();
}
}
public List<RegionData> Get(string regionName, UUID scopeID)
{
string sql = "select * from ["+m_Realm+"] where regionName like @regionName";
if (scopeID != UUID.Zero)
sql += " and ScopeID = @scopeID";
sql += " order by regionName";
using (SqlConnection conn = new SqlConnection(m_ConnectionString))
using (SqlCommand cmd = new SqlCommand(sql, conn))
{
cmd.Parameters.Add(m_database.CreateParameter("@regionName", regionName));
cmd.Parameters.Add(m_database.CreateParameter("@scopeID", scopeID));
conn.Open();
return RunCommand(cmd);
}
}
public RegionData Get(int posX, int posY, UUID scopeID)
{
string sql = "select * from ["+m_Realm+"] where locX = @posX and locY = @posY";
if (scopeID != UUID.Zero)
sql += " and ScopeID = @scopeID";
using (SqlConnection conn = new SqlConnection(m_ConnectionString))
using (SqlCommand cmd = new SqlCommand(sql, conn))
{
cmd.Parameters.Add(m_database.CreateParameter("@posX", posX.ToString()));
cmd.Parameters.Add(m_database.CreateParameter("@posY", posY.ToString()));
cmd.Parameters.Add(m_database.CreateParameter("@scopeID", scopeID));
conn.Open();
List<RegionData> ret = RunCommand(cmd);
if (ret.Count == 0)
return null;
return ret[0];
}
}
public RegionData Get(UUID regionID, UUID scopeID)
{
string sql = "select * from ["+m_Realm+"] where uuid = @regionID";
if (scopeID != UUID.Zero)
sql += " and ScopeID = @scopeID";
using (SqlConnection conn = new SqlConnection(m_ConnectionString))
using (SqlCommand cmd = new SqlCommand(sql, conn))
{
cmd.Parameters.Add(m_database.CreateParameter("@regionID", regionID));
cmd.Parameters.Add(m_database.CreateParameter("@scopeID", scopeID));
conn.Open();
List<RegionData> ret = RunCommand(cmd);
if (ret.Count == 0)
return null;
return ret[0];
}
}
public List<RegionData> Get(int startX, int startY, int endX, int endY, UUID scopeID)
{
string sql = "select * from ["+m_Realm+"] where locX between @startX and @endX and locY between @startY and @endY";
if (scopeID != UUID.Zero)
sql += " and ScopeID = @scopeID";
using (SqlConnection conn = new SqlConnection(m_ConnectionString))
using (SqlCommand cmd = new SqlCommand(sql, conn))
{
cmd.Parameters.Add(m_database.CreateParameter("@startX", startX));
cmd.Parameters.Add(m_database.CreateParameter("@startY", startY));
cmd.Parameters.Add(m_database.CreateParameter("@endX", endX));
cmd.Parameters.Add(m_database.CreateParameter("@endY", endY));
cmd.Parameters.Add(m_database.CreateParameter("@scopeID", scopeID));
conn.Open();
return RunCommand(cmd);
}
}
public List<RegionData> RunCommand(SqlCommand cmd)
{
List<RegionData> retList = new List<RegionData>();
SqlDataReader result = cmd.ExecuteReader();
while (result.Read())
{
RegionData ret = new RegionData();
ret.Data = new Dictionary<string, object>();
UUID regionID;
UUID.TryParse(result["uuid"].ToString(), out regionID);
ret.RegionID = regionID;
UUID scope;
UUID.TryParse(result["ScopeID"].ToString(), out scope);
ret.ScopeID = scope;
ret.RegionName = result["regionName"].ToString();
ret.posX = Convert.ToInt32(result["locX"]);
ret.posY = Convert.ToInt32(result["locY"]);
ret.sizeX = Convert.ToInt32(result["sizeX"]);
ret.sizeY = Convert.ToInt32(result["sizeY"]);
if (m_ColumnNames == null)
{
m_ColumnNames = new List<string>();
DataTable schemaTable = result.GetSchemaTable();
foreach (DataRow row in schemaTable.Rows)
m_ColumnNames.Add(row["ColumnName"].ToString());
}
foreach (string s in m_ColumnNames)
{
if (s == "uuid")
continue;
if (s == "ScopeID")
continue;
if (s == "regionName")
continue;
if (s == "locX")
continue;
if (s == "locY")
continue;
ret.Data[s] = result[s].ToString();
}
retList.Add(ret);
}
return retList;
}
public bool Store(RegionData data)
{
if (data.Data.ContainsKey("uuid"))
data.Data.Remove("uuid");
if (data.Data.ContainsKey("ScopeID"))
data.Data.Remove("ScopeID");
if (data.Data.ContainsKey("regionName"))
data.Data.Remove("regionName");
if (data.Data.ContainsKey("posX"))
data.Data.Remove("posX");
if (data.Data.ContainsKey("posY"))
data.Data.Remove("posY");
if (data.Data.ContainsKey("sizeX"))
data.Data.Remove("sizeX");
if (data.Data.ContainsKey("sizeY"))
data.Data.Remove("sizeY");
if (data.Data.ContainsKey("locX"))
data.Data.Remove("locX");
if (data.Data.ContainsKey("locY"))
data.Data.Remove("locY");
string[] fields = new List<string>(data.Data.Keys).ToArray();
using (SqlConnection conn = new SqlConnection(m_ConnectionString))
using (SqlCommand cmd = new SqlCommand())
{
string update = "update [" + m_Realm + "] set locX=@posX, locY=@posY, sizeX=@sizeX, sizeY=@sizeY ";
foreach (string field in fields)
{
update += ", ";
update += "[" + field + "] = @" + field;
cmd.Parameters.Add(m_database.CreateParameter("@" + field, data.Data[field]));
}
update += " where uuid = @regionID";
if (data.ScopeID != UUID.Zero)
update += " and ScopeID = @scopeID";
cmd.CommandText = update;
cmd.Connection = conn;
cmd.Parameters.Add(m_database.CreateParameter("@regionID", data.RegionID));
cmd.Parameters.Add(m_database.CreateParameter("@regionName", data.RegionName));
cmd.Parameters.Add(m_database.CreateParameter("@scopeID", data.ScopeID));
cmd.Parameters.Add(m_database.CreateParameter("@posX", data.posX));
cmd.Parameters.Add(m_database.CreateParameter("@posY", data.posY));
cmd.Parameters.Add(m_database.CreateParameter("@sizeX", data.sizeX));
cmd.Parameters.Add(m_database.CreateParameter("@sizeY", data.sizeY));
conn.Open();
try
{
if (cmd.ExecuteNonQuery() < 1)
{
string insert = "insert into [" + m_Realm + "] ([uuid], [ScopeID], [locX], [locY], [sizeX], [sizeY], [regionName], [" +
String.Join("], [", fields) +
"]) values (@regionID, @scopeID, @posX, @posY, @sizeX, @sizeY, @regionName, @" + String.Join(", @", fields) + ")";
cmd.CommandText = insert;
try
{
if (cmd.ExecuteNonQuery() < 1)
{
return false;
}
}
catch (Exception ex)
{
m_log.Warn("[MSSQL Grid]: Error inserting into Regions table: " + ex.Message + ", INSERT sql: " + insert);
}
}
}
catch (Exception ex)
{
m_log.Warn("[MSSQL Grid]: Error updating Regions table: " + ex.Message + ", UPDATE sql: " + update);
}
}
return true;
}
public bool SetDataItem(UUID regionID, string item, string value)
{
string sql = "update [" + m_Realm +
"] set [" + item + "] = @" + item + " where uuid = @UUID";
using (SqlConnection conn = new SqlConnection(m_ConnectionString))
using (SqlCommand cmd = new SqlCommand(sql, conn))
{
cmd.Parameters.Add(m_database.CreateParameter("@" + item, value));
cmd.Parameters.Add(m_database.CreateParameter("@UUID", regionID));
conn.Open();
if (cmd.ExecuteNonQuery() > 0)
return true;
}
return false;
}
public bool Delete(UUID regionID)
{
string sql = "delete from [" + m_Realm +
"] where uuid = @UUID";
using (SqlConnection conn = new SqlConnection(m_ConnectionString))
using (SqlCommand cmd = new SqlCommand(sql, conn))
{
cmd.Parameters.Add(m_database.CreateParameter("@UUID", regionID));
conn.Open();
if (cmd.ExecuteNonQuery() > 0)
return true;
}
return false;
}
public List<RegionData> GetDefaultRegions(UUID scopeID)
{
return Get((int)RegionFlags.DefaultRegion, scopeID);
}
public List<RegionData> GetDefaultHypergridRegions(UUID scopeID)
{
return Get((int)RegionFlags.DefaultHGRegion, scopeID);
}
public List<RegionData> GetFallbackRegions(UUID scopeID, int x, int y)
{
List<RegionData> regions = Get((int)RegionFlags.FallbackRegion, scopeID);
RegionDataDistanceCompare distanceComparer = new RegionDataDistanceCompare(x, y);
regions.Sort(distanceComparer);
return regions;
}
public List<RegionData> GetHyperlinks(UUID scopeID)
{
return Get((int)RegionFlags.Hyperlink, scopeID);
}
private List<RegionData> Get(int regionFlags, UUID scopeID)
{
string sql = "SELECT * FROM [" + m_Realm + "] WHERE (flags & " + regionFlags.ToString() + ") <> 0";
if (scopeID != UUID.Zero)
sql += " AND ScopeID = @scopeID";
using (SqlConnection conn = new SqlConnection(m_ConnectionString))
using (SqlCommand cmd = new SqlCommand(sql, conn))
{
cmd.Parameters.Add(m_database.CreateParameter("@scopeID", scopeID));
conn.Open();
return RunCommand(cmd);
}
}
}
}

Some files were not shown because too many files have changed in this diff Show More