Compare commits

..

80 Commits

Author SHA1 Message Date
Diva Canto 47ce1a47bb Deleted all [ZZZ] debug messages. 2013-07-24 14:24:17 -07:00
Diva Canto 10def95c27 The previous commit did fix the infinity problem! I'm putting the same time on TP_V1 and adding a big red warning on top of those lines. 2013-07-24 14:22:59 -07:00
Diva Canto dab01a10d9 Today's wild shot at the infinity problem. Wait on the child agent left behind. 2013-07-24 12:54:13 -07:00
Diva Canto b44d96618c Amend previous commit. 2013-07-24 11:42:35 -07:00
Diva Canto 3a6c690e69 Added config var that we all thought was already there: see_into_region. (Note: different from the defunct see_into_neighboring_sim, which used to control the process from the other end). This enables child agents in neighbors for which the root agent doesn't have permission to be in. 2013-07-24 11:23:19 -07:00
Diva Canto 051cf81c9f Decreased the time of group cache to 1 min, because it was getting on my nerves that it takes so long to let go of old info. 2013-07-24 11:13:31 -07:00
Diva Canto c7a3714c37 Don't touch the Current Outfit folder also on coming back home 2013-07-23 15:04:24 -07:00
Diva Canto 1815c2f98c Restoring landing on prims, which had been affected by the edit beams commit. 2013-07-23 14:23:22 -07:00
Diva Canto 7c884d16f4 In renaming the folders for hypergriding, don't rename the Current Outfit folder. The viewer doesn't like that. 2013-07-23 14:17:32 -07:00
Diva Canto f3d31e6e53 Improvement of fetching name in groups 2013-07-23 11:29:53 -07:00
Diva Canto 701e15760c That didn't change anything.
Revert "One more tweak to check the infinity problem"

This reverts commit 2b696bc0c8.
2013-07-23 10:10:33 -07:00
Diva Canto 2b696bc0c8 One more tweak to check the infinity problem 2013-07-23 10:04:08 -07:00
Justin Clark-Casey (justincc) 9e277b54b9 Improve spacing between data and units on console stats display 2013-07-23 17:48:35 +01:00
Justin Clark-Casey (justincc) 805ac6435e For stats which can show average change over time, show the last sample as well as the average.
This is somewhat cryptic at the moment, need to improve documentation.
2013-07-23 17:48:10 +01:00
Justin Clark-Casey (justincc) 511801c607 Add proper method doc and comments to m_dataPresentEvent (from d9d9959) 2013-07-23 17:48:05 +01:00
Diva Canto ff294dce6c Moved TriggerOnMakeRootAgent back to the end of MakeRootAgent, to see if that eliminates the temporary placement at infinity upon TPs 2013-07-22 22:00:20 -07:00
Diva Canto 9c1ec98415 When LLSD handlers are not found, the server should return a 404 instead of a valid response saying 'No handler registered for LLSD Requests' 2013-07-22 21:45:57 -07:00
Diva Canto 01561166aa One more thing to test in order to let CompleteMovement go up the stack. 2013-07-22 20:49:40 -07:00
Diva Canto 8d1108e542 Minor adjustment on timings of waits. 2013-07-22 20:20:48 -07:00
Diva Canto be4034fd1c Merge branch 'cpu-performance' of ssh://opensimulator.org/var/git/opensim into cpu-performance 2013-07-22 18:47:10 -07:00
Diva Canto 87a19d4cab Changed the RegionHandshake packet to the Unknown queue, so that it is sent with high priority and hopefully gets to the client before AgentMovementComplete 2013-07-22 18:46:51 -07:00
Justin Clark-Casey (justincc) 35e46c2836 Add clientstack.InboxPacketsCount stat. This records the number of packets waiting to be processed at the second stage (after initial UDP processing)
If this consistently increases then this is a problem since it means the simulator is receiving more requests than it can distribute to other parts of the code.
2013-07-23 00:31:57 +01:00
Justin Clark-Casey (justincc) 0d90834f86 Add clientstack.OutgoingUDPSendsCount stat to show number of outbound UDP packets sent by a region per second 2013-07-23 00:15:58 +01:00
Justin Clark-Casey (justincc) 0755fc2f65 Merge branch 'cpu-performance' of ssh://opensimulator.org/var/git/opensim into cpu-performance 2013-07-22 23:59:10 +01:00
Justin Clark-Casey (justincc) 94072fb633 Record raw number of UDP receives as clientstack.IncomingUDPReceivesCount 2013-07-22 23:58:45 +01:00
Robert Adams 882efc1a2e Added check for user movement specification before discarding an incoming
AgentUpdate packet. This fixes the problem with vehicles not moving forward
after the first up-arrow.
Code to fix a potential exception when using different IClientAPIs.

Conflicts:

	OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
2013-07-22 15:51:44 -07:00
Justin Clark-Casey (justincc) deace1f344 Merge branch 'cpu-performance' of ssh://opensimulator.org/var/git/opensim into cpu-performance 2013-07-22 23:37:55 +01:00
Justin Clark-Casey (justincc) 7f0f3cc011 Add AverageUDPProcessTime stat to try and get a handle on how long we're taking on the initial processing of a UDP packet.
If we're not receiving packets with multiple threads (m_asyncPacketHandling) then this is critical since it will limit the number of incoming UDP requests that the region can handle and affects packet loss.
If m_asyncPacketHandling then this is less critical though a long process will increase the scope for threads to race.
This is an experimental stat which may be changed.
2013-07-22 23:30:09 +01:00
Diva Canto c163276032 This commit message intentionally left blank (last commit was idiotic) 2013-07-22 14:35:14 -07:00
Diva Canto a2a05d470e Improve the opening test in CompleteMovement, to account for multiple flags besides ViaLogin. 2013-07-22 14:23:50 -07:00
Diva Canto d5f8b7924c More on putting TP V1 as it was 2013-07-22 13:29:58 -07:00
Diva Canto d70a0c09cb Minor improvements on TP V1 trying to make it exactly as it was before. 2013-07-22 13:16:13 -07:00
Diva Canto df09fdf65d New Teleport protocol (V2), still compatible with V1 and older. (version of the destination is being checked)
In this new protocol, and as committed before, the viewer is not sent EnableSimulator/EstablishChildCommunication for the destination. Instead, it is sent TeleportFinish directly. TeleportFinish, in turn, makes the viewer send a UserCircuitCode packet followed by CompleteMovementIntoRegion packet. These 2 packets tend to occur one after the other almost immediately to the point that when CMIR arrives the client is not even connected yet and that packet is ignored (there might have been some race conditions here before); then the viewer sends CMIR again within 5-8 secs. But the delay between them may be higher in busier regions, which may lead to race conditions.
This commit improves the process so there are are no race conditions at the destination. CompleteMovement (triggered by the viewer) waits until Update has been sent from the origin. Update, in turn, waits until there is a *root* scene presence -- so making sure CompleteMovement has run MakeRoot. In other words, there are two threadlets at the destination, one from the viewer and one from the origin region, waiting for each other to do the right thing. That makes it safe to close the agent at the origin upon return of the Update call without having to wait for callback, because we are absolutely sure that the viewer knows it is in th new region.
Note also that in the V1 protocol, the destination was getting UseCircuitCode from the viewer twice -- once on EstablishAgentCommunication and then again on TeleportFinish. The second UCC was being ignored, but it shows how we were not following the expected steps...
2013-07-22 11:54:35 -07:00
Diva Canto 37337a4de9 Further tweaks on TPs: not sending the callback URL and instead waiting 15sec before closing the agent. This seems to be working fairly well. The viewer seems to have an 8 sec delay between UseCircuitCode and CompleteMovement.
Also added back the position on UpdateAgent, because it's needed for TPing between neighboring regions.
2013-07-21 20:22:13 -07:00
Diva Canto 8d98d287bd EXPERIMENTAL: yet another variation of ES/EAC/TPFinish 2013-07-21 17:38:01 -07:00
Diva Canto e1404adac6 That also didn't work.
Revert "One last thing before I stop on this: now not sending ES and EAC to the viewer. Looking in GridProxy, I don't see those messages in the Linden grid."

This reverts commit 1d27c9f4d1.
2013-07-21 17:23:52 -07:00
Diva Canto 1d27c9f4d1 One last thing before I stop on this: now not sending ES and EAC to the viewer. Looking in GridProxy, I don't see those messages in the Linden grid. 2013-07-21 17:18:54 -07:00
Diva Canto 428b51ffda That also didn't work.
Revert "EXPERIMENTAL: Trying the other order -- delaying MoveAgentIntoRegion until after the departing agent is released."

This reverts commit fe2487f8d3.
2013-07-21 17:11:25 -07:00
Diva Canto fe2487f8d3 EXPERIMENTAL: Trying the other order -- delaying MoveAgentIntoRegion until after the departing agent is released. 2013-07-21 16:49:24 -07:00
Diva Canto b69ddbb66b That didn't work. If anything, it made it worse.
Revert "EXPERIMENTAL: Switch MoveAgentIntoRegion with MakeRootAgent, to see if that eliminates the momentary position at infinity."

This reverts commit 1cb5e31716.
2013-07-21 16:18:24 -07:00
Diva Canto 1cb5e31716 EXPERIMENTAL: Switch MoveAgentIntoRegion with MakeRootAgent, to see if that eliminates the momentary position at infinity. 2013-07-21 16:06:03 -07:00
Diva Canto 7f60800ca6 Don't post Link asset types back to the home grid 2013-07-21 15:46:00 -07:00
Diva Canto ceaa7e9a54 Better version of previous commit 2013-07-21 14:39:50 -07:00
Diva Canto cab3e9978b Add the Current Outfit folder as an available folder in the SuitcaseInventory. 2013-07-21 14:34:43 -07:00
Diva Canto 049022717c Revert "WARNING: DON'T USE THIS COMMIT -- major spew on HG teleports."
This reverts commit 40c54a718f.
2013-07-21 14:08:22 -07:00
Diva Canto 40c54a718f WARNING: DON'T USE THIS COMMIT -- major spew on HG teleports. 2013-07-21 13:46:03 -07:00
Diva Canto 315097b8b9 Minor fixes 2013-07-21 13:36:03 -07:00
Diva Canto 5e5aa5fba7 Now diagnosing a strange behavior where upon TP agents are temporarily placed in very large coordinates, then snap back.
Extra checks in preparation for dropping obsolete data in agent transfers.
2013-07-21 12:44:46 -07:00
Diva Canto 9801d0d4c8 Minor aesthetic change to make things more clear. 2013-07-21 08:50:52 -07:00
Diva Canto d95a470442 The quaternion delta was a bit to high, now that the head rotation is out of the equation. (head rotation was the problematic one) 2013-07-20 19:20:20 -07:00
Diva Canto 74a341fd22 EDIT BEAMS!!! They had been missing from OpenSim since ever. Thanks to lkalif for telling me how to route the information. The viewer effect is under the distance filter, so only avatars with cameras < 10m away see the beams. 2013-07-20 17:58:32 -07:00
Diva Canto 95b248e9e5 Filter certain viewer effects depending on distance between the avatar that is generating the effect and the cameras of the observers. In particular, this applies to LookAt (which is really verbose and occurs every time users move the mouse) and Beam (which doesn't occur that often, but that can be extremely noisy (10.sec) when it happens) 2013-07-20 15:42:01 -07:00
Diva Canto 340abd1110 A couple of small optimizations over the previous commit 2013-07-20 13:42:39 -07:00
Diva Canto 0910c5c101 Manage AgentUpdates more sanely:
- The existing event to scene has been split into 2: OnAgentUpdate and OnAgentCameraUpdate, to better reflect the two types of updates that the viewer sends. We can run one without the other, which is what happens when the avie is still but the user is camming around
- Added thresholds (as opposed to equality) to determine whether the update is significant or not. I thin these thresholds are ok, but we can play with them later
- Ignore updates of HeadRotation, which were problematic and aren't being used up stream
2013-07-20 12:20:35 -07:00
Diva Canto f0126a1575 Fixed the stats in show client stats. Also left some comments with observations about AgentUpdates. 2013-07-19 22:11:32 -07:00
Diva Canto 0d5b2dd5ce Fix HGTravelStore.migrations in SQLite (mantis #6709) 2013-07-19 20:24:56 -07:00
Diva Canto 64cda1b26e Removed verbose debug from previous commit 2013-07-19 13:19:36 -07:00
Diva Canto 778babaab2 Merge branch 'cpu-performance' of ssh://opensimulator.org/var/git/opensim into cpu-performance 2013-07-19 13:18:04 -07:00
Diva Canto d30e5f7ded PollServiceRequestManager: changed the long poll from a Queue to a List. No need to dequeue and enqueue items every 1sec. 2013-07-19 13:17:15 -07:00
Robert Adams f05654d8d6 BulletSim: add position resetting for stationary avatars so they don't
move around when standing on a stationary object.
Create proper linkage between BSCharacter and its actor by generating
a UpdatedProperties event the same way BSPrim does.
2013-07-18 19:19:29 -07:00
Diva Canto 52bb732692 Merge branch 'cpu-performance' of ssh://opensimulator.org/var/git/opensim into cpu-performance 2013-07-18 19:02:46 -07:00
Diva Canto dc88ffc5b4 Delay the enqueueing of non-longpoll requests for 100ms. No need to have these requests actively on the processing queue if it seems they're not ready. 2013-07-18 17:17:20 -07:00
Justin Clark-Casey (justincc) 07420a3b4d furhter shorten CheckAgentUpdateSignificance(). No real perf impact. 2013-07-19 01:00:38 +01:00
Justin Clark-Casey (justincc) 42e5856464 Remove some pointless code in CheckAgentUpdateSignificance() 2013-07-19 00:56:45 +01:00
Justin Clark-Casey (justincc) 3b8e7ff013 Make the check as to whether any particular inbound AgentUpdate packet is significant much earlier in UDP processing (i.e. before we pointlessly place such packets on internal queues, etc.)
Appears to have some impact on cpu but needs testing.
2013-07-19 00:51:13 +01:00
Justin Clark-Casey (justincc) 5c74f3ec9c Add measure of number of inbound AgentUpdates that were seen as significant to "show client stats" (i.e. sent on for further processing instead of being discarded)
Added here since it was the most convenient place
Number is in the last column, "Sig. AgentUpdates" along with percentage of all AgentUpdates
Percentage largely falls over time, most cpu for processing AgentUpdates may be in UDP processing as turning this off even earlier (with "debug lludp toggle agentupdate" results in a big cpu fall
Also tidies up display.
2013-07-19 00:16:09 +01:00
Diva Canto d1e9beead8 Revert "Now trying DoubleQueue instead of BlockingQueue for the PollServiceRequestManager."
This reverts commit 5f95f4d78e.
2013-07-18 15:52:07 -07:00
Justin Clark-Casey (justincc) 35aa6c86fe Hack in console command "debug lludp toggle agentupdate" to allow AgentUpdate in packets to be discarded at a very early stage.
Enabling this will stop anybody from moving on a sim, though all other updates should be unaffected.
Appears to make some cpu difference on very basic testing with a static standing avatar (though not all that much).
Need to see the results with much higher av numbers.
2013-07-18 23:05:45 +01:00
Justin Clark-Casey (justincc) 5cdc21aac7 minor: provide user feedback in the log for now when udp in/out bound threads are started/stopped 2013-07-18 22:54:10 +01:00
Justin Clark-Casey (justincc) cbb47f8489 Merge branch 'cpu-performance' of ssh://opensimulator.org/var/git/opensim into cpu-performance 2013-07-18 22:43:15 +01:00
Justin Clark-Casey (justincc) b2b29b7ec0 Fix up a temporary debugging change from last commit which stopped "lludp stop out" from actually doing anything 2013-07-18 22:42:25 +01:00
Diva Canto 27377194cd Changed the timoeut of EQ 502s (no events) to 50 secs. The viewer post requests timeout in 60 secs.
There's plenty of room for improvement in handling the EQs. Some other time...
2013-07-18 13:48:56 -07:00
Justin Clark-Casey (justincc) 8c6761c152 Do some simple queue empty checks in the main outgoing udp loop instead of always performing these on a separate fired thread.
This appears to improve cpu usage since launching a new thread is more expensive than performing a small amount of inline logic.
However, needs testing at scale.
2013-07-18 21:28:36 +01:00
Diva Canto 553d9cc5d2 Applying the same fix here that dan lake applied to master -- unfortunately I can't cherry-pick because that commit has 2 parents... 2013-07-18 07:52:14 -07:00
Diva Canto c685cc1799 Revert "This is a completely unreasonable thing to do, effectively defying the purpose of BlockingQueues. Trying this, to see the effect on CPU."
This reverts commit 5232ab0496.
2013-07-17 20:42:38 -07:00
Justin Clark-Casey (justincc) 1ba5a05cf7 try Hacking in an AutoResetEvent to control the outgoing UDP loop instead of a continuous loop with sleeps.
Does appear to have a cpu impact but may need further tweaking
2013-07-18 01:17:46 +01:00
Justin Clark-Casey (justincc) 0af3b5ed9a Revert "Put in temporary hack for performnace 'queue-empty' logic on a persistent thread rather than through fire and forget"
This reverts commit b402220dbb.

Eliminating fire and forget here does not appear to make a significant difference.
2013-07-18 00:51:10 +01:00
Justin Clark-Casey (justincc) a94a43d249 Revert "Properly remove the hack queue update thread when the voewr shuts down"
This reverts commit 7c544c0d4e.
2013-07-18 00:50:16 +01:00
Justin Clark-Casey (justincc) 7c544c0d4e Properly remove the hack queue update thread when the voewr shuts down
No functional change.
2013-07-18 00:39:28 +01:00
Justin Clark-Casey (justincc) b402220dbb Put in temporary hack for performnace 'queue-empty' logic on a persistent thread rather than through fire and forget
May not scale since this gives each client its own thread.
2013-07-18 00:30:22 +01:00
1741 changed files with 187515 additions and 303216 deletions

21
.gitignore vendored
View File

@ -1,6 +1,5 @@
.project .project
.settings .settings
.gitignore
*.csproj *.csproj
*.csproj.user *.csproj.user
*.build *.build
@ -11,13 +10,6 @@
*.pidb *.pidb
*.dll.build *.dll.build
*.dll *.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
*.suo
*.user
*.VisualState.xml *.VisualState.xml
*/*/obj */*/obj
*/*/*/obj */*/*/obj
@ -31,8 +23,6 @@
*/*/*/*/*/bin */*/*/*/*/bin
*/*/*/*/*/*/bin */*/*/*/*/*/bin
*/*/*/*/*/*/*/bin */*/*/*/*/*/*/bin
.vs/
addon-modules/
bin/Debug/*.dll bin/Debug/*.dll
bin/*.dll.mdb bin/*.dll.mdb
bin/*.db bin/*.db
@ -58,7 +48,6 @@ bin/Regions/*
bin/UserAssets bin/UserAssets
bin/assetcache bin/assetcache
bin/maptiles bin/maptiles
bin/bakes
bin/estate_settings.xml bin/estate_settings.xml
bin/config-include/CenomeCache.ini bin/config-include/CenomeCache.ini
bin/config-include/FlotsamCache.ini bin/config-include/FlotsamCache.ini
@ -71,17 +60,12 @@ bin/OpenSim.Grid.InventoryServer.log
bin/OpenSim.Grid.MessagingServer.log bin/OpenSim.Grid.MessagingServer.log
bin/OpenSim.Grid.UserServer.log bin/OpenSim.Grid.UserServer.log
bin/OpenSim.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/*.manifest
bin/crashes/ bin/crashes/
Examples/*.dll Examples/*.dll
OpenSim.build OpenSim.build
OpenSim.sln OpenSim.sln
OpenSim.suo
OpenSim.userprefs OpenSim.userprefs
Prebuild/Prebuild.build Prebuild/Prebuild.build
Prebuild/Prebuild.sln Prebuild/Prebuild.sln
@ -94,6 +78,7 @@ TAGS
Makefile.local Makefile.local
bin/.version bin/.version
compile.bat compile.bat
addon-modules
OpenSim/Data/Tests/test-results/ OpenSim/Data/Tests/test-results/
OpenSim/Framework/Serialization/Tests/test-results/ OpenSim/Framework/Serialization/Tests/test-results/
OpenSim/Framework/Servers/Tests/test-results/ OpenSim/Framework/Servers/Tests/test-results/
@ -112,5 +97,3 @@ OpenSim/Tests/test-results/
test-results/ test-results/
doc/html doc/html
doc/doxygen.error.log doc/doxygen.error.log
*.patch

View File

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

View File

@ -1,35 +1,34 @@
# Building on Windows # Building on Windows
Steps: Steps:
* runprebuild.bat * runprebuild.bat
* Load OpenSim.sln into Visual Studio .NET and build the solution. * Load OpenSim.sln into Visual Studio .NET and build the solution.
* chdir bin * chdir bin
* copy OpenSim.ini.example to OpenSim.ini and other appropriate files in bin/config-include * copy OpenSim.ini.example to OpenSim.ini and other appropriate files in bin/config-include
* run OpenSim.exe * run OpenSim.exe
# Building on Linux / Mac # Building on Linux
Prereqs: Prereqs:
* Mono >= 2.4.3
* Mono > 5.0 * Nant >= 0.85
* On some Linux distributions you may need to install additional packages. * 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.
* 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: From the distribution type:
* ./runprebuild.sh * ./runprebuild.sh
* type msbuild or xbuild * nant (or xbuild)
* cd bin * cd bin
* copy OpenSim.ini.example to OpenSim.ini and other appropriate files in bin/config-include * 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 * run mono OpenSim.exe
* windows: execute opensim.exe or opensim32.exe for small regions
* linux: run ./opensim.sh # Using Monodevelop
* msbuild (xbuild) option switches
* clean: msbuild /target:clean From the distribution type:
* debug: (default) msbuild /property:Configuration=Debug * ./runprebuild.sh
* release: msbuild /property:Configuration=Release * type monodevelop OpenSim.sln
# References # References

View File

@ -1,22 +1,39 @@
The following people have contributed to OpenSim (Thank you for your effort!) <<<>>>>The following people have contributed to OpenSim (Thank you
for your effort!)
= Current OpenSim Developers (in very rough order of appearance) = = Current OpenSim Developers (in very rough order of appearance) =
These folks represent the current core team for OpenSim, and are the These folks represent the current core team for OpenSim, and are the
people that make the day to day of OpenSim happen. people that make the day to day of OpenSim happen.
* justincc (OSVW Consulting, justincc.org)
* chi11ken (Genkii)
* dahlia
* Melanie Thielker * Melanie Thielker
* Diva (Crista Lopes, University of California, Irvine) * Diva (Crista Lopes, University of California, Irvine)
* Robert Adams (MisterBlue) * Dan Lake (Intel)
* Kevin Cozens * Marck
* Leal Duarte (Ubit Umarov) * Mic Bowman (Intel)
* BlueWall (James Hughes)
* Nebadon Izumi (Michael Cerquoni, OSgrid)
* Snoopy Pfeffer
* Robert Adams (Intel)
= Core Developers Following the White Rabbit = = Core Developers Following the White Rabbit =
Core developers who have temporarily (we hope) gone chasing 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 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. been that active lately, so their voting rights are awaiting their come back.
* Nebadon Izumi (Michael Cerquoni, OSgrid) * MW (Tribal Media AB)
* Alicia Raven * 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 = = Past Open Sim Developers =
These folks are alumns of the OpenSim core group, but are now These folks are alumns of the OpenSim core group, but are now
@ -38,86 +55,49 @@ where we are today.
* adjohn (Genkii) * adjohn (Genkii)
* idb (Ian Brown) * idb (Ian Brown)
* Johan Berntsson (3Di) * 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 = = Additional OpenSim Contributors =
These folks have contributed code patches or content to OpenSimulator to help make it These folks have contributed code patches or content to OpenSimulator to help make it
what it is today. what it is today.
* A_Biondi
* aduffy70 * aduffy70
* Ai Austin * A_Biondi
* alex_carnell * alex_carnell
* Alan Webb (IBM) * Alan Webb (IBM)
* Aleric
* Allen Kerensky * Allen Kerensky
* BigFootAg * BigFootAg
* Bill Blight
* BlueWall Slade * BlueWall Slade
* bobshaffer2
* brianw/Sir_Ahzz * brianw/Sir_Ahzz
* CharlieO * CharlieO
* ChrisDown * ChrisDown
* Chris Yeoh (IBM) * Chris Yeoh (IBM)
* cinderblocks
* controlbreak * controlbreak
* coyled * coyled
* ctrlaltdavid (David Rowe)
* Daedius * Daedius
* daTwitch * daTwitch
* Dev Random
* devalnor-#708 * devalnor-#708
* dmiles (Daxtron Labs) * dmiles (Daxtron Labs)
* Dong Jun Lan (IBM) * Dong Jun Lan (IBM)
* DoranZemlja * DoranZemlja
* Drake Arconis
* dr0b3rts * dr0b3rts
* dslake * dslake (Intel)
* eeyore
* FredoChaplin * FredoChaplin
* FreakyTech
* Garmin Kawaguichi * Garmin Kawaguichi
* Gavin Hird
* Gerhard * Gerhard
* Godfrey * Godfrey
* Greg C.
* Grumly57 * Grumly57
* GuduleLapointe * GuduleLapointe
* Ewe Loon * Ewe Loon
* Fernando Oliveira * Fernando Oliveira
* Fly-Man * Fly-Man
* Flyte Xevious * Flyte Xevious
* Freaky Tech
* Garmin Kawaguichi * Garmin Kawaguichi
* Geir Noklebye
* Glenn Martin (MOSES)
* Gryc Ueusp * Gryc Ueusp
* H-H-H (ginge264)
* Hiro Lecker * Hiro Lecker
* Iain Oliver * Iain Oliver
* Imaze Rhiano * Imaze Rhiano
* Intimidated * Intimidated
* Jak Daniels
* Jeff Kelly
* Jeremy Bongio (IBM) * Jeremy Bongio (IBM)
* jhurliman * jhurliman
* John R Sohn (XenReborn) * John R Sohn (XenReborn)
@ -125,36 +105,25 @@ what it is today.
* Jon Cundill * Jon Cundill
* Junta Kohime * Junta Kohime
* Kayne * Kayne
* Kevin Cozens
* kinoc (Daxtron Labs) * kinoc (Daxtron Labs)
* Kira
* Kitto Flora * Kitto Flora
* KittyLiu * KittyLiu
* Kurt Taylor (IBM) * Kurt Taylor (IBM)
* Lani Global
* lickx
* lillith_xue
* lkalif * lkalif
* LuciusSirnah
* lulurun * lulurun
* M.Igarashi * M.Igarashi
* Magnuz Binder
* maimedleech * maimedleech
* Mana Janus * Mana Janus
* Mandarinka Tasty
* MarcelEdward * MarcelEdward
* Matt Lehmann
* mewtwo0641
* Mic Bowman * Mic Bowman
* Michelle Argus * Michelle Argus
* Michael Cortez (The Flotsam Project, http://osflotsam.org/) * Michael Cortez (The Flotsam Project, http://osflotsam.org/)
* Michael Heilmann (MOSES)
* Micheil Merlin * Micheil Merlin
* Mike Osias (IBM) * Mike Osias (IBM)
* Mike Pitman (IBM) * Mike Pitman (IBM)
* Mike Rieker (Dreamnation)
* mikemig
* mikkopa/_someone - RealXtend * mikkopa/_someone - RealXtend
* Misterblue * Misterblue (Intel)
* Mircea Kitsune * Mircea Kitsune
* mpallari * mpallari
* MrMonkE * MrMonkE
@ -163,42 +132,32 @@ what it is today.
* nornalbion * nornalbion
* Omar Vera Ustariz (IBM) * Omar Vera Ustariz (IBM)
* openlifegrid.com * openlifegrid.com
* Oren Hurvitz (Kitely)
* otakup0pe * otakup0pe
* Pixel Tomsen * Pixel Tomsen
* Quill Littlefeather
* ralphos * ralphos
* RemedyTomm * RemedyTomm
* Revolution * Revolution
* Richard Alimi (IBM) * Richard Alimi (IBM)
* Rick Alther (IBM) * Rick Alther (IBM)
* Rob Smart (IBM) * Rob Smart (IBM)
* Robert Louden (MOSES)
* Roger Kirkman (zadark)
* rtomita * rtomita
* Ruud Lathorp * Ruud Lathorp
* SachaMagne * SachaMagne
* Salahzar Stenvaag * Salahzar Stenvaag
* satguru p srivastava * satguru p srivastava
* sempuki * sempuki
* Shy Robbiani
* SignpostMarv * SignpostMarv
* SpotOn3D * SpotOn3D
* Stefan_Boom / stoehr * Stefan_Boom / stoehr
* Steven Zielinski (MOSES)
* Stolen Ruby
* Strawberry Fride * Strawberry Fride
* Talun * Talun
* TechplexEngineer (Blake Bourque) * TechplexEngineer (Blake Bourque)
* TBG Renfold * TBG Renfold
* Terry Ford
* tglion * tglion
* tlaukkan/Tommil (Tommi S. E. Laukkanen, Bubble Cloud) * tlaukkan/Tommil (Tommi S. E. Laukkanen, Bubble Cloud)
* TomDataWorks
* TomTheDragon (muckwaddle)
* tyre * tyre
* uriesk
* Vegaslon <vegaslon@gmail.com> * Vegaslon <vegaslon@gmail.com>
* Vincent Sylvester
* VikingErik * VikingErik
* Vytek * Vytek
* webmage (IBM) * webmage (IBM)
@ -210,18 +169,23 @@ what it is today.
* Zha Ewry * Zha Ewry
* ziah * ziah
= LSL Devs = = LSL Devs =
* Alondria * Alondria
* CharlieO * CharlieO
* Tedd * Tedd
* Melanie Thielker * Melanie Thielker
= Testers = = Testers =
* Ai Austin * Ai Austin
* CharlieO (LSL) * CharlieO (LSL)
* Ckrinke * Ckrinke
* openlifegrid.com * openlifegrid.com
This software uses components from the following developers: This software uses components from the following developers:
* Sleepycat Software (Berkeley DB) * Sleepycat Software (Berkeley DB)
* Aurora-Sim (http://aurora-sim.org) * Aurora-Sim (http://aurora-sim.org)

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.Framework;
using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.Framework.Interfaces;
using OpenSim.Services.Interfaces;
namespace OpenSim.Groups namespace OpenSim.Groups
{ {

View File

@ -46,7 +46,7 @@ namespace OpenSim.Groups
public string AccessToken; public string AccessToken;
} }
public class ExtendedGroupMembersData public class ExtendedGroupMembersData
{ {
// This is the only difference: this is a string // This is the only difference: this is a string
public string AgentID; public string AgentID;
@ -65,7 +65,7 @@ namespace OpenSim.Groups
public UUID RoleID; public UUID RoleID;
// This is the only difference: this is a string // This is the only difference: this is a string
public string MemberID; public string MemberID;
} }
public struct ExtendedGroupNoticeData public struct ExtendedGroupNoticeData
@ -174,7 +174,7 @@ namespace OpenSim.Groups
if (dict.ContainsKey("ServiceLocation") && dict["ServiceLocation"] != null) if (dict.ContainsKey("ServiceLocation") && dict["ServiceLocation"] != null)
grec.ServiceLocation = dict["ServiceLocation"].ToString(); grec.ServiceLocation = dict["ServiceLocation"].ToString();
else else
grec.ServiceLocation = string.Empty; grec.GroupName = string.Empty;
if (dict.ContainsKey("ShownInList") && dict["ShownInList"] != null) if (dict.ContainsKey("ShownInList") && dict["ShownInList"] != null)
grec.ShowInList = bool.Parse(dict["ShownInList"].ToString()); grec.ShowInList = bool.Parse(dict["ShownInList"].ToString());
@ -504,30 +504,6 @@ namespace OpenSim.Groups
return notice; return notice;
} }
public static Dictionary<string, object> DirGroupsReplyData(DirGroupsReplyData g)
{
Dictionary<string, object> dict = new Dictionary<string, object>();
dict["GroupID"] = g.groupID;
dict["Name"] = g.groupName;
dict["NMembers"] = g.members;
dict["SearchOrder"] = g.searchOrder;
return dict;
}
public static DirGroupsReplyData DirGroupsReplyData(Dictionary<string, object> dict)
{
DirGroupsReplyData g;
g.groupID = new UUID(dict["GroupID"].ToString());
g.groupName = dict["Name"].ToString();
Int32.TryParse(dict["NMembers"].ToString(), out g.members);
float.TryParse(dict["SearchOrder"].ToString(), out g.searchOrder);
return g;
}
} }
} }

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

@ -39,7 +39,6 @@ using OpenSim.Region.Framework.Interfaces;
using OpenSim.Region.Framework.Scenes; using OpenSim.Region.Framework.Scenes;
using OpenSim.Services.Interfaces; using OpenSim.Services.Interfaces;
using PresenceInfo = OpenSim.Services.Interfaces.PresenceInfo; using PresenceInfo = OpenSim.Services.Interfaces.PresenceInfo;
using GridRegion = OpenSim.Services.Interfaces.GridRegion;
namespace OpenSim.Groups namespace OpenSim.Groups
{ {
@ -52,12 +51,12 @@ namespace OpenSim.Groups
private IPresenceService m_presenceService; private IPresenceService m_presenceService;
private IMessageTransferModule m_msgTransferModule = null; private IMessageTransferModule m_msgTransferModule = null;
private IUserManagement m_UserManagement = null;
private IGroupsServicesConnector m_groupData = null; private IGroupsServicesConnector m_groupData = null;
// Config Options // Config Options
private bool m_groupMessagingEnabled; private bool m_groupMessagingEnabled = false;
private bool m_debugEnabled; private bool m_debugEnabled = true;
/// <summary> /// <summary>
/// If enabled, module only tries to send group IMs to online users by querying cached presence information. /// If enabled, module only tries to send group IMs to online users by querying cached presence information.
@ -80,9 +79,6 @@ namespace OpenSim.Groups
private int m_usersOnlineCacheExpirySeconds = 20; private int m_usersOnlineCacheExpirySeconds = 20;
private Dictionary<UUID, List<string>> m_groupsAgentsDroppedFromChatSession = new Dictionary<UUID, List<string>>();
private Dictionary<UUID, List<string>> m_groupsAgentsInvitedToChatSession = new Dictionary<UUID, List<string>>();
#region Region Module interfaceBase Members #region Region Module interfaceBase Members
public void Initialise(IConfigSource config) public void Initialise(IConfigSource config)
@ -110,17 +106,9 @@ namespace OpenSim.Groups
m_messageOnlineAgentsOnly = groupsConfig.GetBoolean("MessageOnlineUsersOnly", false); m_messageOnlineAgentsOnly = groupsConfig.GetBoolean("MessageOnlineUsersOnly", false);
if (m_messageOnlineAgentsOnly) if (m_messageOnlineAgentsOnly)
{
m_usersOnlineCache = new ExpiringCache<UUID, PresenceInfo[]>(); m_usersOnlineCache = new ExpiringCache<UUID, PresenceInfo[]>();
}
else
{
m_log.Error("[Groups.Messaging]: GroupsMessagingModule V2 requires MessageOnlineUsersOnly = true");
m_groupMessagingEnabled = false;
return;
}
m_debugEnabled = groupsConfig.GetBoolean("MessagingDebugEnabled", m_debugEnabled); m_debugEnabled = groupsConfig.GetBoolean("DebugEnabled", true);
m_log.InfoFormat( m_log.InfoFormat(
"[Groups.Messaging]: GroupsMessagingModule enabled with MessageOnlineOnly = {0}, DebugEnabled = {1}", "[Groups.Messaging]: GroupsMessagingModule enabled with MessageOnlineOnly = {0}, DebugEnabled = {1}",
@ -131,25 +119,15 @@ namespace OpenSim.Groups
{ {
if (!m_groupMessagingEnabled) if (!m_groupMessagingEnabled)
return; return;
scene.RegisterModuleInterface<IGroupsMessagingModule>(this); scene.RegisterModuleInterface<IGroupsMessagingModule>(this);
m_sceneList.Add(scene); m_sceneList.Add(scene);
scene.EventManager.OnNewClient += OnNewClient; scene.EventManager.OnNewClient += OnNewClient;
scene.EventManager.OnMakeRootAgent += OnMakeRootAgent;
scene.EventManager.OnMakeChildAgent += OnMakeChildAgent;
scene.EventManager.OnIncomingInstantMessage += OnGridInstantMessage; scene.EventManager.OnIncomingInstantMessage += OnGridInstantMessage;
scene.EventManager.OnClientLogin += OnClientLogin; scene.EventManager.OnClientLogin += OnClientLogin;
scene.AddCommand(
"Debug",
this,
"debug groups messaging verbose",
"debug groups messaging verbose <true|false>",
"This setting turns on very verbose groups messaging debugging",
HandleDebugGroupsMessagingVerbose);
} }
public void RegionLoaded(Scene scene) public void RegionLoaded(Scene scene)
{ {
if (!m_groupMessagingEnabled) if (!m_groupMessagingEnabled)
@ -163,7 +141,7 @@ namespace OpenSim.Groups
if (m_groupData == null) if (m_groupData == null)
{ {
m_log.Error("[Groups.Messaging]: Could not get IGroupsServicesConnector, GroupsMessagingModule is now disabled."); m_log.Error("[Groups.Messaging]: Could not get IGroupsServicesConnector, GroupsMessagingModule is now disabled.");
RemoveRegion(scene); RemoveRegion(scene);
return; return;
} }
@ -177,18 +155,9 @@ namespace OpenSim.Groups
return; return;
} }
m_UserManagement = scene.RequestModuleInterface<IUserManagement>();
// No groups module, no groups messaging
if (m_UserManagement == null)
{
m_log.Error("[Groups.Messaging]: Could not get IUserManagement, GroupsMessagingModule is now disabled.");
RemoveRegion(scene);
return;
}
if (m_presenceService == null) if (m_presenceService == null)
m_presenceService = scene.PresenceService; m_presenceService = scene.PresenceService;
} }
public void RemoveRegion(Scene scene) public void RemoveRegion(Scene scene)
@ -218,7 +187,7 @@ namespace OpenSim.Groups
m_msgTransferModule = null; m_msgTransferModule = null;
} }
public Type ReplaceableInterface public Type ReplaceableInterface
{ {
get { return null; } get { return null; }
} }
@ -235,25 +204,6 @@ namespace OpenSim.Groups
#endregion #endregion
private void HandleDebugGroupsMessagingVerbose(object modules, string[] args)
{
if (args.Length < 5)
{
MainConsole.Instance.Output("Usage: debug groups messaging verbose <true|false>");
return;
}
bool verbose = false;
if (!bool.TryParse(args[4], out verbose))
{
MainConsole.Instance.Output("Usage: debug groups messaging verbose <true|false>");
return;
}
m_debugEnabled = verbose;
MainConsole.Instance.Output("{0} verbose logging set to {1}", Name, m_debugEnabled);
}
/// <summary> /// <summary>
/// Not really needed, but does confirm that the group exists. /// Not really needed, but does confirm that the group exists.
@ -262,7 +212,7 @@ namespace OpenSim.Groups
{ {
if (m_debugEnabled) if (m_debugEnabled)
m_log.DebugFormat("[Groups.Messaging]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); m_log.DebugFormat("[Groups.Messaging]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
GroupRecord groupInfo = m_groupData.GetGroupRecord(agentID.ToString(), groupID, null); GroupRecord groupInfo = m_groupData.GetGroupRecord(agentID.ToString(), groupID, null);
if (groupInfo != null) if (groupInfo != null)
@ -274,147 +224,95 @@ namespace OpenSim.Groups
return false; return false;
} }
} }
public void SendMessageToGroup(GridInstantMessage im, UUID groupID) public void SendMessageToGroup(GridInstantMessage im, UUID groupID)
{ {
SendMessageToGroup(im, groupID, UUID.Zero, null); List<GroupMembersData> groupMembers = m_groupData.GetGroupMembers(new UUID(im.fromAgentID).ToString(), groupID);
}
public void SendMessageToGroup(
GridInstantMessage im, UUID groupID, UUID sendingAgentForGroupCalls, Func<GroupMembersData, bool> sendCondition)
{
int requestStartTick = Environment.TickCount;
UUID fromAgentID = new UUID(im.fromAgentID);
// Unlike current XmlRpcGroups, Groups V2 can accept UUID.Zero when a perms check for the requesting agent
// is not necessary.
List<GroupMembersData> groupMembers = m_groupData.GetGroupMembers(UUID.Zero.ToString(), groupID);
int groupMembersCount = groupMembers.Count; int groupMembersCount = groupMembers.Count;
PresenceInfo[] onlineAgents = null;
// In V2 we always only send to online members. if (m_messageOnlineAgentsOnly)
// Sending to offline members is not an option.
string[] t1 = groupMembers.ConvertAll<string>(gmd => gmd.AgentID.ToString()).ToArray();
// We cache in order not to overwhelm the presence service on large grids with many groups. This does
// mean that members coming online will not see all group members until after m_usersOnlineCacheExpirySeconds has elapsed.
// (assuming this is the same across all grid simulators).
if (!m_usersOnlineCache.TryGetValue(groupID, out onlineAgents))
{ {
onlineAgents = m_presenceService.GetAgents(t1); string[] t1 = groupMembers.ConvertAll<string>(gmd => gmd.AgentID.ToString()).ToArray();
m_usersOnlineCache.Add(groupID, onlineAgents, m_usersOnlineCacheExpirySeconds);
}
HashSet<string> onlineAgentsUuidSet = new HashSet<string>(); // We cache in order not to overwhlem the presence service on large grids with many groups. This does
Array.ForEach<PresenceInfo>(onlineAgents, pi => onlineAgentsUuidSet.Add(pi.UserID)); // mean that members coming online will not see all group members until after m_usersOnlineCacheExpirySeconds has elapsed.
// (assuming this is the same across all grid simulators).
PresenceInfo[] onlineAgents;
if (!m_usersOnlineCache.TryGetValue(groupID, out onlineAgents))
{
onlineAgents = m_presenceService.GetAgents(t1);
m_usersOnlineCache.Add(groupID, onlineAgents, m_usersOnlineCacheExpirySeconds);
}
groupMembers = groupMembers.Where(gmd => onlineAgentsUuidSet.Contains(gmd.AgentID.ToString())).ToList(); HashSet<string> onlineAgentsUuidSet = new HashSet<string>();
Array.ForEach<PresenceInfo>(onlineAgents, pi => onlineAgentsUuidSet.Add(pi.UserID));
// if (m_debugEnabled) groupMembers = groupMembers.Where(gmd => onlineAgentsUuidSet.Contains(gmd.AgentID.ToString())).ToList();
// if (m_debugEnabled)
// m_log.DebugFormat( // m_log.DebugFormat(
// "[Groups.Messaging]: SendMessageToGroup called for group {0} with {1} visible members, {2} online", // "[Groups.Messaging]: SendMessageToGroup called for group {0} with {1} visible members, {2} online",
// groupID, groupMembersCount, groupMembers.Count()); // groupID, groupMembersCount, groupMembers.Count());
}
im.imSessionID = groupID.Guid; else
im.fromGroup = true;
IClientAPI thisClient = GetActiveClient(fromAgentID);
if (thisClient != null)
{ {
im.RegionID = thisClient.Scene.RegionInfo.RegionID.Guid; if (m_debugEnabled)
m_log.DebugFormat(
"[Groups.Messaging]: SendMessageToGroup called for group {0} with {1} visible members",
groupID, groupMembers.Count);
} }
if ((im.binaryBucket == null) || (im.binaryBucket.Length == 0) || ((im.binaryBucket.Length == 1 && im.binaryBucket[0] == 0))) int requestStartTick = Environment.TickCount;
{
ExtendedGroupRecord groupInfo = m_groupData.GetGroupRecord(UUID.Zero.ToString(), groupID, null);
if (groupInfo != null)
im.binaryBucket = Util.StringToBytes256(groupInfo.GroupName);
}
// Send to self first of all
im.toAgentID = im.fromAgentID;
im.fromGroup = true;
ProcessMessageFromGroupSession(im);
List<UUID> regions = new List<UUID>();
List<UUID> clientsAlreadySent = new List<UUID>();
// Then send to everybody else
foreach (GroupMembersData member in groupMembers) foreach (GroupMembersData member in groupMembers)
{ {
if (member.AgentID.Guid == im.fromAgentID) if (m_groupData.hasAgentDroppedGroupChatSession(member.AgentID.ToString(), groupID))
continue;
if (clientsAlreadySent.Contains(member.AgentID))
continue;
clientsAlreadySent.Add(member.AgentID);
if (sendCondition != null)
{
if (!sendCondition(member))
{
if (m_debugEnabled)
m_log.DebugFormat(
"[Groups.Messaging]: Not sending to {0} as they do not fulfill send condition",
member.AgentID);
continue;
}
}
else if (hasAgentDroppedGroupChatSession(member.AgentID.ToString(), groupID))
{ {
// Don't deliver messages to people who have dropped this session // 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);
m_log.DebugFormat("[Groups.Messaging]: {0} has dropped session, not delivering to them", member.AgentID);
continue; continue;
} }
im.toAgentID = member.AgentID.Guid; // Copy Message
GridInstantMessage msg = new GridInstantMessage();
msg.imSessionID = groupID.Guid;
msg.fromAgentName = im.fromAgentName;
msg.message = im.message;
msg.dialog = im.dialog;
msg.offline = im.offline;
msg.ParentEstateID = im.ParentEstateID;
msg.Position = im.Position;
msg.RegionID = im.RegionID;
msg.binaryBucket = im.binaryBucket;
msg.timestamp = (uint)Util.UnixTimeSinceEpoch();
msg.fromAgentID = im.fromAgentID;
msg.fromGroup = true;
msg.toAgentID = member.AgentID.Guid;
IClientAPI client = GetActiveClient(member.AgentID); IClientAPI client = GetActiveClient(member.AgentID);
if (client == null) if (client == null)
{ {
// If they're not local, forward across the grid // If they're not local, forward across the grid
// BUT do it only once per region, please! Sim would be even better!
if (m_debugEnabled) m_log.DebugFormat("[Groups.Messaging]: Delivering to {0} via Grid", member.AgentID); if (m_debugEnabled) m_log.DebugFormat("[Groups.Messaging]: Delivering to {0} via Grid", member.AgentID);
m_msgTransferModule.SendInstantMessage(msg, delegate(bool success) { });
bool reallySend = true;
if (onlineAgents != null)
{
PresenceInfo presence = onlineAgents.First(p => p.UserID == member.AgentID.ToString());
if (regions.Contains(presence.RegionID))
reallySend = false;
else
regions.Add(presence.RegionID);
}
if (reallySend)
{
// We have to create a new IM structure because the transfer module
// uses async send
GridInstantMessage msg = new GridInstantMessage(im, true);
m_msgTransferModule.SendInstantMessage(msg, delegate(bool success) { });
}
} }
else else
{ {
// Deliver locally, directly // Deliver locally, directly
if (m_debugEnabled) m_log.DebugFormat("[Groups.Messaging]: Passing to ProcessMessageFromGroupSession to deliver to {0} locally", client.Name); if (m_debugEnabled) m_log.DebugFormat("[Groups.Messaging]: Passing to ProcessMessageFromGroupSession to deliver to {0} locally", client.Name);
ProcessMessageFromGroupSession(msg);
ProcessMessageFromGroupSession(im);
} }
} }
if (m_debugEnabled) // Temporary for assessing how long it still takes to send messages to large online groups.
if (m_messageOnlineAgentsOnly)
m_log.DebugFormat( m_log.DebugFormat(
"[Groups.Messaging]: SendMessageToGroup for group {0} with {1} visible members, {2} online took {3}ms", "[Groups.Messaging]: SendMessageToGroup for group {0} with {1} visible members, {2} online took {3}ms",
groupID, groupMembersCount, groupMembers.Count(), Environment.TickCount - requestStartTick); groupID, groupMembersCount, groupMembers.Count(), Environment.TickCount - requestStartTick);
} }
#region SimGridEventHandlers #region SimGridEventHandlers
void OnClientLogin(IClientAPI client) void OnClientLogin(IClientAPI client)
@ -426,113 +324,32 @@ namespace OpenSim.Groups
{ {
if (m_debugEnabled) m_log.DebugFormat("[Groups.Messaging]: OnInstantMessage registered for {0}", client.Name); if (m_debugEnabled) m_log.DebugFormat("[Groups.Messaging]: OnInstantMessage registered for {0}", client.Name);
ResetAgentGroupChatSessions(client.AgentId.ToString()); client.OnInstantMessage += OnInstantMessage;
} }
void OnMakeRootAgent(ScenePresence sp)
{
sp.ControllingClient.OnInstantMessage += OnInstantMessage;
}
void OnMakeChildAgent(ScenePresence sp)
{
sp.ControllingClient.OnInstantMessage -= OnInstantMessage;
}
private void OnGridInstantMessage(GridInstantMessage msg) private void OnGridInstantMessage(GridInstantMessage msg)
{ {
// The instant message module will only deliver messages of dialog types: // The instant message module will only deliver messages of dialog types:
// MessageFromAgent, StartTyping, StopTyping, MessageFromObject // 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 // Instant Message Module
UUID regionID = new UUID(msg.RegionID);
if (m_debugEnabled) if (m_debugEnabled)
{ {
m_log.DebugFormat("[Groups.Messaging]: {0} called, IM from region {1}", m_log.DebugFormat("[Groups.Messaging]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
System.Reflection.MethodBase.GetCurrentMethod().Name, regionID);
DebugGridInstantMessage(msg); DebugGridInstantMessage(msg);
} }
// Incoming message from a group // Incoming message from a group
if ((msg.fromGroup == true) && (msg.dialog == (byte)InstantMessageDialog.SessionSend)) if ((msg.fromGroup == true) &&
((msg.dialog == (byte)InstantMessageDialog.SessionSend)
|| (msg.dialog == (byte)InstantMessageDialog.SessionAdd)
|| (msg.dialog == (byte)InstantMessageDialog.SessionDrop)))
{ {
// We have to redistribute the message across all members of the group who are here ProcessMessageFromGroupSession(msg);
// on this sim
UUID GroupID = new UUID(msg.imSessionID);
Scene aScene = m_sceneList[0];
GridRegion regionOfOrigin = aScene.GridService.GetRegionByUUID(aScene.RegionInfo.ScopeID, regionID);
List<GroupMembersData> groupMembers = m_groupData.GetGroupMembers(UUID.Zero.ToString(), GroupID);
//if (m_debugEnabled)
// foreach (GroupMembersData m in groupMembers)
// m_log.DebugFormat("[Groups.Messaging]: member {0}", m.AgentID);
foreach (Scene s in m_sceneList)
{
s.ForEachScenePresence(sp =>
{
// If we got this via grid messaging, it's because the caller thinks
// that the root agent is here. We should only send the IM to root agents.
if (sp.IsChildAgent)
return;
GroupMembersData m = groupMembers.Find(gmd =>
{
return gmd.AgentID == sp.UUID;
});
if (m.AgentID == UUID.Zero)
{
if (m_debugEnabled)
m_log.DebugFormat("[Groups.Messaging]: skipping agent {0} because he is not a member of the group", sp.UUID);
return;
}
// Check if the user has an agent in the region where
// the IM came from, and if so, skip it, because the IM
// was already sent via that agent
if (regionOfOrigin != null)
{
AgentCircuitData aCircuit = s.AuthenticateHandler.GetAgentCircuitData(sp.UUID);
if (aCircuit != null)
{
if (aCircuit.ChildrenCapSeeds.Keys.Contains(regionOfOrigin.RegionHandle))
{
if (m_debugEnabled)
m_log.DebugFormat("[Groups.Messaging]: skipping agent {0} because he has an agent in region of origin", sp.UUID);
return;
}
else
{
if (m_debugEnabled)
m_log.DebugFormat("[Groups.Messaging]: not skipping agent {0}", sp.UUID);
}
}
}
UUID AgentID = sp.UUID;
msg.toAgentID = AgentID.Guid;
if (!hasAgentDroppedGroupChatSession(AgentID.ToString(), GroupID))
{
if (!hasAgentBeenInvitedToGroupChatSession(AgentID.ToString(), GroupID))
AddAgentToSession(AgentID, GroupID, msg);
else
{
if (m_debugEnabled) m_log.DebugFormat("[Groups.Messaging]: Passing to ProcessMessageFromGroupSession to deliver to {0} locally", sp.Name);
ProcessMessageFromGroupSession(msg);
}
}
});
}
} }
} }
@ -542,40 +359,82 @@ namespace OpenSim.Groups
UUID AgentID = new UUID(msg.fromAgentID); UUID AgentID = new UUID(msg.fromAgentID);
UUID GroupID = new UUID(msg.imSessionID); UUID GroupID = new UUID(msg.imSessionID);
UUID toAgentID = new UUID(msg.toAgentID);
switch (msg.dialog) switch (msg.dialog)
{ {
case (byte)InstantMessageDialog.SessionAdd: case (byte)InstantMessageDialog.SessionAdd:
AgentInvitedToGroupChatSession(AgentID.ToString(), GroupID); m_groupData.AgentInvitedToGroupChatSession(AgentID.ToString(), GroupID);
break; break;
case (byte)InstantMessageDialog.SessionDrop: case (byte)InstantMessageDialog.SessionDrop:
AgentDroppedFromGroupChatSession(AgentID.ToString(), GroupID); m_groupData.AgentDroppedFromGroupChatSession(AgentID.ToString(), GroupID);
break; break;
case (byte)InstantMessageDialog.SessionSend: case (byte)InstantMessageDialog.SessionSend:
// User hasn't dropped, so they're in the session, if (!m_groupData.hasAgentDroppedGroupChatSession(AgentID.ToString(), GroupID)
// maybe we should deliver it. && !m_groupData.hasAgentBeenInvitedToGroupChatSession(AgentID.ToString(), GroupID)
IClientAPI client = GetActiveClient(new UUID(msg.toAgentID)); )
if (client != null)
{ {
// Deliver locally, directly // Agent not in session and hasn't dropped from session
if (m_debugEnabled) m_log.DebugFormat("[Groups.Messaging]: Delivering to {0} locally", client.Name); // Add them to the session for now, and Invite them
m_groupData.AgentInvitedToGroupChatSession(AgentID.ToString(), GroupID);
if (!hasAgentDroppedGroupChatSession(toAgentID.ToString(), GroupID)) UUID toAgentID = new UUID(msg.toAgentID);
IClientAPI activeClient = GetActiveClient(toAgentID);
if (activeClient != null)
{ {
if (!hasAgentBeenInvitedToGroupChatSession(toAgentID.ToString(), GroupID)) GroupRecord groupInfo = m_groupData.GetGroupRecord(UUID.Zero.ToString(), GroupID, null);
// This actually sends the message too, so no need to resend it if (groupInfo != null)
// with client.SendInstantMessage {
AddAgentToSession(toAgentID, GroupID, msg); if (m_debugEnabled) m_log.DebugFormat("[Groups.Messaging]: Sending chatterbox invite instant message");
else
client.SendInstantMessage(msg); // 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>();
eq.ChatterboxInvitation(
GroupID
, groupInfo.GroupName
, new UUID(msg.fromAgentID)
, msg.message
, new UUID(msg.toAgentID)
, 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.ChatterBoxSessionAgentListUpdates(
new UUID(GroupID)
, new UUID(msg.fromAgentID)
, new UUID(msg.toAgentID)
, false //canVoiceChat
, false //isModerator
, false //text mute
);
}
} }
} }
else else if (!m_groupData.hasAgentDroppedGroupChatSession(AgentID.ToString(), GroupID))
{ {
m_log.WarnFormat("[Groups.Messaging]: Received a message over the grid for a client that isn't here: {0}", msg.toAgentID); // 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)
{
// Deliver locally, directly
if (m_debugEnabled) m_log.DebugFormat("[Groups.Messaging]: Delivering to {0} locally", client.Name);
client.SendInstantMessage(msg);
}
else
{
m_log.WarnFormat("[Groups.Messaging]: Received a message over the grid for a client that isn't here: {0}", msg.toAgentID);
}
} }
break; break;
@ -585,52 +444,6 @@ namespace OpenSim.Groups
} }
} }
private void AddAgentToSession(UUID AgentID, UUID GroupID, GridInstantMessage msg)
{
// Agent not in session and hasn't dropped from session
// Add them to the session for now, and Invite them
AgentInvitedToGroupChatSession(AgentID.ToString(), GroupID);
IClientAPI activeClient = GetActiveClient(AgentID);
if (activeClient != null)
{
GroupRecord groupInfo = m_groupData.GetGroupRecord(UUID.Zero.ToString(), GroupID, null);
if (groupInfo != null)
{
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)
);
var update = new GroupChatListAgentUpdateData(AgentID);
var updates = new List<GroupChatListAgentUpdateData> { update };
eq.ChatterBoxSessionAgentListUpdates(GroupID, new UUID(msg.toAgentID), updates);
}
}
}
}
#endregion #endregion
@ -653,20 +466,22 @@ namespace OpenSim.Groups
UUID AgentID = new UUID(im.fromAgentID); UUID AgentID = new UUID(im.fromAgentID);
GroupRecord groupInfo = m_groupData.GetGroupRecord(UUID.Zero.ToString(), GroupID, null); GroupRecord groupInfo = m_groupData.GetGroupRecord(UUID.Zero.ToString(), GroupID, null);
if (groupInfo != null) if (groupInfo != null)
{ {
AgentInvitedToGroupChatSession(AgentID.ToString(), GroupID); m_groupData.AgentInvitedToGroupChatSession(AgentID.ToString(), GroupID);
ChatterBoxSessionStartReplyViaCaps(remoteClient, groupInfo.GroupName, GroupID); ChatterBoxSessionStartReplyViaCaps(remoteClient, groupInfo.GroupName, GroupID);
IEventQueue queue = remoteClient.Scene.RequestModuleInterface<IEventQueue>(); IEventQueue queue = remoteClient.Scene.RequestModuleInterface<IEventQueue>();
if (queue != null) queue.ChatterBoxSessionAgentListUpdates(
{ GroupID
var update = new GroupChatListAgentUpdateData(AgentID); , AgentID
var updates = new List<GroupChatListAgentUpdateData> { update }; , new UUID(im.toAgentID)
queue.ChatterBoxSessionAgentListUpdates(GroupID, remoteClient.AgentId, updates); , false //canVoiceChat
} , false //isModerator
, false //text mute
);
} }
} }
@ -676,11 +491,11 @@ namespace OpenSim.Groups
UUID GroupID = new UUID(im.imSessionID); UUID GroupID = new UUID(im.imSessionID);
UUID AgentID = new UUID(im.fromAgentID); 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()); 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 //If this agent is sending a message, then they want to be in the session
AgentInvitedToGroupChatSession(AgentID.ToString(), GroupID); m_groupData.AgentInvitedToGroupChatSession(AgentID.ToString(), GroupID);
SendMessageToGroup(im, GroupID); SendMessageToGroup(im, GroupID);
} }
@ -708,7 +523,11 @@ namespace OpenSim.Groups
bodyMap.Add("session_info", sessionMap); bodyMap.Add("session_info", sessionMap);
IEventQueue queue = remoteClient.Scene.RequestModuleInterface<IEventQueue>(); 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) private void DebugGridInstantMessage(GridInstantMessage im)
@ -747,12 +566,12 @@ namespace OpenSim.Groups
{ {
if (!sp.IsChildAgent) if (!sp.IsChildAgent)
{ {
if (m_debugEnabled) m_log.DebugFormat("[Groups.Messaging]: Found root agent for client : {0}", sp.ControllingClient.Name); if (m_debugEnabled) m_log.WarnFormat("[Groups.Messaging]: Found root agent for client : {0}", sp.ControllingClient.Name);
return sp.ControllingClient; return sp.ControllingClient;
} }
else else
{ {
if (m_debugEnabled) m_log.DebugFormat("[Groups.Messaging]: Found child agent for client : {0}", sp.ControllingClient.Name); if (m_debugEnabled) m_log.WarnFormat("[Groups.Messaging]: Found child agent for client : {0}", sp.ControllingClient.Name);
child = sp.ControllingClient; child = sp.ControllingClient;
} }
} }
@ -771,71 +590,5 @@ namespace OpenSim.Groups
} }
#endregion #endregion
#region GroupSessionTracking
public void ResetAgentGroupChatSessions(string agentID)
{
foreach (List<string> agentList in m_groupsAgentsDroppedFromChatSession.Values)
agentList.Remove(agentID);
foreach (List<string> agentList in m_groupsAgentsInvitedToChatSession.Values)
agentList.Remove(agentID);
}
public bool hasAgentBeenInvitedToGroupChatSession(string agentID, UUID groupID)
{
// If we're tracking this group, and we can find them in the tracking, then they've been invited
return m_groupsAgentsInvitedToChatSession.ContainsKey(groupID)
&& m_groupsAgentsInvitedToChatSession[groupID].Contains(agentID);
}
public bool hasAgentDroppedGroupChatSession(string agentID, UUID groupID)
{
// If we're tracking drops for this group,
// and we find them, well... then they've dropped
return m_groupsAgentsDroppedFromChatSession.ContainsKey(groupID)
&& m_groupsAgentsDroppedFromChatSession[groupID].Contains(agentID);
}
public void AgentDroppedFromGroupChatSession(string agentID, UUID groupID)
{
if (m_groupsAgentsDroppedFromChatSession.ContainsKey(groupID))
{
// If not in dropped list, add
if (!m_groupsAgentsDroppedFromChatSession[groupID].Contains(agentID))
{
m_groupsAgentsDroppedFromChatSession[groupID].Add(agentID);
}
}
}
public void AgentInvitedToGroupChatSession(string agentID, UUID groupID)
{
// Add Session Status if it doesn't exist for this session
CreateGroupChatSessionTracking(groupID);
// If nessesary, remove from dropped list
if (m_groupsAgentsDroppedFromChatSession[groupID].Contains(agentID))
{
m_groupsAgentsDroppedFromChatSession[groupID].Remove(agentID);
}
// Add to invited
if (!m_groupsAgentsInvitedToChatSession[groupID].Contains(agentID))
m_groupsAgentsInvitedToChatSession[groupID].Add(agentID);
}
private void CreateGroupChatSessionTracking(UUID groupID)
{
if (!m_groupsAgentsDroppedFromChatSession.ContainsKey(groupID))
{
m_groupsAgentsDroppedFromChatSession.Add(groupID, new List<string>());
m_groupsAgentsInvitedToChatSession.Add(groupID, new List<string>());
}
}
#endregion
} }
} }

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

File diff suppressed because it is too large Load Diff

View File

@ -101,7 +101,7 @@ namespace OpenSim.Groups
Dictionary<string, object> sendData = new Dictionary<string, object>(); Dictionary<string, object> sendData = new Dictionary<string, object>();
if (GroupID != UUID.Zero) if (GroupID != UUID.Zero)
sendData["GroupID"] = GroupID.ToString(); sendData["GroupID"] = GroupID.ToString();
if (!string.IsNullOrEmpty(GroupName)) if (GroupName != null && GroupName != string.Empty)
sendData["Name"] = GroupsDataUtils.Sanitize(GroupName); sendData["Name"] = GroupsDataUtils.Sanitize(GroupName);
sendData["RequestingAgentID"] = RequestingAgentID; sendData["RequestingAgentID"] = RequestingAgentID;
@ -275,7 +275,7 @@ namespace OpenSim.Groups
//m_log.DebugFormat("[XXX]: reply was {0}", reply); //m_log.DebugFormat("[XXX]: reply was {0}", reply);
if (string.IsNullOrEmpty(reply)) if (reply == string.Empty || reply == null)
return null; return null;
Dictionary<string, object> replyData = ServerUtils.ParseXmlResponse( Dictionary<string, object> replyData = ServerUtils.ParseXmlResponse(

View File

@ -1,4 +1,4 @@
/* /*
* Copyright (c) Contributors, http://opensimulator.org/ * Copyright (c) Contributors, http://opensimulator.org/
* See CONTRIBUTORS.TXT for a full list of copyright holders. * See CONTRIBUTORS.TXT for a full list of copyright holders.
* *
@ -32,7 +32,6 @@ using System.Reflection;
using System.Text; using System.Text;
using OpenSim.Framework; using OpenSim.Framework;
using OpenSim.Framework.Monitoring;
using OpenSim.Framework.Servers; using OpenSim.Framework.Servers;
using OpenSim.Region.Framework.Scenes; using OpenSim.Region.Framework.Scenes;
using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.Framework.Interfaces;
@ -103,7 +102,7 @@ namespace OpenSim.Groups
if (!m_Enabled) if (!m_Enabled)
return; 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); scene.RegisterModuleInterface<IGroupsServicesConnector>(this);
m_Scenes.Add(scene); m_Scenes.Add(scene);
@ -135,7 +134,7 @@ namespace OpenSim.Groups
{ {
m_LocalGroupsConnector = new GroupsServiceLocalConnectorModule(m_Config, m_UserManagement); m_LocalGroupsConnector = new GroupsServiceLocalConnectorModule(m_Config, m_UserManagement);
// Also, if local, create the endpoint for the HGGroupsService // 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>()); scene.RequestModuleInterface<IOfflineIMService>(), scene.RequestModuleInterface<IUserAccountService>());
} }
@ -170,7 +169,7 @@ namespace OpenSim.Groups
if (sp is ScenePresence && ((ScenePresence)sp).PresenceType != PresenceType.Npc) if (sp is ScenePresence && ((ScenePresence)sp).PresenceType != PresenceType.Npc)
{ {
AgentCircuitData aCircuit = ((ScenePresence)sp).Scene.AuthenticateHandler.GetAgentCircuitData(client.AgentId); 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) m_OfflineIM != null && m_Messaging != null)
{ {
List<GridInstantMessage> ims = m_OfflineIM.GetMessages(aCircuit.AgentID); List<GridInstantMessage> ims = m_OfflineIM.GetMessages(aCircuit.AgentID);
@ -184,12 +183,12 @@ namespace OpenSim.Groups
#region IGroupsServicesConnector #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) bool allowPublish, bool maturePublish, UUID founderID, out string reason)
{ {
reason = string.Empty; reason = string.Empty;
if (m_UserManagement.IsLocalGridUser(RequestingAgentID)) 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); membershipFee, openEnrollment, allowPublish, maturePublish, founderID, out reason);
else else
{ {
@ -198,14 +197,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) bool openEnrollment, bool allowPublish, bool maturePublish, out string reason)
{ {
reason = string.Empty; reason = string.Empty;
string url = string.Empty; string url = string.Empty;
string name = string.Empty; string name = string.Empty;
if (IsLocal(groupID, out url, out name)) 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); openEnrollment, allowPublish, maturePublish, out reason);
else else
{ {
@ -246,19 +245,16 @@ namespace OpenSim.Groups
return null; 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) public List<GroupMembersData> GetGroupMembers(string RequestingAgentID, UUID GroupID)
{ {
string url = string.Empty, gname = string.Empty; string url = string.Empty, gname = string.Empty;
if (IsLocal(GroupID, out url, out gname)) if (IsLocal(GroupID, out url, out gname))
{ return m_LocalGroupsConnector.GetGroupMembers(AgentUUI(RequestingAgentID), GroupID);
string agentID = AgentUUI(RequestingAgentID);
return m_LocalGroupsConnector.GetGroupMembers(agentID, GroupID);
}
else if (!string.IsNullOrEmpty(url)) else if (!string.IsNullOrEmpty(url))
{ {
ExtendedGroupMembershipData membership = m_LocalGroupsConnector.GetAgentGroupMembership(RequestingAgentID, RequestingAgentID, GroupID); ExtendedGroupMembershipData membership = m_LocalGroupsConnector.GetAgentGroupMembership(RequestingAgentID, RequestingAgentID, GroupID);
@ -374,7 +370,7 @@ namespace OpenSim.Groups
} }
} }
return new List<GroupRoleMembersData>(); return new List<GroupRoleMembersData>();
} }
@ -400,21 +396,17 @@ namespace OpenSim.Groups
if (success) if (success)
{ {
// Here we always return true. The user has been added to the local group,
// independent of whether the remote operation succeeds or not
url = m_UserManagement.GetUserServerURL(uid, "GroupsServerURI"); url = m_UserManagement.GetUserServerURL(uid, "GroupsServerURI");
if (url == string.Empty) if (url == string.Empty)
{ {
reason = "You don't have an accessible groups server in your home world. You membership to this group in only within this grid."; reason = "User doesn't have a groups server";
return true; return false;
} }
GroupsServiceHGConnector c = GetConnector(url); GroupsServiceHGConnector c = GetConnector(url);
if (c != null) if (c != null)
c.CreateProxy(AgentUUI(RequestingAgentID), AgentID, token, GroupID, m_LocalGroupsServiceLocation, name, out reason); return c.CreateProxy(AgentUUI(RequestingAgentID), AgentID, token, GroupID, m_LocalGroupsServiceLocation, name, out reason);
return true;
} }
return false;
} }
} }
else if (m_UserManagement.IsLocalGridUser(uid)) // local user else if (m_UserManagement.IsLocalGridUser(uid)) // local user
@ -561,7 +553,7 @@ namespace OpenSim.Groups
// so we have the list of urls to send the notice to // so we have the list of urls to send the notice to
// this may take a long time... // this may take a long time...
WorkManager.RunInThread(delegate Util.FireAndForget(delegate
{ {
foreach (string u in urls) foreach (string u in urls)
{ {
@ -572,7 +564,7 @@ namespace OpenSim.Groups
hasAttachment, attType, attName, attItemID, AgentUUIForOutside(attOwnerID)); hasAttachment, attType, attName, attItemID, AgentUUIForOutside(attOwnerID));
} }
} }
}, null, string.Format("AddGroupNotice (agent {0}, group {1})", RequestingAgentID, groupID)); });
return true; return true;
} }
@ -598,6 +590,28 @@ namespace OpenSim.Groups
return m_LocalGroupsConnector.GetGroupNotices(AgentUUI(RequestingAgentID), GroupID); return m_LocalGroupsConnector.GetGroupNotices(AgentUUI(RequestingAgentID), GroupID);
} }
public void ResetAgentGroupChatSessions(string agentID)
{
}
public bool hasAgentBeenInvitedToGroupChatSession(string agentID, UUID groupID)
{
return false;
}
public bool hasAgentDroppedGroupChatSession(string agentID, UUID groupID)
{
return false;
}
public void AgentDroppedFromGroupChatSession(string agentID, UUID groupID)
{
}
public void AgentInvitedToGroupChatSession(string agentID, UUID groupID)
{
}
#endregion #endregion
#region hypergrid groups #region hypergrid groups
@ -605,8 +619,14 @@ namespace OpenSim.Groups
private string AgentUUI(string AgentIDStr) private string AgentUUI(string AgentIDStr)
{ {
UUID AgentID = UUID.Zero; UUID AgentID = UUID.Zero;
if (!UUID.TryParse(AgentIDStr, out AgentID) || AgentID == UUID.Zero) try
return UUID.Zero.ToString(); {
AgentID = new UUID(AgentIDStr);
}
catch (FormatException)
{
return AgentID.ToString();
}
if (m_UserManagement.IsLocalGridUser(AgentID)) if (m_UserManagement.IsLocalGridUser(AgentID))
return AgentID.ToString(); return AgentID.ToString();
@ -618,20 +638,23 @@ namespace OpenSim.Groups
if (agent != null) if (agent != null)
break; break;
} }
if (agent != null) if (agent == null) // oops
return Util.ProduceUserUniversalIdentifier(agent); return AgentID.ToString();
// we don't know anything about this foreign user
// try asking the user management module, which may know more
return m_UserManagement.GetUserUUI(AgentID);
return Util.ProduceUserUniversalIdentifier(agent);
} }
private string AgentUUIForOutside(string AgentIDStr) private string AgentUUIForOutside(string AgentIDStr)
{ {
UUID AgentID = UUID.Zero; UUID AgentID = UUID.Zero;
if (!UUID.TryParse(AgentIDStr, out AgentID) || AgentID == UUID.Zero) try
return UUID.Zero.ToString(); {
AgentID = new UUID(AgentIDStr);
}
catch (FormatException)
{
return AgentID.ToString();
}
AgentCircuitData agent = null; AgentCircuitData agent = null;
foreach (Scene scene in m_Scenes) foreach (Scene scene in m_Scenes)
@ -652,7 +675,7 @@ namespace OpenSim.Groups
string url = string.Empty, first = string.Empty, last = string.Empty, tmp = string.Empty; 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)) if (Util.ParseUniversalUserIdentifier(uID, out userID, out url, out first, out last, out tmp))
m_UserManagement.AddUser(userID, first, last, url); m_UserManagement.AddUser(userID, first, last, url);
return userID; return userID;
} }

View File

@ -1,4 +1,4 @@
/* /*
* Copyright (c) Contributors, http://opensimulator.org/ * Copyright (c) Contributors, http://opensimulator.org/
* See CONTRIBUTORS.TXT for a full list of copyright holders. * See CONTRIBUTORS.TXT for a full list of copyright holders.
* *
@ -64,8 +64,8 @@ namespace OpenSim.Groups
m_log.DebugFormat("[Groups.RobustHGConnector]: Starting with config name {0}", m_ConfigName); m_log.DebugFormat("[Groups.RobustHGConnector]: Starting with config name {0}", m_ConfigName);
string homeURI = Util.GetConfigVarFromSections<string>(config, "HomeURI", string homeURI = Util.GetConfigVarFromSections<string>(config, "HomeURI",
new string[] { "Startup", "Hypergrid", m_ConfigName}, string.Empty); new string[] { "Startup", "Hypergrid", m_ConfigName}, string.Empty);
if (homeURI == string.Empty) if (homeURI == string.Empty)
throw new Exception(String.Format("[Groups.RobustHGConnector]: please provide the HomeURI [Startup] or in section {0}", m_ConfigName)); 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, protected override byte[] ProcessRequest(string path, Stream requestData,
IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
{ {
string body; StreamReader sr = new StreamReader(requestData);
using(StreamReader sr = new StreamReader(requestData)) string body = sr.ReadToEnd();
body = sr.ReadToEnd(); sr.Close();
body = body.Trim(); body = body.Trim();
//m_log.DebugFormat("[XXX]: query String: {0}", body); //m_log.DebugFormat("[XXX]: query String: {0}", body);
@ -159,7 +158,7 @@ namespace OpenSim.Groups
} }
catch (Exception e) catch (Exception e)
{ {
m_log.Error(string.Format("[Groups.RobustHGConnector]: Exception {0} ", e.Message), e); m_log.DebugFormat("[Groups.RobustHGConnector]: Exception {0}", e.StackTrace);
} }
return FailureResult(); return FailureResult();
@ -210,13 +209,11 @@ namespace OpenSim.Groups
string agentID = request["AgentID"].ToString(); string agentID = request["AgentID"].ToString();
string token = request["AccessToken"].ToString(); string token = request["AccessToken"].ToString();
if (!m_GroupsService.RemoveAgentFromGroup(agentID, agentID, groupID, token)) m_GroupsService.RemoveAgentFromGroup(agentID, agentID, groupID, token);
NullResult(result, "Internal error");
else
result["RESULT"] = "true";
} }
//m_log.DebugFormat("[XXX]: resp string: {0}", xmlString); //m_log.DebugFormat("[XXX]: resp string: {0}", xmlString);
result["RESULT"] = "true";
return Util.UTF8NoBomEncoding.GetBytes(ServerUtils.BuildXmlResponse(result)); return Util.UTF8NoBomEncoding.GetBytes(ServerUtils.BuildXmlResponse(result));
} }

View File

@ -34,12 +34,12 @@ namespace OpenSim.Groups
{ {
public interface IGroupsServicesConnector 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 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); bool openEnrollment, bool allowPublish, bool maturePublish, out string reason);
ExtendedGroupRecord GetGroupRecord(string RequestingAgentID, UUID GroupID, string GroupName); 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); 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); 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. /// If the user is a member of the group then the data structure is returned. If not, then null is returned.
/// </returns> /// </returns>
ExtendedGroupMembershipData GetAgentGroupMembership(string RequestingAgentID, string AgentID, UUID GroupID); ExtendedGroupMembershipData GetAgentGroupMembership(string RequestingAgentID, string AgentID, UUID GroupID);
/// <summary> /// <summary>
/// Get information about the groups to which a user belongs. /// Get information about the groups to which a user belongs.
/// </summary> /// </summary>
@ -87,11 +87,17 @@ namespace OpenSim.Groups
/// </returns> /// </returns>
List<GroupMembershipData> GetAgentGroupMemberships(string RequestingAgentID, string AgentID); 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); bool hasAttachment, byte attType, string attName, UUID attItemID, string attOwnerID);
GroupNoticeInfo GetGroupNotice(string RequestingAgentID, UUID noticeID); GroupNoticeInfo GetGroupNotice(string RequestingAgentID, UUID noticeID);
List<ExtendedGroupNoticeData> GetGroupNotices(string RequestingAgentID, UUID GroupID); List<ExtendedGroupNoticeData> GetGroupNotices(string RequestingAgentID, UUID GroupID);
void ResetAgentGroupChatSessions(string agentID);
bool hasAgentBeenInvitedToGroupChatSession(string agentID, UUID groupID);
bool hasAgentDroppedGroupChatSession(string agentID, UUID groupID);
void AgentDroppedFromGroupChatSession(string agentID, UUID groupID);
void AgentInvitedToGroupChatSession(string agentID, UUID groupID);
} }
public class GroupInviteInfo public class GroupInviteInfo

View File

@ -34,7 +34,6 @@ using System.Text;
using OpenSim.Framework; using OpenSim.Framework;
using OpenSim.Region.Framework.Scenes; using OpenSim.Region.Framework.Scenes;
using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.Framework.Interfaces;
using OpenSim.Services.Interfaces;
using OpenMetaverse; using OpenMetaverse;
using Mono.Addins; using Mono.Addins;
@ -108,7 +107,7 @@ namespace OpenSim.Groups
if (!m_Enabled) if (!m_Enabled)
return; 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); scene.RegisterModuleInterface<IGroupsServicesConnector>(this);
m_Scenes.Add(scene); m_Scenes.Add(scene);
} }
@ -146,16 +145,16 @@ namespace OpenSim.Groups
#region IGroupsServicesConnector #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) bool allowPublish, bool maturePublish, UUID founderID, out string reason)
{ {
m_log.DebugFormat("[Groups]: Creating group {0}", name); m_log.DebugFormat("[Groups]: Creating group {0}", name);
reason = string.Empty; 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); 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) bool openEnrollment, bool allowPublish, bool maturePublish, out string reason)
{ {
reason = string.Empty; reason = string.Empty;
@ -173,9 +172,9 @@ namespace OpenSim.Groups
return null; 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) 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, 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) 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); hasAttachment, attType, attName, attItemID, attOwnerID);
} }
@ -321,6 +320,28 @@ namespace OpenSim.Groups
return m_GroupsService.GetGroupNotices(RequestingAgentID, GroupID); return m_GroupsService.GetGroupNotices(RequestingAgentID, GroupID);
} }
public void ResetAgentGroupChatSessions(string agentID)
{
}
public bool hasAgentBeenInvitedToGroupChatSession(string agentID, UUID groupID)
{
return false;
}
public bool hasAgentDroppedGroupChatSession(string agentID, UUID groupID)
{
return false;
}
public void AgentDroppedFromGroupChatSession(string agentID, UUID groupID)
{
}
public void AgentInvitedToGroupChatSession(string agentID, UUID groupID)
{
}
#endregion #endregion
} }
} }

View File

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

View File

@ -32,12 +32,10 @@ using System.Reflection;
using System.Text; using System.Text;
using OpenSim.Framework; using OpenSim.Framework;
using OpenSim.Framework.ServiceAuth;
using OpenSim.Server.Base; using OpenSim.Server.Base;
using OpenMetaverse; using OpenMetaverse;
using log4net; using log4net;
using Nini.Config;
namespace OpenSim.Groups namespace OpenSim.Groups
{ {
@ -46,33 +44,15 @@ namespace OpenSim.Groups
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_ServerURI; private string m_ServerURI;
private IServiceAuth m_Auth;
private object m_Lock = new object(); private object m_Lock = new object();
public GroupsServiceRemoteConnector(IConfigSource config) public GroupsServiceRemoteConnector(string url)
{ {
IConfig groupsConfig = config.Configs["Groups"];
string url = groupsConfig.GetString("GroupsServerURI", string.Empty);
if (!Uri.IsWellFormedUriString(url, UriKind.Absolute))
throw new Exception(string.Format("[Groups.RemoteConnector]: Malformed groups server URL {0}. Fix it or disable the Groups feature.", url));
m_ServerURI = url; m_ServerURI = url;
if (!m_ServerURI.EndsWith("/")) if (!m_ServerURI.EndsWith("/"))
m_ServerURI += "/"; m_ServerURI += "/";
/// This is from BaseServiceConnector m_log.DebugFormat("[Groups.RemoteConnector]: Groups server at {0}", m_ServerURI);
string authType = Util.GetConfigVarFromSections<string>(config, "AuthType", new string[] { "Network", "Groups" }, "None");
switch (authType)
{
case "BasicHttpAuthentication":
m_Auth = new BasicHttpAuthentication(config, "Groups");
break;
}
///
m_log.DebugFormat("[Groups.RemoteConnector]: Groups server at {0}, authentication {1}",
m_ServerURI, (m_Auth == null ? "None" : m_Auth.GetType().ToString()));
} }
public ExtendedGroupRecord CreateGroup(string RequestingAgentID, string name, string charter, bool showInList, UUID insigniaID, int membershipFee, bool openEnrollment, public ExtendedGroupRecord CreateGroup(string RequestingAgentID, string name, string charter, bool showInList, UUID insigniaID, int membershipFee, bool openEnrollment,
@ -126,7 +106,7 @@ namespace OpenSim.Groups
sendData["OP"] = "UPDATE"; sendData["OP"] = "UPDATE";
Dictionary<string, object> ret = MakeRequest("PUTGROUP", sendData); Dictionary<string, object> ret = MakeRequest("PUTGROUP", sendData);
if (ret == null || (ret != null && (!ret.ContainsKey("RESULT") || ret["RESULT"].ToString() == "NULL"))) if (ret == null || (ret != null && ret["RESULT"].ToString() == "NULL"))
return null; return null;
return GroupsDataUtils.GroupRecord((Dictionary<string, object>)ret["RESULT"]); return GroupsDataUtils.GroupRecord((Dictionary<string, object>)ret["RESULT"]);
@ -140,49 +120,19 @@ namespace OpenSim.Groups
Dictionary<string, object> sendData = new Dictionary<string, object>(); Dictionary<string, object> sendData = new Dictionary<string, object>();
if (GroupID != UUID.Zero) if (GroupID != UUID.Zero)
sendData["GroupID"] = GroupID.ToString(); sendData["GroupID"] = GroupID.ToString();
if (!string.IsNullOrEmpty(GroupName)) if (GroupName != null && GroupName != string.Empty)
sendData["Name"] = GroupsDataUtils.Sanitize(GroupName); sendData["Name"] = GroupsDataUtils.Sanitize(GroupName);
sendData["RequestingAgentID"] = RequestingAgentID; sendData["RequestingAgentID"] = RequestingAgentID;
Dictionary<string, object> ret = MakeRequest("GETGROUP", sendData); Dictionary<string, object> ret = MakeRequest("GETGROUP", sendData);
if (ret == null || (ret != null && (!ret.ContainsKey("RESULT") || ret["RESULT"].ToString() == "NULL"))) if (ret == null || (ret != null && ret["RESULT"].ToString() == "NULL"))
return null; return null;
return GroupsDataUtils.GroupRecord((Dictionary<string, object>)ret["RESULT"]); return GroupsDataUtils.GroupRecord((Dictionary<string, object>)ret["RESULT"]);
} }
public List<DirGroupsReplyData> FindGroups(string RequestingAgentIDstr, string query)
{
List<DirGroupsReplyData> hits = new List<DirGroupsReplyData>();
if (string.IsNullOrEmpty(query))
return hits;
Dictionary<string, object> sendData = new Dictionary<string, object>();
sendData["Query"] = query;
sendData["RequestingAgentID"] = RequestingAgentIDstr;
Dictionary<string, object> ret = MakeRequest("FINDGROUPS", sendData);
if (ret == null)
return hits;
if (!ret.ContainsKey("RESULT"))
return hits;
if (ret["RESULT"].ToString() == "NULL")
return hits;
foreach (object v in ((Dictionary<string, object>)ret["RESULT"]).Values)
{
DirGroupsReplyData m = GroupsDataUtils.DirGroupsReplyData((Dictionary<string, object>)v);
hits.Add(m);
}
return hits;
}
public GroupMembershipData AddAgentToGroup(string RequestingAgentID, string AgentID, UUID GroupID, UUID RoleID, string token, out string reason) public GroupMembershipData AddAgentToGroup(string RequestingAgentID, string AgentID, UUID GroupID, UUID RoleID, string token, out string reason)
{ {
reason = string.Empty; reason = string.Empty;
@ -276,7 +226,6 @@ namespace OpenSim.Groups
Dictionary<string, object> sendData = new Dictionary<string, object>(); Dictionary<string, object> sendData = new Dictionary<string, object>();
sendData["GroupID"] = GroupID.ToString(); sendData["GroupID"] = GroupID.ToString();
sendData["RequestingAgentID"] = RequestingAgentID; sendData["RequestingAgentID"] = RequestingAgentID;
Dictionary<string, object> ret = MakeRequest("GETGROUPMEMBERS", sendData); Dictionary<string, object> ret = MakeRequest("GETGROUPMEMBERS", sendData);
if (ret == null) if (ret == null)
@ -287,7 +236,6 @@ namespace OpenSim.Groups
if (ret["RESULT"].ToString() == "NULL") if (ret["RESULT"].ToString() == "NULL")
return members; return members;
foreach (object v in ((Dictionary<string, object>)ret["RESULT"]).Values) foreach (object v in ((Dictionary<string, object>)ret["RESULT"]).Values)
{ {
ExtendedGroupMembersData m = GroupsDataUtils.GroupMembersData((Dictionary<string, object>)v); ExtendedGroupMembersData m = GroupsDataUtils.GroupMembersData((Dictionary<string, object>)v);
@ -378,7 +326,6 @@ namespace OpenSim.Groups
if (ret["RESULT"].ToString() == "NULL") if (ret["RESULT"].ToString() == "NULL")
return roles; return roles;
foreach (object v in ((Dictionary<string, object>)ret["RESULT"]).Values) foreach (object v in ((Dictionary<string, object>)ret["RESULT"]).Values)
{ {
GroupRolesData m = GroupsDataUtils.GroupRolesData((Dictionary<string, object>)v); GroupRolesData m = GroupsDataUtils.GroupRolesData((Dictionary<string, object>)v);
@ -679,8 +626,7 @@ namespace OpenSim.Groups
lock (m_Lock) lock (m_Lock)
reply = SynchronousRestFormsRequester.MakeRequest("POST", reply = SynchronousRestFormsRequester.MakeRequest("POST",
m_ServerURI + "groups", m_ServerURI + "groups",
ServerUtils.BuildQueryString(sendData), ServerUtils.BuildQueryString(sendData));
m_Auth);
if (reply == string.Empty) if (reply == string.Empty)
return null; return null;
@ -690,7 +636,7 @@ namespace OpenSim.Groups
return replyData; return replyData;
} }
#endregion #endregion
} }
} }

View File

@ -36,7 +36,6 @@ using OpenSim.Framework;
using OpenSim.Region.Framework.Scenes; using OpenSim.Region.Framework.Scenes;
using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.Framework.Interfaces;
using OpenSim.Server.Base; using OpenSim.Server.Base;
using OpenSim.Services.Interfaces;
using OpenMetaverse; using OpenMetaverse;
using Mono.Addins; using Mono.Addins;
@ -73,7 +72,12 @@ namespace OpenSim.Groups
private void Init(IConfigSource config) private void Init(IConfigSource config)
{ {
m_GroupsService = new GroupsServiceRemoteConnector(config); IConfig groupsConfig = config.Configs["Groups"];
string url = groupsConfig.GetString("GroupsServerURI", string.Empty);
if (!Uri.IsWellFormedUriString(url, UriKind.Absolute))
throw new Exception(string.Format("[Groups.RemoteConnector]: Malformed groups server URL {0}. Fix it or disable the Groups feature.", url));
m_GroupsService = new GroupsServiceRemoteConnector(url);
m_Scenes = new List<Scene>(); m_Scenes = new List<Scene>();
} }
@ -113,7 +117,7 @@ namespace OpenSim.Groups
if (!m_Enabled) if (!m_Enabled)
return; 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); scene.RegisterModuleInterface<IGroupsServicesConnector>(this);
m_Scenes.Add(scene); m_Scenes.Add(scene);
} }
@ -151,7 +155,7 @@ namespace OpenSim.Groups
#region IGroupsServicesConnector #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) bool allowPublish, bool maturePublish, UUID founderID, out string reason)
{ {
m_log.DebugFormat("[Groups.RemoteConnector]: Creating group {0}", name); m_log.DebugFormat("[Groups.RemoteConnector]: Creating group {0}", name);
@ -167,7 +171,7 @@ namespace OpenSim.Groups
return groupID; 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) bool openEnrollment, bool allowPublish, bool maturePublish, out string reason)
{ {
string r = string.Empty; string r = string.Empty;
@ -186,16 +190,16 @@ namespace OpenSim.Groups
if (GroupID == UUID.Zero && (GroupName == null || GroupName != null && GroupName == string.Empty)) if (GroupID == UUID.Zero && (GroupName == null || GroupName != null && GroupName == string.Empty))
return null; return null;
return m_CacheWrapper.GetGroupRecord(RequestingAgentID,GroupID,GroupName, delegate return m_CacheWrapper.GetGroupRecord(RequestingAgentID,GroupID,GroupName, delegate
{ {
return m_GroupsService.GetGroupRecord(RequestingAgentID, GroupID, GroupName); return m_GroupsService.GetGroupRecord(RequestingAgentID, GroupID, GroupName);
}); });
} }
public List<DirGroupsReplyData> FindGroups(string RequestingAgentIDstr, string search) public List<DirGroupsReplyData> FindGroups(string RequestingAgentID, string search)
{ {
// TODO! // TODO!
return m_GroupsService.FindGroups(RequestingAgentIDstr, search); return new List<DirGroupsReplyData>();
} }
public bool AddAgentToGroup(string RequestingAgentID, string AgentID, UUID GroupID, UUID RoleID, string token, out string reason) public bool AddAgentToGroup(string RequestingAgentID, string AgentID, UUID GroupID, UUID RoleID, string token, out string reason)
@ -362,7 +366,7 @@ namespace OpenSim.Groups
m_GroupsService.RemoveAgentToGroupInvite(RequestingAgentID, inviteID); 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) bool hasAttachment, byte attType, string attName, UUID attItemID, string attOwnerID)
{ {
GroupNoticeInfo notice = new GroupNoticeInfo(); GroupNoticeInfo notice = new GroupNoticeInfo();
@ -402,6 +406,28 @@ namespace OpenSim.Groups
}); });
} }
public void ResetAgentGroupChatSessions(string agentID)
{
}
public bool hasAgentBeenInvitedToGroupChatSession(string agentID, UUID groupID)
{
return false;
}
public bool hasAgentDroppedGroupChatSession(string agentID, UUID groupID)
{
return false;
}
public void AgentDroppedFromGroupChatSession(string agentID, UUID groupID)
{
}
public void AgentInvitedToGroupChatSession(string agentID, UUID groupID)
{
}
#endregion #endregion
} }

View File

@ -36,7 +36,6 @@ using OpenSim.Framework;
using OpenSim.Server.Base; using OpenSim.Server.Base;
using OpenSim.Services.Interfaces; using OpenSim.Services.Interfaces;
using OpenSim.Framework.Servers.HttpServer; using OpenSim.Framework.Servers.HttpServer;
using OpenSim.Framework.ServiceAuth;
using OpenSim.Server.Handlers.Base; using OpenSim.Server.Handlers.Base;
using log4net; using log4net;
using OpenMetaverse; using OpenMetaverse;
@ -53,26 +52,14 @@ namespace OpenSim.Groups
public GroupsServiceRobustConnector(IConfigSource config, IHttpServer server, string configName) : public GroupsServiceRobustConnector(IConfigSource config, IHttpServer server, string configName) :
base(config, server, configName) base(config, server, configName)
{ {
string key = string.Empty;
if (configName != String.Empty) if (configName != String.Empty)
m_ConfigName = configName; m_ConfigName = configName;
m_log.DebugFormat("[Groups.RobustConnector]: Starting with config name {0}", m_ConfigName); m_log.DebugFormat("[Groups.RobustConnector]: Starting with config name {0}", m_ConfigName);
IConfig groupsConfig = config.Configs[m_ConfigName];
if (groupsConfig != null)
{
key = groupsConfig.GetString("SecretKey", string.Empty);
m_log.DebugFormat("[Groups.RobustConnector]: Starting with secret key {0}", key);
}
// else
// m_log.DebugFormat("[Groups.RobustConnector]: Unable to find {0} section in configuration", m_ConfigName);
m_GroupsService = new GroupsService(config); m_GroupsService = new GroupsService(config);
IServiceAuth auth = ServiceAuth.Create(config, m_ConfigName); server.AddStreamHandler(new GroupsServicePostHandler(m_GroupsService));
server.AddStreamHandler(new GroupsServicePostHandler(m_GroupsService, auth));
} }
} }
@ -82,8 +69,8 @@ namespace OpenSim.Groups
private GroupsService m_GroupsService; private GroupsService m_GroupsService;
public GroupsServicePostHandler(GroupsService service, IServiceAuth auth) : public GroupsServicePostHandler(GroupsService service) :
base("POST", "/groups", auth) base("POST", "/groups")
{ {
m_GroupsService = service; m_GroupsService = service;
} }
@ -91,10 +78,9 @@ namespace OpenSim.Groups
protected override byte[] ProcessRequest(string path, Stream requestData, protected override byte[] ProcessRequest(string path, Stream requestData,
IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
{ {
string body; StreamReader sr = new StreamReader(requestData);
using(StreamReader sr = new StreamReader(requestData)) string body = sr.ReadToEnd();
body = sr.ReadToEnd(); sr.Close();
body = body.Trim(); body = body.Trim();
//m_log.DebugFormat("[XXX]: query String: {0}", body); //m_log.DebugFormat("[XXX]: query String: {0}", body);
@ -110,7 +96,7 @@ namespace OpenSim.Groups
string method = request["METHOD"].ToString(); string method = request["METHOD"].ToString();
request.Remove("METHOD"); request.Remove("METHOD");
// m_log.DebugFormat("[Groups.Handler]: {0}", method); m_log.DebugFormat("[Groups.Handler]: {0}", method);
switch (method) switch (method)
{ {
case "PUTGROUP": case "PUTGROUP":
@ -147,14 +133,12 @@ namespace OpenSim.Groups
return HandleAddNotice(request); return HandleAddNotice(request);
case "GETNOTICES": case "GETNOTICES":
return HandleGetNotices(request); return HandleGetNotices(request);
case "FINDGROUPS":
return HandleFindGroups(request);
} }
m_log.DebugFormat("[GROUPS HANDLER]: unknown method request: {0}", method); m_log.DebugFormat("[GROUPS HANDLER]: unknown method request: {0}", method);
} }
catch (Exception e) catch (Exception e)
{ {
m_log.Error(string.Format("[GROUPS HANDLER]: Exception {0} ", e.Message), e); m_log.DebugFormat("[GROUPS HANDLER]: Exception {0}", e.StackTrace);
} }
return FailureResult(); return FailureResult();
@ -286,13 +270,11 @@ namespace OpenSim.Groups
string agentID = request["AgentID"].ToString(); string agentID = request["AgentID"].ToString();
string requestingAgentID = request["RequestingAgentID"].ToString(); string requestingAgentID = request["RequestingAgentID"].ToString();
if (!m_GroupsService.RemoveAgentFromGroup(requestingAgentID, agentID, groupID)) m_GroupsService.RemoveAgentFromGroup(requestingAgentID, agentID, groupID);
NullResult(result, string.Format("Insufficient permissions. {0}", agentID));
else
result["RESULT"] = "true";
} }
//m_log.DebugFormat("[XXX]: resp string: {0}", xmlString); //m_log.DebugFormat("[XXX]: resp string: {0}", xmlString);
result["RESULT"] = "true";
return Util.UTF8NoBomEncoding.GetBytes(ServerUtils.BuildXmlResponse(result)); return Util.UTF8NoBomEncoding.GetBytes(ServerUtils.BuildXmlResponse(result));
} }
@ -394,7 +376,7 @@ namespace OpenSim.Groups
if (!request.ContainsKey("RequestingAgentID") || !request.ContainsKey("GroupID") || !request.ContainsKey("RoleID") || if (!request.ContainsKey("RequestingAgentID") || !request.ContainsKey("GroupID") || !request.ContainsKey("RoleID") ||
!request.ContainsKey("Name") || !request.ContainsKey("Description") || !request.ContainsKey("Title") || !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"); NullResult(result, "Bad network data");
else else
@ -520,11 +502,11 @@ namespace OpenSim.Groups
bool success = false; bool success = false;
if (op == "ADD") 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())); new UUID(request["GroupID"].ToString()), new UUID(request["RoleID"].ToString()));
else if (op == "DELETE") 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())); new UUID(request["GroupID"].ToString()), new UUID(request["RoleID"].ToString()));
result["RESULT"] = success.ToString(); result["RESULT"] = success.ToString();
@ -648,8 +630,8 @@ namespace OpenSim.Groups
string op = request["OP"].ToString(); string op = request["OP"].ToString();
if (op == "ADD" && request.ContainsKey("GroupID") && request.ContainsKey("RoleID") && request.ContainsKey("AgentID")) 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["InviteID"].ToString()), new UUID(request["GroupID"].ToString()),
new UUID(request["RoleID"].ToString()), request["AgentID"].ToString()); new UUID(request["RoleID"].ToString()), request["AgentID"].ToString());
@ -665,14 +647,10 @@ namespace OpenSim.Groups
} }
else if (op == "GET") 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())); new UUID(request["InviteID"].ToString()));
if (invite != null) result["RESULT"] = GroupsDataUtils.GroupInviteInfo(invite);
result["RESULT"] = GroupsDataUtils.GroupInviteInfo(invite);
else
result["RESULT"] = "NULL";
return Util.UTF8NoBomEncoding.GetBytes(ServerUtils.BuildXmlResponse(result)); return Util.UTF8NoBomEncoding.GetBytes(ServerUtils.BuildXmlResponse(result));
} }
@ -762,32 +740,6 @@ namespace OpenSim.Groups
return Util.UTF8NoBomEncoding.GetBytes(xmlString); return Util.UTF8NoBomEncoding.GetBytes(xmlString);
} }
byte[] HandleFindGroups(Dictionary<string, object> request)
{
Dictionary<string, object> result = new Dictionary<string, object>();
if (!request.ContainsKey("RequestingAgentID") || !request.ContainsKey("Query"))
NullResult(result, "Bad network data");
List<DirGroupsReplyData> hits = m_GroupsService.FindGroups(request["RequestingAgentID"].ToString(), request["Query"].ToString());
if (hits == null || (hits != null && hits.Count == 0))
NullResult(result, "No hits");
else
{
Dictionary<string, object> dict = new Dictionary<string, object>();
int i = 0;
foreach (DirGroupsReplyData n in hits)
dict["n-" + i++] = GroupsDataUtils.DirGroupsReplyData(n);
result["RESULT"] = dict;
}
string xmlString = ServerUtils.BuildXmlResponse(result);
return Util.UTF8NoBomEncoding.GetBytes(xmlString);
}
#region Helpers #region Helpers
@ -804,14 +756,6 @@ namespace OpenSim.Groups
string xmlString = ServerUtils.BuildXmlResponse(result); string xmlString = ServerUtils.BuildXmlResponse(result);
return Util.UTF8NoBomEncoding.GetBytes(xmlString); return Util.UTF8NoBomEncoding.GetBytes(xmlString);
} }
private byte[] FailureResult(string reason)
{
Dictionary<string, object> result = new Dictionary<string, object>();
NullResult(result, reason);
string xmlString = ServerUtils.BuildXmlResponse(result);
return Util.UTF8NoBomEncoding.GetBytes(xmlString);
}
#endregion #endregion
} }
} }

View File

@ -31,8 +31,7 @@ using System.Reflection;
using System.Threading; using System.Threading;
using OpenSim.Framework; using OpenSim.Framework;
//using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.Framework.Interfaces;
using OpenSim.Services.Interfaces;
using OpenMetaverse; using OpenMetaverse;
@ -145,20 +144,14 @@ namespace OpenSim.Groups
if (firstCall) if (firstCall)
{ {
try //group = m_GroupsService.GetGroupRecord(RequestingAgentID, GroupID, GroupName);
{ group = d();
//group = m_GroupsService.GetGroupRecord(RequestingAgentID, GroupID, GroupName);
group = d();
lock (m_Cache) lock (m_Cache)
{
m_Cache.AddOrUpdate(cacheKey, group, GROUPS_CACHE_TIMEOUT);
return (ExtendedGroupRecord)group;
}
}
finally
{ {
m_Cache.AddOrUpdate(cacheKey, group, GROUPS_CACHE_TIMEOUT);
m_ActiveRequests.Remove(cacheKey); m_ActiveRequests.Remove(cacheKey);
return (ExtendedGroupRecord)group;
} }
} }
else else
@ -250,19 +243,13 @@ namespace OpenSim.Groups
if (firstCall) if (firstCall)
{ {
try membership = d();
{
membership = d();
lock (m_Cache) lock (m_Cache)
{
m_Cache.AddOrUpdate(cacheKey, membership, GROUPS_CACHE_TIMEOUT);
return (ExtendedGroupMembershipData)membership;
}
}
finally
{ {
m_Cache.AddOrUpdate(cacheKey, membership, GROUPS_CACHE_TIMEOUT);
m_ActiveRequests.Remove(cacheKey); m_ActiveRequests.Remove(cacheKey);
return (ExtendedGroupMembershipData)membership;
} }
} }
else else
@ -299,18 +286,12 @@ namespace OpenSim.Groups
if (firstCall) if (firstCall)
{ {
try membership = d();
{ lock (m_Cache)
membership = d();
lock (m_Cache)
{
m_Cache.AddOrUpdate(cacheKey, membership, GROUPS_CACHE_TIMEOUT);
return (ExtendedGroupMembershipData)membership;
}
}
finally
{ {
m_Cache.AddOrUpdate(cacheKey, membership, GROUPS_CACHE_TIMEOUT);
m_ActiveRequests.Remove(cacheKey); m_ActiveRequests.Remove(cacheKey);
return (ExtendedGroupMembershipData)membership;
} }
} }
else else
@ -346,18 +327,12 @@ namespace OpenSim.Groups
if (firstCall) if (firstCall)
{ {
try memberships = d();
{ lock (m_Cache)
memberships = d();
lock (m_Cache)
{
m_Cache.AddOrUpdate(cacheKey, memberships, GROUPS_CACHE_TIMEOUT);
return (List<GroupMembershipData>)memberships;
}
}
finally
{ {
m_Cache.AddOrUpdate(cacheKey, memberships, GROUPS_CACHE_TIMEOUT);
m_ActiveRequests.Remove(cacheKey); m_ActiveRequests.Remove(cacheKey);
return (List<GroupMembershipData>)memberships;
} }
} }
else else
@ -394,26 +369,20 @@ namespace OpenSim.Groups
if (firstCall) if (firstCall)
{ {
try List<ExtendedGroupMembersData> _members = d();
{
List<ExtendedGroupMembersData> _members = d(); if (_members != null && _members.Count > 0)
members = _members.ConvertAll<GroupMembersData>(new Converter<ExtendedGroupMembersData, GroupMembersData>(m_ForeignImporter.ConvertGroupMembersData));
if (_members != null && _members.Count > 0) else
members = _members.ConvertAll<GroupMembersData>(new Converter<ExtendedGroupMembersData, GroupMembersData>(m_ForeignImporter.ConvertGroupMembersData)); members = new List<GroupMembersData>();
else
members = new List<GroupMembersData>(); lock (m_Cache)
lock (m_Cache)
{
//m_Cache.AddOrUpdate(cacheKey, members, GROUPS_CACHE_TIMEOUT);
m_Cache.AddOrUpdate(cacheKey, _members, GROUPS_CACHE_TIMEOUT);
return (List<GroupMembersData>)members;
}
}
finally
{ {
//m_Cache.AddOrUpdate(cacheKey, members, GROUPS_CACHE_TIMEOUT);
m_Cache.AddOrUpdate(cacheKey, _members, GROUPS_CACHE_TIMEOUT);
m_ActiveRequests.Remove(cacheKey); m_ActiveRequests.Remove(cacheKey);
return (List<GroupMembersData>)members;
} }
} }
else else
@ -528,22 +497,16 @@ namespace OpenSim.Groups
if (firstCall) if (firstCall)
{ {
try roles = d();
if (roles != null)
{ {
roles = d(); lock (m_Cache)
if (roles != null)
{ {
lock (m_Cache) m_Cache.AddOrUpdate(cacheKey, roles, GROUPS_CACHE_TIMEOUT);
{ m_ActiveRequests.Remove(cacheKey);
m_Cache.AddOrUpdate(cacheKey, roles, GROUPS_CACHE_TIMEOUT); return (List<GroupRolesData>)roles;
return (List<GroupRolesData>)roles;
}
} }
} }
finally
{
m_ActiveRequests.Remove(cacheKey);
}
} }
else else
Thread.Sleep(50); Thread.Sleep(50);
@ -578,29 +541,23 @@ namespace OpenSim.Groups
if (firstCall) if (firstCall)
{ {
try List<ExtendedGroupRoleMembersData> _rmembers = d();
{
List<ExtendedGroupRoleMembersData> _rmembers = d();
if (_rmembers != null && _rmembers.Count > 0) if (_rmembers != null && _rmembers.Count > 0)
rmembers = _rmembers.ConvertAll<GroupRoleMembersData>(new Converter<ExtendedGroupRoleMembersData, GroupRoleMembersData>(m_ForeignImporter.ConvertGroupRoleMembersData)); rmembers = _rmembers.ConvertAll<GroupRoleMembersData>(new Converter<ExtendedGroupRoleMembersData, GroupRoleMembersData>(m_ForeignImporter.ConvertGroupRoleMembersData));
else else
rmembers = new List<GroupRoleMembersData>(); rmembers = new List<GroupRoleMembersData>();
lock (m_Cache) 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
{ {
// 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); m_ActiveRequests.Remove(cacheKey);
return (List<GroupRoleMembersData>)rmembers;
} }
} }
else else
@ -709,19 +666,12 @@ namespace OpenSim.Groups
if (firstCall) if (firstCall)
{ {
try roles = d();
{ lock (m_Cache)
roles = d();
lock (m_Cache)
{
m_Cache.AddOrUpdate(cacheKey, roles, GROUPS_CACHE_TIMEOUT);
m_ActiveRequests.Remove(cacheKey);
return (List<GroupRolesData>)roles;
}
}
finally
{ {
m_Cache.AddOrUpdate(cacheKey, roles, GROUPS_CACHE_TIMEOUT);
m_ActiveRequests.Remove(cacheKey); m_ActiveRequests.Remove(cacheKey);
return (List<GroupRolesData>)roles;
} }
} }
else else
@ -817,19 +767,13 @@ namespace OpenSim.Groups
if (firstCall) if (firstCall)
{ {
try GroupNoticeInfo _notice = d();
{
GroupNoticeInfo _notice = d();
lock (m_Cache) lock (m_Cache)
{
m_Cache.AddOrUpdate(cacheKey, _notice, GROUPS_CACHE_TIMEOUT);
return _notice;
}
}
finally
{ {
m_Cache.AddOrUpdate(cacheKey, _notice, GROUPS_CACHE_TIMEOUT);
m_ActiveRequests.Remove(cacheKey); m_ActiveRequests.Remove(cacheKey);
return _notice;
} }
} }
else else
@ -865,24 +809,20 @@ namespace OpenSim.Groups
if (firstCall) if (firstCall)
{ {
try notices = d();
{
notices = d();
lock (m_Cache) lock (m_Cache)
{
m_Cache.AddOrUpdate(cacheKey, notices, GROUPS_CACHE_TIMEOUT);
return (List<ExtendedGroupNoticeData>)notices;
}
}
finally
{ {
m_Cache.AddOrUpdate(cacheKey, notices, GROUPS_CACHE_TIMEOUT);
m_ActiveRequests.Remove(cacheKey); m_ActiveRequests.Remove(cacheKey);
return (List<ExtendedGroupNoticeData>)notices;
} }
} }
else else
Thread.Sleep(50); Thread.Sleep(50);
} }
} }
} }
} }

View File

@ -43,63 +43,59 @@ namespace OpenSim.Groups
{ {
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
public const GroupPowers DefaultEveryonePowers = public const GroupPowers DefaultEveryonePowers = GroupPowers.AllowSetHome |
GroupPowers.AllowSetHome | GroupPowers.Accountable |
GroupPowers.Accountable | GroupPowers.JoinChat |
GroupPowers.JoinChat | GroupPowers.AllowVoiceChat |
GroupPowers.AllowVoiceChat | GroupPowers.ReceiveNotices |
GroupPowers.ReceiveNotices | GroupPowers.StartProposal |
GroupPowers.StartProposal | GroupPowers.VoteOnProposal;
GroupPowers.VoteOnProposal;
public const GroupPowers OfficersPowers = DefaultEveryonePowers | public const GroupPowers OwnerPowers = GroupPowers.Accountable |
GroupPowers.AllowFly | GroupPowers.AllowEditLand |
GroupPowers.AllowLandmark | GroupPowers.AllowFly |
GroupPowers.AllowRez | GroupPowers.AllowLandmark |
GroupPowers.AssignMemberLimited | GroupPowers.AllowRez |
GroupPowers.ChangeIdentity | GroupPowers.AllowSetHome |
GroupPowers.ChangeMedia | GroupPowers.AllowVoiceChat |
GroupPowers.ChangeOptions | GroupPowers.AssignMember |
GroupPowers.DeedObject | GroupPowers.AssignMemberLimited |
GroupPowers.Eject | GroupPowers.ChangeActions |
GroupPowers.FindPlaces | GroupPowers.ChangeIdentity |
GroupPowers.Invite | GroupPowers.ChangeMedia |
GroupPowers.LandChangeIdentity | GroupPowers.ChangeOptions |
GroupPowers.LandDeed | GroupPowers.CreateRole |
GroupPowers.LandDivideJoin | GroupPowers.DeedObject |
GroupPowers.LandEdit | GroupPowers.DeleteRole |
GroupPowers.AllowEnvironment | GroupPowers.Eject |
GroupPowers.LandEjectAndFreeze | GroupPowers.FindPlaces |
GroupPowers.LandGardening | GroupPowers.Invite |
GroupPowers.LandManageAllowed | GroupPowers.JoinChat |
GroupPowers.LandManageBanned | GroupPowers.LandChangeIdentity |
GroupPowers.LandManagePasses | GroupPowers.LandDeed |
GroupPowers.LandOptions | GroupPowers.LandDivideJoin |
GroupPowers.LandRelease | GroupPowers.LandEdit |
GroupPowers.LandSetSale | GroupPowers.LandEjectAndFreeze |
GroupPowers.MemberVisible | GroupPowers.LandGardening |
GroupPowers.ModerateChat | GroupPowers.LandManageAllowed |
GroupPowers.ObjectManipulate | GroupPowers.LandManageBanned |
GroupPowers.ObjectSetForSale | GroupPowers.LandManagePasses |
GroupPowers.ReturnGroupOwned | GroupPowers.LandOptions |
GroupPowers.ReturnGroupSet | GroupPowers.LandRelease |
GroupPowers.ReturnNonGroup | GroupPowers.LandSetSale |
GroupPowers.RoleProperties | GroupPowers.ModerateChat |
GroupPowers.SendNotices | GroupPowers.ObjectManipulate |
GroupPowers.SetLandingPoint; GroupPowers.ObjectSetForSale |
GroupPowers.ReceiveNotices |
public const GroupPowers OwnerPowers = OfficersPowers | GroupPowers.RemoveMember |
GroupPowers.Accountable | GroupPowers.ReturnGroupOwned |
GroupPowers.AllowEditLand | GroupPowers.ReturnGroupSet |
GroupPowers.AssignMember | GroupPowers.ReturnNonGroup |
GroupPowers.ChangeActions | GroupPowers.RoleProperties |
GroupPowers.CreateRole | GroupPowers.SendNotices |
GroupPowers.DeleteRole | GroupPowers.SetLandingPoint |
GroupPowers.ExperienceAdmin | GroupPowers.StartProposal |
GroupPowers.ExperienceCreator | GroupPowers.VoteOnProposal;
GroupPowers.GroupBanAccess |
GroupPowers.HostEvent |
GroupPowers.RemoveMember;
#region Daily Cleanup #region Daily Cleanup
@ -129,7 +125,7 @@ namespace OpenSim.Groups
#endregion #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) bool allowPublish, bool maturePublish, UUID founderID, out string reason)
{ {
reason = string.Empty; reason = string.Empty;
@ -154,25 +150,20 @@ namespace OpenSim.Groups
data.Data["ShowInList"] = showInList ? "1" : "0"; data.Data["ShowInList"] = showInList ? "1" : "0";
data.Data["AllowPublish"] = allowPublish ? "1" : "0"; data.Data["AllowPublish"] = allowPublish ? "1" : "0";
data.Data["MaturePublish"] = maturePublish ? "1" : "0"; data.Data["MaturePublish"] = maturePublish ? "1" : "0";
UUID ownerRoleID = UUID.Random(); data.Data["OwnerRoleID"] = UUID.Random().ToString();
data.Data["OwnerRoleID"] = ownerRoleID.ToString();
if (!m_Database.StoreGroup(data)) if (!m_Database.StoreGroup(data))
return UUID.Zero; return UUID.Zero;
// Create Everyone role // 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); _AddOrUpdateGroupRole(RequestingAgentID, data.GroupID, UUID.Zero, "Everyone", "Everyone in the group", "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);
// Create Owner role // Create Owner role
_AddOrUpdateGroupRole(RequestingAgentID, data.GroupID, ownerRoleID, "Owners", "Owners of the group", "Owner of " + name, (ulong)OwnerPowers, true); UUID roleID = UUID.Random();
_AddOrUpdateGroupRole(RequestingAgentID, data.GroupID, roleID, "Owners", "Owners of the group", "Owner of " + name, (ulong)OwnerPowers, true);
// Add founder to group // Add founder to group
_AddAgentToGroup(RequestingAgentID, founderID.ToString(), data.GroupID, ownerRoleID); _AddAgentToGroup(RequestingAgentID, founderID.ToString(), data.GroupID, roleID);
_AddAgentToGroup(RequestingAgentID, founderID.ToString(), data.GroupID, officersRoleID);
return data.GroupID; return data.GroupID;
} }
@ -231,22 +222,15 @@ namespace OpenSim.Groups
if (d.Data.ContainsKey("Location") && d.Data["Location"] != string.Empty) if (d.Data.ContainsKey("Location") && d.Data["Location"] != string.Empty)
continue; continue;
int nmembers = m_Database.MemberCount(d.GroupID);
if(nmembers == 0)
continue;
DirGroupsReplyData g = new DirGroupsReplyData(); DirGroupsReplyData g = new DirGroupsReplyData();
g.groupID = d.GroupID;
if (d.Data.ContainsKey("Name")) if (d.Data.ContainsKey("Name"))
g.groupName = d.Data["Name"]; g.groupName = d.Data["Name"];
else else
{
m_log.DebugFormat("[Groups]: Key Name not found"); m_log.DebugFormat("[Groups]: Key Name not found");
continue;
}
g.groupID = d.GroupID; g.members = m_Database.MemberCount(d.GroupID);
g.members = nmembers;
groups.Add(g); groups.Add(g);
} }
@ -263,9 +247,6 @@ namespace OpenSim.Groups
if (group == null) if (group == null)
return members; return members;
// Unfortunately this doesn't quite work on legacy group data because of a bug
// that's also being fixed here on CreateGroup. The OwnerRoleID sent to the DB was wrong.
// See how to find the ownerRoleID a few lines below.
UUID ownerRoleID = new UUID(group.Data["OwnerRoleID"]); UUID ownerRoleID = new UUID(group.Data["OwnerRoleID"]);
RoleData[] roles = m_Database.RetrieveRoles(GroupID); RoleData[] roles = m_Database.RetrieveRoles(GroupID);
@ -274,25 +255,13 @@ namespace OpenSim.Groups
return members; return members;
List<RoleData> rolesList = new List<RoleData>(roles); List<RoleData> rolesList = new List<RoleData>(roles);
// Let's find the "real" ownerRoleID // Is the requester a member of the group?
RoleData ownerRole = rolesList.Find(r => r.Data["Powers"] == ((long)OwnerPowers).ToString()); bool isInGroup = false;
if (ownerRole != null) if (m_Database.RetrieveMember(GroupID, RequestingAgentID) != null)
ownerRoleID = ownerRole.RoleID; isInGroup = true;
// Check visibility? if (!isInGroup) // reduce the roles to the visible ones
// When we don't want to check visibility, we pass it "all" as the requestingAgentID rolesList = rolesList.FindAll(r => (UInt64.Parse(r.Data["Powers"]) & (ulong)GroupPowers.MemberVisible) != 0);
bool checkVisibility = !RequestingAgentID.Equals(UUID.Zero.ToString());
if (checkVisibility)
{
// Is the requester a member of the group?
bool isInGroup = false;
if (m_Database.RetrieveMember(GroupID, RequestingAgentID) != null)
isInGroup = true;
if (!isInGroup) // reduce the roles to the visible ones
rolesList = rolesList.FindAll(r => (UInt64.Parse(r.Data["Powers"]) & (ulong)GroupPowers.MemberVisible) != 0);
}
MembershipData[] datas = m_Database.RetrieveMembers(GroupID); MembershipData[] datas = m_Database.RetrieveMembers(GroupID);
if (datas == null || (datas != null && datas.Length == 0)) if (datas == null || (datas != null && datas.Length == 0))
@ -315,32 +284,17 @@ namespace OpenSim.Groups
{ {
m.Title = selected.Data["Title"]; m.Title = selected.Data["Title"];
m.AgentPowers = UInt64.Parse(selected.Data["Powers"]); m.AgentPowers = UInt64.Parse(selected.Data["Powers"]);
m.AgentID = d.PrincipalID;
m.AcceptNotices = d.Data["AcceptNotices"] == "1" ? true : false;
m.Contribution = Int32.Parse(d.Data["Contribution"]);
m.ListInProfile = d.Data["ListInProfile"] == "1" ? true : false;
// Is this person an owner of the group?
m.IsOwner = (rolemembershipsList.Find(r => r.RoleID == ownerRoleID) != null) ? true : false;
members.Add(m);
} }
m.AgentID = d.PrincipalID;
m.AcceptNotices = d.Data["AcceptNotices"] == "1" ? true : false;
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;
members.Add(m);
} }
return members; return members;
@ -432,15 +386,13 @@ namespace OpenSim.Groups
return true; return true;
} }
public bool RemoveAgentFromGroup(string RequestingAgentID, string AgentID, UUID GroupID) public void RemoveAgentFromGroup(string RequestingAgentID, string AgentID, UUID GroupID)
{ {
// check perms // check perms
if (RequestingAgentID != AgentID && !HasPower(RequestingAgentID, GroupID, GroupPowers.Eject)) if (RequestingAgentID != AgentID && !HasPower(RequestingAgentID, GroupID, GroupPowers.Eject))
return false; return;
_RemoveAgentFromGroup(RequestingAgentID, AgentID, GroupID); _RemoveAgentFromGroup(RequestingAgentID, AgentID, GroupID);
return true;
} }
public bool AddAgentToGroupInvite(string RequestingAgentID, UUID inviteID, UUID groupID, UUID roleID, string agentID) public bool AddAgentToGroupInvite(string RequestingAgentID, UUID inviteID, UUID groupID, UUID roleID, string agentID)
@ -500,8 +452,8 @@ namespace OpenSim.Groups
// check permissions // check permissions
bool limited = HasPower(RequestingAgentID, GroupID, GroupPowers.AssignMemberLimited); bool limited = HasPower(RequestingAgentID, GroupID, GroupPowers.AssignMemberLimited);
bool unlimited = HasPower(RequestingAgentID, GroupID, GroupPowers.AssignMember) || IsOwner(RequestingAgentID, GroupID); bool unlimited = HasPower(RequestingAgentID, GroupID, GroupPowers.AssignMember) | IsOwner(RequestingAgentID, GroupID);
if (!limited && !unlimited) if (!limited || !unlimited)
{ {
m_log.DebugFormat("[Groups]: ({0}) Attempt at assigning {1} to role {2} denied because of lack of permission", RequestingAgentID, AgentID, RoleID); m_log.DebugFormat("[Groups]: ({0}) Attempt at assigning {1} to role {2} denied because of lack of permission", RequestingAgentID, AgentID, RoleID);
return false; return false;
@ -511,7 +463,7 @@ namespace OpenSim.Groups
if (!unlimited && limited) if (!unlimited && limited)
{ {
// check whether person's has this role // 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) if (rolemembership == null)
{ {
m_log.DebugFormat("[Groups]: ({0}) Attempt at assigning {1} to role {2} denied because of limited permission", RequestingAgentID, AgentID, RoleID); m_log.DebugFormat("[Groups]: ({0}) Attempt at assigning {1} to role {2} denied because of limited permission", RequestingAgentID, AgentID, RoleID);
@ -531,26 +483,13 @@ namespace OpenSim.Groups
return false; return false;
// check permissions // check permissions
bool limited = HasPower(RequestingAgentID, GroupID, GroupPowers.AssignMemberLimited);
bool unlimited = HasPower(RequestingAgentID, GroupID, GroupPowers.AssignMember) || IsOwner(RequestingAgentID, GroupID); 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); m_log.DebugFormat("[Groups]: ({0}) Attempt at removing {1} from role {2} denied because of lack of permission", RequestingAgentID, AgentID, RoleID);
return false; 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); RoleMembershipData rolemember = m_Database.RetrieveRoleMember(GroupID, RoleID, AgentID);
if (rolemember == null) if (rolemember == null)
@ -568,8 +507,8 @@ namespace OpenSim.Groups
{ {
newRoleID = r.RoleID; newRoleID = r.RoleID;
break; break;
} }
} }
MembershipData member = m_Database.RetrieveMember(GroupID, AgentID); MembershipData member = m_Database.RetrieveMember(GroupID, AgentID);
if (member != null) if (member != null)
@ -727,7 +666,7 @@ namespace OpenSim.Groups
m_Database.StoreMember(membership); 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) bool hasAttachment, byte attType, string attName, UUID attItemID, string attOwnerID)
{ {
// Check perms // Check perms
@ -840,7 +779,7 @@ namespace OpenSim.Groups
if (RoleID != UUID.Zero) if (RoleID != UUID.Zero)
_AddAgentToGroupRole(RequestingAgentID, AgentID, GroupID, RoleID); _AddAgentToGroupRole(RequestingAgentID, AgentID, GroupID, RoleID);
// Make this the active group // Make thit this active group
PrincipalData pdata = new PrincipalData(); PrincipalData pdata = new PrincipalData();
pdata.PrincipalID = AgentID; pdata.PrincipalID = AgentID;
pdata.ActiveGroupID = GroupID; pdata.ActiveGroupID = GroupID;
@ -858,7 +797,7 @@ namespace OpenSim.Groups
return false; 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); m_log.DebugFormat("[Groups]: Group {0} doesn't exist. Can't update it", groupID);
return false; return false;

View File

@ -1,4 +1,4 @@
/* /*
* Copyright (c) Contributors, http://opensimulator.org/ * Copyright (c) Contributors, http://opensimulator.org/
* See CONTRIBUTORS.TXT for a full list of copyright holders. * See CONTRIBUTORS.TXT for a full list of copyright holders.
* *
@ -38,7 +38,6 @@ namespace OpenSim.Groups
public class GroupsServiceBase : ServiceBase public class GroupsServiceBase : ServiceBase
{ {
protected IGroupsData m_Database = null; protected IGroupsData m_Database = null;
protected IGridUserData m_GridUserService = null;
public GroupsServiceBase(IConfigSource config, string cName) public GroupsServiceBase(IConfigSource config, string cName)
: base(config) : base(config)
@ -46,7 +45,6 @@ namespace OpenSim.Groups
string dllName = String.Empty; string dllName = String.Empty;
string connString = String.Empty; string connString = String.Empty;
string realm = "os_groups"; string realm = "os_groups";
string usersRealm = "GridUser";
string configName = (cName == string.Empty) ? "Groups" : cName; string configName = (cName == string.Empty) ? "Groups" : cName;
// //
@ -81,21 +79,6 @@ namespace OpenSim.Groups
m_Database = LoadPlugin<IGroupsData>(dllName, new Object[] { connString, realm }); m_Database = LoadPlugin<IGroupsData>(dllName, new Object[] { connString, realm });
if (m_Database == null) if (m_Database == null)
throw new Exception("Could not find a storage interface in the given module " + dllName); 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 // Check if it already exists
GroupData grec = m_Database.RetrieveGroup(groupID); 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())) (grec != null && grec.Data["Location"] != string.Empty && grec.Data["Location"].ToLower() != serviceLocation.ToLower()))
{ {
// Create the group // Create the group
@ -131,27 +131,19 @@ namespace OpenSim.Groups
return true; return true;
} }
public bool RemoveAgentFromGroup(string RequestingAgentID, string AgentID, UUID GroupID, string token) public void RemoveAgentFromGroup(string RequestingAgentID, string AgentID, UUID GroupID, string token)
{ {
// check the token // check the token
MembershipData membership = m_Database.RetrieveMember(GroupID, AgentID); MembershipData membership = m_Database.RetrieveMember(GroupID, AgentID);
if (membership != null) if (membership != null)
{ {
if (token != string.Empty && token.Equals(membership.Data["AccessToken"])) if (token != string.Empty && token.Equals(membership.Data["AccessToken"]))
{ RemoveAgentFromGroup(RequestingAgentID, AgentID, GroupID);
return RemoveAgentFromGroup(RequestingAgentID, AgentID, GroupID);
}
else else
{
m_log.DebugFormat("[Groups.HGGroupsService]: access token {0} did not match stored one {1}", token, membership.Data["AccessToken"]); m_log.DebugFormat("[Groups.HGGroupsService]: access token {0} did not match stored one {1}", token, membership.Data["AccessToken"]);
return false;
}
} }
else else
{
m_log.DebugFormat("[Groups.HGGroupsService]: membership not found for {0}", AgentID); m_log.DebugFormat("[Groups.HGGroupsService]: membership not found for {0}", AgentID);
return false;
}
} }
public ExtendedGroupRecord GetGroupRecord(string RequestingAgentID, UUID GroupID, string groupName, string token) public ExtendedGroupRecord GetGroupRecord(string RequestingAgentID, UUID GroupID, string groupName, string token)

View File

@ -66,7 +66,7 @@ namespace OpenSim.OfflineIM
if (serviceLocation == string.Empty) if (serviceLocation == string.Empty)
m_OfflineIMService = new OfflineIMService(config); m_OfflineIMService = new OfflineIMService(config);
else else
m_OfflineIMService = new OfflineIMServiceRemoteConnector(config); m_OfflineIMService = new OfflineIMServiceRemoteConnector(serviceLocation);
m_ForwardOfflineGroupMessages = cnf.GetBoolean("ForwardOfflineGroupMessages", m_ForwardOfflineGroupMessages); m_ForwardOfflineGroupMessages = cnf.GetBoolean("ForwardOfflineGroupMessages", m_ForwardOfflineGroupMessages);
m_log.DebugFormat("[OfflineIM.V2]: Offline messages enabled by {0}", Name); m_log.DebugFormat("[OfflineIM.V2]: Offline messages enabled by {0}", Name);
@ -114,6 +114,7 @@ namespace OpenSim.OfflineIM
scene.ForEachClient(delegate(IClientAPI client) scene.ForEachClient(delegate(IClientAPI client)
{ {
client.OnRetrieveInstantMessages -= RetrieveInstantMessages; client.OnRetrieveInstantMessages -= RetrieveInstantMessages;
client.OnMuteListRequest -= OnMuteListRequest;
}); });
} }
@ -161,6 +162,7 @@ namespace OpenSim.OfflineIM
private void OnNewClient(IClientAPI client) private void OnNewClient(IClientAPI client)
{ {
client.OnRetrieveInstantMessages += RetrieveInstantMessages; client.OnRetrieveInstantMessages += RetrieveInstantMessages;
client.OnMuteListRequest += OnMuteListRequest;
} }
private void RetrieveInstantMessages(IClientAPI client) 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) private void UndeliveredMessage(GridInstantMessage im)
{ {
if (im.dialog != (byte)InstantMessageDialog.MessageFromObject && if (im.dialog != (byte)InstantMessageDialog.MessageFromObject &&
@ -210,6 +226,10 @@ namespace OpenSim.OfflineIM
return; return;
} }
Scene scene = FindScene(new UUID(im.fromAgentID));
if (scene == null)
scene = m_SceneList[0];
string reason = string.Empty; string reason = string.Empty;
bool success = m_OfflineIMService.StoreMessage(im, out reason); bool success = m_OfflineIMService.StoreMessage(im, out reason);
@ -241,11 +261,6 @@ namespace OpenSim.OfflineIM
return m_OfflineIMService.StoreMessage(im, out reason); return m_OfflineIMService.StoreMessage(im, out reason);
} }
public void DeleteMessages(UUID userID)
{
m_OfflineIMService.DeleteMessages(userID);
}
#endregion #endregion
} }
} }

View File

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

View File

@ -32,7 +32,6 @@ using System.Reflection;
using System.Text; using System.Text;
using OpenSim.Framework; using OpenSim.Framework;
using OpenSim.Framework.ServiceAuth;
using OpenSim.Server.Base; using OpenSim.Server.Base;
using OpenSim.Services.Interfaces; using OpenSim.Services.Interfaces;
@ -47,7 +46,6 @@ namespace OpenSim.OfflineIM
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_ServerURI = string.Empty; private string m_ServerURI = string.Empty;
private IServiceAuth m_Auth;
private object m_Lock = new object(); private object m_Lock = new object();
public OfflineIMServiceRemoteConnector(string url) public OfflineIMServiceRemoteConnector(string url)
@ -67,18 +65,6 @@ namespace OpenSim.OfflineIM
m_ServerURI = cnf.GetString("OfflineMessageURL", string.Empty); m_ServerURI = cnf.GetString("OfflineMessageURL", string.Empty);
/// This is from BaseServiceConnector
string authType = Util.GetConfigVarFromSections<string>(config, "AuthType", new string[] { "Network", "Messaging" }, "None");
switch (authType)
{
case "BasicHttpAuthentication":
m_Auth = new BasicHttpAuthentication(config, "Messaging");
break;
}
///
m_log.DebugFormat("[OfflineIM.V2.RemoteConnector]: Offline IM server at {0} with auth {1}",
m_ServerURI, (m_Auth == null ? "None" : m_Auth.GetType().ToString()));
} }
#region IOfflineIMService #region IOfflineIMService
@ -96,13 +82,8 @@ namespace OpenSim.OfflineIM
if (!ret.ContainsKey("RESULT")) if (!ret.ContainsKey("RESULT"))
return ims; return ims;
string result = ret["RESULT"].ToString(); if (ret["RESULT"].ToString() == "NULL")
if (result == "NULL" || result.ToLower() == "false")
{
string reason = ret.ContainsKey("REASON") ? ret["REASON"].ToString() : "Unknown error";
m_log.DebugFormat("[OfflineIM.V2.RemoteConnector]: GetMessages for {0} failed: {1}", principalID, reason);
return ims; return ims;
}
foreach (object v in ((Dictionary<string, object>)ret["RESULT"]).Values) foreach (object v in ((Dictionary<string, object>)ret["RESULT"]).Values)
{ {
@ -129,21 +110,13 @@ namespace OpenSim.OfflineIM
string result = ret["RESULT"].ToString(); string result = ret["RESULT"].ToString();
if (result == "NULL" || result.ToLower() == "false") if (result == "NULL" || result.ToLower() == "false")
{ {
reason = ret.ContainsKey("REASON") ? ret["REASON"].ToString() : "Unknown error"; reason = ret["REASON"].ToString();
return false; return false;
} }
return true; return true;
} }
public void DeleteMessages(UUID userID)
{
Dictionary<string, object> sendData = new Dictionary<string, object>();
sendData["UserID"] = userID;
MakeRequest("DELETE", sendData);
}
#endregion #endregion
@ -157,8 +130,7 @@ namespace OpenSim.OfflineIM
lock (m_Lock) lock (m_Lock)
reply = SynchronousRestFormsRequester.MakeRequest("POST", reply = SynchronousRestFormsRequester.MakeRequest("POST",
m_ServerURI + "/offlineim", m_ServerURI + "/offlineim",
ServerUtils.BuildQueryString(sendData), ServerUtils.BuildQueryString(sendData));
m_Auth);
Dictionary<string, object> replyData = ServerUtils.ParseXmlResponse( Dictionary<string, object> replyData = ServerUtils.ParseXmlResponse(
reply); reply);

View File

@ -1,4 +1,4 @@
/* /*
* Copyright (c) Contributors, http://opensimulator.org/ * Copyright (c) Contributors, http://opensimulator.org/
* See CONTRIBUTORS.TXT for a full list of copyright holders. * See CONTRIBUTORS.TXT for a full list of copyright holders.
* *
@ -36,7 +36,6 @@ using OpenSim.Framework;
using OpenSim.Server.Base; using OpenSim.Server.Base;
using OpenSim.Services.Interfaces; using OpenSim.Services.Interfaces;
using OpenSim.Framework.Servers.HttpServer; using OpenSim.Framework.Servers.HttpServer;
using OpenSim.Framework.ServiceAuth;
using OpenSim.Server.Handlers.Base; using OpenSim.Server.Handlers.Base;
using log4net; using log4net;
using OpenMetaverse; using OpenMetaverse;
@ -60,9 +59,7 @@ namespace OpenSim.OfflineIM
m_OfflineIMService = new OfflineIMService(config); m_OfflineIMService = new OfflineIMService(config);
IServiceAuth auth = ServiceAuth.Create(config, m_ConfigName); server.AddStreamHandler(new OfflineIMServicePostHandler(m_OfflineIMService));
server.AddStreamHandler(new OfflineIMServicePostHandler(m_OfflineIMService, auth));
} }
} }
@ -72,8 +69,8 @@ namespace OpenSim.OfflineIM
private IOfflineIMService m_OfflineIMService; private IOfflineIMService m_OfflineIMService;
public OfflineIMServicePostHandler(IOfflineIMService service, IServiceAuth auth) : public OfflineIMServicePostHandler(IOfflineIMService service) :
base("POST", "/offlineim", auth) base("POST", "/offlineim")
{ {
m_OfflineIMService = service; m_OfflineIMService = service;
} }
@ -99,20 +96,19 @@ namespace OpenSim.OfflineIM
string method = request["METHOD"].ToString(); string method = request["METHOD"].ToString();
request.Remove("METHOD"); request.Remove("METHOD");
m_log.DebugFormat("[OfflineIM.V2.Handler]: {0}", method);
switch (method) switch (method)
{ {
case "GET": case "GET":
return HandleGet(request); return HandleGet(request);
case "STORE": case "STORE":
return HandleStore(request); return HandleStore(request);
case "DELETE":
return HandleDelete(request);
} }
m_log.DebugFormat("[OFFLINE IM HANDLER]: unknown method request: {0}", method); m_log.DebugFormat("[OFFLINE IM HANDLER]: unknown method request: {0}", method);
} }
catch (Exception e) catch (Exception e)
{ {
m_log.Error(string.Format("[OFFLINE IM HANDLER]: Exception {0} ", e.Message), e); m_log.DebugFormat("[OFFLINE IM HANDLER]: Exception {0}", e.StackTrace);
} }
return FailureResult(); return FailureResult();
@ -163,21 +159,6 @@ namespace OpenSim.OfflineIM
return Util.UTF8NoBomEncoding.GetBytes(xmlString); return Util.UTF8NoBomEncoding.GetBytes(xmlString);
} }
byte[] HandleDelete(Dictionary<string, object> request)
{
if (!request.ContainsKey("UserID"))
{
return FailureResult();
}
else
{
UUID userID = new UUID(request["UserID"].ToString());
m_OfflineIMService.DeleteMessages(userID);
return SuccessResult();
}
}
#region Helpers #region Helpers
private void NullResult(Dictionary<string, object> result, string reason) private void NullResult(Dictionary<string, object> result, string reason)
@ -215,7 +196,18 @@ namespace OpenSim.OfflineIM
rootElement.AppendChild(result); rootElement.AppendChild(result);
return Util.DocToBytes(doc); return DocToBytes(doc);
}
private byte[] DocToBytes(XmlDocument doc)
{
MemoryStream ms = new MemoryStream();
XmlTextWriter xw = new XmlTextWriter(ms, null);
xw.Formatting = Formatting.Indented;
doc.WriteTo(xw);
xw.Flush();
return ms.ToArray();
} }
#endregion #endregion

View File

@ -1,4 +1,4 @@
/* /*
* Copyright (c) Contributors, http://opensimulator.org/ * Copyright (c) Contributors, http://opensimulator.org/
* See CONTRIBUTORS.TXT for a full list of copyright holders. * See CONTRIBUTORS.TXT for a full list of copyright holders.
* *
@ -90,8 +90,8 @@ namespace OpenSim.OfflineIM
public bool StoreMessage(GridInstantMessage im, out string reason) public bool StoreMessage(GridInstantMessage im, out string reason)
{ {
reason = string.Empty; reason = string.Empty;
// Check limits // TODO Check limits
UUID principalID = new UUID(im.toAgentID); UUID principalID = new UUID(im.toAgentID);
long count = m_Database.GetCount("PrincipalID", principalID.ToString()); long count = m_Database.GetCount("PrincipalID", principalID.ToString());
if (count >= MAX_IM) if (count >= MAX_IM)
@ -100,35 +100,32 @@ namespace OpenSim.OfflineIM
return false; return false;
} }
string imXml; string imXml = string.Empty;
using (MemoryStream mstream = new MemoryStream()) using (MemoryStream mstream = new MemoryStream())
{ {
XmlWriterSettings settings = new XmlWriterSettings(); XmlWriterSettings settings = new XmlWriterSettings();
settings.Encoding = Util.UTF8NoBomEncoding; settings.Encoding = Encoding.UTF8;
using (XmlWriter writer = XmlWriter.Create(mstream, settings)) using (XmlWriter writer = XmlWriter.Create(mstream, settings))
{ {
m_serializer.Serialize(writer, im); m_serializer.Serialize(writer, im);
writer.Flush(); writer.Flush();
imXml = Util.UTF8NoBomEncoding.GetString(mstream.ToArray());
mstream.Position = 0;
using (StreamReader sreader = new StreamReader(mstream))
{
imXml = sreader.ReadToEnd();
}
} }
} }
OfflineIMData data = new OfflineIMData(); OfflineIMData data = new OfflineIMData();
data.PrincipalID = principalID; data.PrincipalID = principalID;
data.FromID = new UUID(im.fromAgentID);
data.Data = new Dictionary<string, string>(); data.Data = new Dictionary<string, string>();
data.Data["Message"] = imXml; data.Data["Message"] = imXml;
return m_Database.Store(data); return m_Database.Store(data);
} }
public void DeleteMessages(UUID userID)
{
m_Database.Delete("PrincipalID", userID.ToString());
m_Database.Delete("FromID", userID.ToString());
}
} }
} }

View File

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

View File

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

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

View File

@ -32,13 +32,11 @@ using log4net;
using Mono.Addins; using Mono.Addins;
using Nini.Config; using Nini.Config;
using OpenSim; using OpenSim;
using OpenSim.Framework;
using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.Framework.Interfaces;
using OpenSim.Region.Framework.Scenes; using OpenSim.Region.Framework.Scenes;
namespace OpenSim.ApplicationPlugins.RegionModulesController namespace OpenSim.ApplicationPlugins.RegionModulesController
{ {
[Extension(Path = "/OpenSim/Startup", Id = "LoadRegions", NodeName = "Plugin")]
public class RegionModulesControllerPlugin : IRegionModulesController, public class RegionModulesControllerPlugin : IRegionModulesController,
IApplicationPlugin IApplicationPlugin
{ {
@ -47,12 +45,6 @@ namespace OpenSim.ApplicationPlugins.RegionModulesController
LogManager.GetLogger( LogManager.GetLogger(
MethodBase.GetCurrentMethod().DeclaringType); MethodBase.GetCurrentMethod().DeclaringType);
/// <summary>
/// Controls whether we load modules from Mono.Addins.
/// </summary>
/// <remarks>For debug purposes. Defaults to true.</remarks>
public bool LoadModulesFromAddins { get; set; }
// Config access // Config access
private OpenSimBase m_openSim; private OpenSimBase m_openSim;
@ -69,22 +61,14 @@ namespace OpenSim.ApplicationPlugins.RegionModulesController
private List<ISharedRegionModule> m_sharedInstances = private List<ISharedRegionModule> m_sharedInstances =
new List<ISharedRegionModule>(); new List<ISharedRegionModule>();
public RegionModulesControllerPlugin()
{
LoadModulesFromAddins = true;
}
#region IApplicationPlugin implementation #region IApplicationPlugin implementation
public void Initialise (OpenSimBase openSim) public void Initialise (OpenSimBase openSim)
{ {
m_openSim = openSim; m_openSim = openSim;
m_openSim.ApplicationRegistry.RegisterInterface<IRegionModulesController>(this); m_openSim.ApplicationRegistry.RegisterInterface<IRegionModulesController>(this);
m_log.DebugFormat("[REGIONMODULES]: Initializing..."); m_log.DebugFormat("[REGIONMODULES]: Initializing...");
if (!LoadModulesFromAddins)
return;
// Who we are // Who we are
string id = AddinManager.CurrentAddin.Id; string id = AddinManager.CurrentAddin.Id;
@ -104,14 +88,46 @@ namespace OpenSim.ApplicationPlugins.RegionModulesController
Dictionary<RuntimeAddin, IList<int>> loadedModules = new Dictionary<RuntimeAddin, IList<int>>(); Dictionary<RuntimeAddin, IList<int>> loadedModules = new Dictionary<RuntimeAddin, IList<int>>();
// Scan modules and load all that aren't disabled // Scan modules and load all that aren't disabled
foreach (TypeExtensionNode node in AddinManager.GetExtensionNodes("/OpenSim/RegionModules")) foreach (TypeExtensionNode node in
AddNode(node, modulesConfig, loadedModules); AddinManager.GetExtensionNodes("/OpenSim/RegionModules"))
{
IList<int> loadedModuleData;
if (!loadedModules.ContainsKey(node.Addin))
loadedModules.Add(node.Addin, new List<int> { 0, 0, 0 });
loadedModuleData = loadedModules[node.Addin];
if (node.Type.GetInterface(typeof(ISharedRegionModule).ToString()) != null)
{
if (CheckModuleEnabled(node, modulesConfig))
{
m_log.DebugFormat("[REGIONMODULES]: Found shared region module {0}, class {1}", node.Id, node.Type);
m_sharedModules.Add(node);
loadedModuleData[0]++;
}
}
else if (node.Type.GetInterface(typeof(INonSharedRegionModule).ToString()) != null)
{
if (CheckModuleEnabled(node, modulesConfig))
{
m_log.DebugFormat("[REGIONMODULES]: Found non-shared region module {0}, class {1}", node.Id, node.Type);
m_nonSharedModules.Add(node);
loadedModuleData[1]++;
}
}
else
{
m_log.WarnFormat("[REGIONMODULES]: Found unknown type of module {0}, class {1}", node.Id, node.Type);
loadedModuleData[2]++;
}
}
foreach (KeyValuePair<RuntimeAddin, IList<int>> loadedModuleData in loadedModules) foreach (KeyValuePair<RuntimeAddin, IList<int>> loadedModuleData in loadedModules)
{ {
m_log.InfoFormat( m_log.InfoFormat(
"[REGIONMODULES]: From plugin {0}, (version {1}), loaded {2} modules, {3} shared, {4} non-shared {5} unknown", "[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.Key.Version,
loadedModuleData.Value[0] + loadedModuleData.Value[1] + loadedModuleData.Value[2], loadedModuleData.Value[0] + loadedModuleData.Value[1] + loadedModuleData.Value[2],
loadedModuleData.Value[0], loadedModuleData.Value[1], loadedModuleData.Value[2]); loadedModuleData.Value[0], loadedModuleData.Value[1], loadedModuleData.Value[2]);
@ -131,9 +147,6 @@ namespace OpenSim.ApplicationPlugins.RegionModulesController
// Read the config again // Read the config again
string moduleString = string moduleString =
modulesConfig.GetString("Setup_" + node.Id, String.Empty); 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 // Get the port number, if there is one
if (moduleString != String.Empty) if (moduleString != String.Empty)
@ -181,41 +194,6 @@ namespace OpenSim.ApplicationPlugins.RegionModulesController
#region IPlugin implementation #region IPlugin implementation
private void AddNode(
TypeExtensionNode node, IConfig modulesConfig, Dictionary<RuntimeAddin, IList<int>> loadedModules)
{
IList<int> loadedModuleData;
if (!loadedModules.ContainsKey(node.Addin))
loadedModules.Add(node.Addin, new List<int> { 0, 0, 0 });
loadedModuleData = loadedModules[node.Addin];
if (node.Type.GetInterface(typeof(ISharedRegionModule).ToString()) != null)
{
if (CheckModuleEnabled(node, modulesConfig))
{
m_log.DebugFormat("[REGIONMODULES]: Found shared region module {0}, class {1}", node.Id, node.Type);
m_sharedModules.Add(node);
loadedModuleData[0]++;
}
}
else if (node.Type.GetInterface(typeof(INonSharedRegionModule).ToString()) != null)
{
if (CheckModuleEnabled(node, modulesConfig))
{
m_log.DebugFormat("[REGIONMODULES]: Found non-shared region module {0}, class {1}", node.Id, node.Type);
m_nonSharedModules.Add(node);
loadedModuleData[1]++;
}
}
else
{
m_log.WarnFormat("[REGIONMODULES]: Found unknown type of module {0}, class {1}", node.Id, node.Type);
loadedModuleData[2]++;
}
}
// We don't do that here // We don't do that here
// //
public void Initialise () public void Initialise ()
@ -237,7 +215,6 @@ namespace OpenSim.ApplicationPlugins.RegionModulesController
m_sharedInstances[0].Close(); m_sharedInstances[0].Close();
m_sharedInstances.RemoveAt(0); m_sharedInstances.RemoveAt(0);
} }
m_sharedModules.Clear(); m_sharedModules.Clear();
m_nonSharedModules.Clear(); m_nonSharedModules.Clear();
} }
@ -261,7 +238,7 @@ namespace OpenSim.ApplicationPlugins.RegionModulesController
} }
#region Region Module interfacesController implementation #region Region Module interfacesController implementation
/// <summary> /// <summary>
/// Check that the given module is no disabled in the [Modules] section of the config files. /// Check that the given module is no disabled in the [Modules] section of the config files.
/// </summary> /// </summary>
@ -293,10 +270,10 @@ namespace OpenSim.ApplicationPlugins.RegionModulesController
if (className != String.Empty && if (className != String.Empty &&
node.Type.ToString() != className) node.Type.ToString() != className)
return false; return false;
} }
return true; return true;
} }
// The root of all evil. // The root of all evil.
// This is where we handle adding the modules to scenes when they // This is where we handle adding the modules to scenes when they
@ -368,10 +345,6 @@ namespace OpenSim.ApplicationPlugins.RegionModulesController
string moduleString = string moduleString =
modulesConfig.GetString("Setup_" + node.Id, String.Empty); 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 // Get the port number, if there is one
if (moduleString != String.Empty) if (moduleString != String.Empty)
{ {
@ -509,8 +482,6 @@ namespace OpenSim.ApplicationPlugins.RegionModulesController
{ {
module.RegionLoaded(scene); module.RegionLoaded(scene);
} }
scene.AllModulesLoaded();
} }
public void RemoveRegionFromModules (Scene scene) 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.Reflection;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.Runtime.InteropServices; 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 // set of attributes. Change these attribute values to modify the information
// associated with an assembly. // associated with an assembly.
[assembly: AssemblyTitle("OpenSim.ApplicationPlugins.RemoteController")] [assembly: AssemblyTitle("OpenSim.ApplicationPlugins.RemoteController")]
@ -15,8 +14,8 @@ using Mono.Addins;
[assembly: AssemblyTrademark("")] [assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")] [assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible // 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 // to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type. // COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)] [assembly: ComVisible(false)]
@ -26,11 +25,9 @@ using Mono.Addins;
// Version information for an assembly consists of the following four values: // Version information for an assembly consists of the following four values:
// //
// Major Version // Major Version
// Minor Version // Minor Version
// Build Number // Build Number
// Revision // Revision
// //
[assembly: AssemblyVersion(OpenSim.VersionInfo.AssemblyVersionNumber)] [assembly: AssemblyVersion("0.7.6.*")]
[assembly: Addin("OpenSim.ApplicationPlugins.RemoteController", OpenSim.VersionInfo.VersionNumber)]
[assembly: AddinDependency("OpenSim", OpenSim.VersionInfo.VersionNumber)]

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;
using System.Collections; using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.Concurrent;
using System.IO; using System.IO;
using System.Reflection; using System.Reflection;
using System.Threading;
using log4net; using log4net;
using Nini.Config; using Nini.Config;
using OpenMetaverse; using OpenMetaverse;
@ -50,9 +48,10 @@ namespace OpenSim.Framework.Capabilities
/// </summary> /// </summary>
public delegate IClientAPI GetClientDelegate(UUID agentID); 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 string m_httpListenerHostName;
private uint m_httpListenPort; private uint m_httpListenPort;
@ -65,15 +64,14 @@ namespace OpenSim.Framework.Capabilities
private CapsHandlers m_capsHandlers; private CapsHandlers m_capsHandlers;
private ConcurrentDictionary<string, PollServiceEventArgs> m_pollServiceHandlers private Dictionary<string, PollServiceEventArgs> m_pollServiceHandlers
= new ConcurrentDictionary<string, PollServiceEventArgs>(); = new Dictionary<string, PollServiceEventArgs>();
private Dictionary<string, string> m_externalCapsHandlers = new Dictionary<string, string>(); private Dictionary<string, string> m_externalCapsHandlers = new Dictionary<string, string>();
private IHttpServer m_httpListener; private IHttpServer m_httpListener;
private UUID m_agentID; private UUID m_agentID;
private string m_regionName; private string m_regionName;
private ManualResetEvent m_capsActive = new ManualResetEvent(false);
public UUID AgentID public UUID AgentID
{ {
@ -120,19 +118,6 @@ namespace OpenSim.Framework.Capabilities
get { return m_externalCapsHandlers; } 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, public Caps(IHttpServer httpServer, string httpListen, uint httpPort, string capsPath,
UUID agent, string regionName) UUID agent, string regionName)
{ {
@ -150,37 +135,8 @@ namespace OpenSim.Framework.Capabilities
} }
m_agentID = agent; 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; 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> /// <summary>
@ -194,32 +150,16 @@ namespace OpenSim.Framework.Capabilities
m_capsHandlers[capName] = handler; 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) public void RegisterPollHandler(string capName, PollServiceEventArgs pollServiceHandler)
{ {
// m_log.DebugFormat( m_pollServiceHandlers.Add(capName, pollServiceHandler);
// "[CAPS]: Registering handler with name {0}, url {1} for {2}",
// capName, pollServiceHandler.Url, m_agentID, m_regionName);
if(!m_pollServiceHandlers.TryAdd(capName, pollServiceHandler)) m_httpListener.AddPollServiceHTTPHandler(pollServiceHandler.Url, 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_httpListener.AddPollServiceHTTPHandler(pollServiceHandler);
// uint port = (MainServer.Instance == null) ? 0 : MainServer.Instance.Port; // uint port = (MainServer.Instance == null) ? 0 : MainServer.Instance.Port;
// string protocol = "http"; // string protocol = "http";
// string hostName = m_httpListenerHostName; // string hostName = m_httpListenerHostName;
// //
// if (MainServer.Instance.UseSSL) // if (MainServer.Instance.UseSSL)
// { // {
// hostName = MainServer.Instance.SSLCommonName; // hostName = MainServer.Instance.SSLCommonName;
@ -254,9 +194,8 @@ namespace OpenSim.Framework.Capabilities
foreach (PollServiceEventArgs handler in m_pollServiceHandlers.Values) 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) public bool TryGetPollHandler(string name, out PollServiceEventArgs pollHandler)
@ -288,13 +227,16 @@ namespace OpenSim.Framework.Capabilities
string hostName = m_httpListenerHostName; string hostName = m_httpListenerHostName;
uint port = (MainServer.Instance == null) ? 0 : MainServer.Instance.Port; uint port = (MainServer.Instance == null) ? 0 : MainServer.Instance.Port;
string protocol = "http"; string protocol = "http";
if (MainServer.Instance.UseSSL) if (MainServer.Instance.UseSSL)
{ {
hostName = MainServer.Instance.SSLCommonName; hostName = MainServer.Instance.SSLCommonName;
port = MainServer.Instance.SSLPort; port = MainServer.Instance.SSLPort;
protocol = "https"; 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); caps[kvp.Key] = string.Format("{0}://{1}:{2}{3}", protocol, hostName, port, kvp.Value.Url);
} }
} }
@ -308,19 +250,7 @@ namespace OpenSim.Framework.Capabilities
caps[kvp.Key] = kvp.Value; caps[kvp.Key] = kvp.Value;
} }
return caps; 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;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.Concurrent;
using OpenSim.Framework.Servers; using OpenSim.Framework.Servers;
using OpenSim.Framework.Servers.HttpServer; using OpenSim.Framework.Servers.HttpServer;
@ -41,7 +40,6 @@ namespace OpenSim.Framework.Capabilities
public class CapsHandlers public class CapsHandlers
{ {
private Dictionary<string, IRequestHandler> m_capsHandlers = new Dictionary<string, IRequestHandler>(); 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 IHttpServer m_httpListener;
private string m_httpListenerHostName; private string m_httpListenerHostName;
private uint m_httpListenerPort; private uint m_httpListenerPort;
@ -55,15 +53,31 @@ namespace OpenSim.Framework.Capabilities
/// <param name="httpListener">base HTTP server</param> /// <param name="httpListener">base HTTP server</param>
/// <param name="httpListenerHostname">host name of the HTTP server</param> /// <param name="httpListenerHostname">host name of the HTTP server</param>
/// <param name="httpListenerPort">HTTP port</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_httpListener = httpListener;
m_httpListenerHostName = httpListenerHostname; m_httpListenerHostName = httpListenerHostname;
m_httpListenerPort = httpListenerPort; m_httpListenerPort = httpListenerPort;
if (httpListener != null && httpListener.UseSSL) m_useSSL = https;
m_useSSL = true; if (httpListener != null && m_useSSL)
else {
m_useSSL = false; m_httpListenerHostName = httpListener.SSLCommonName;
m_httpListenerPort = httpListener.SSLPort;
}
} }
/// <summary> /// <summary>
@ -75,35 +89,16 @@ namespace OpenSim.Framework.Capabilities
{ {
lock (m_capsHandlers) lock (m_capsHandlers)
{ {
if(m_capsHandlers.ContainsKey(capsName)) m_httpListener.RemoveStreamHandler("POST", m_capsHandlers[capsName].Path);
{ m_httpListener.RemoveStreamHandler("GET", m_capsHandlers[capsName].Path);
m_httpListener.RemoveStreamHandler("POST", m_capsHandlers[capsName].Path); m_capsHandlers.Remove(capsName);
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);
}
} }
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) public bool ContainsCap(string cap)
{ {
lock (m_capsHandlers) lock (m_capsHandlers)
if (m_capsHandlers.ContainsKey(cap)) return m_capsHandlers.ContainsKey(cap);
return true;
return m_capsSimpleHandlers.ContainsKey(cap);
} }
/// <summary> /// <summary>
@ -130,14 +125,11 @@ namespace OpenSim.Framework.Capabilities
if (m_capsHandlers.ContainsKey(idx)) if (m_capsHandlers.ContainsKey(idx))
{ {
m_httpListener.RemoveStreamHandler("POST", m_capsHandlers[idx].Path); 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); m_capsHandlers.Remove(idx);
} }
if (null == value) return; if (null == value) return;
m_capsHandlers[idx] = value; m_capsHandlers[idx] = value;
m_httpListener.AddStreamHandler(value); m_httpListener.AddStreamHandler(value);
} }
@ -154,9 +146,8 @@ namespace OpenSim.Framework.Capabilities
{ {
lock (m_capsHandlers) 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_capsHandlers.Keys.CopyTo(__keys, 0);
m_capsSimpleHandlers.Keys.CopyTo(__keys, m_capsHandlers.Keys.Count);
return __keys; return __keys;
} }
} }
@ -170,39 +161,24 @@ namespace OpenSim.Framework.Capabilities
public Hashtable GetCapsDetails(bool excludeSeed, List<string> requestedCaps) public Hashtable GetCapsDetails(bool excludeSeed, List<string> requestedCaps)
{ {
Hashtable caps = new Hashtable(); 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(); 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) 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) if (excludeSeed && "SEED" == capsName)
continue; continue;
if (m_capsSimpleHandlers.TryGetValue(capsName, out ISimpleStreamHandler shdr)) if (requestedCaps != null && !requestedCaps.Contains(capsName))
{
caps[capsName] = baseUrl + shdr.Path;
continue; continue;
}
if (m_capsHandlers.TryGetValue(capsName, out IRequestHandler chdr)) caps[capsName] = baseUrl + m_capsHandlers[capsName].Path;
{
caps[capsName] = baseUrl + chdr.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) if (m_InventoryService == null)
throw new Exception(String.Format("Failed to load InventoryService from {0}; config is {1}", invService, m_ConfigName)); 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 IRequestHandler reqHandler
= new RestStreamHandler( = new RestStreamHandler(
"POST", "/CAPS/FetchInventory/", fiHandler.FetchInventoryRequest, "FetchInventory", null); "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

@ -43,112 +43,73 @@ using Caps = OpenSim.Framework.Capabilities.Caps;
namespace OpenSim.Capabilities.Handlers namespace OpenSim.Capabilities.Handlers
{ {
public class GetMeshHandler public class GetMeshHandler
{ {
private static readonly ILog m_log = // private static readonly ILog m_log =
LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); // LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private IAssetService m_assetService; private IAssetService m_assetService;
public const string DefaultFormat = "vnd.ll.mesh";
public GetMeshHandler(IAssetService assService) public GetMeshHandler(IAssetService assService)
{ {
m_assetService = assService; m_assetService = assService;
} }
public Hashtable Handle(Hashtable request)
{
return ProcessGetMesh(request, UUID.Zero, null); ;
}
public Hashtable ProcessGetMesh(Hashtable request, UUID AgentId, Caps cap) public Hashtable ProcessGetMesh(Hashtable request, UUID AgentId, Caps cap)
{ {
Hashtable responsedata = new Hashtable(); Hashtable responsedata = new Hashtable();
if (m_assetService == null) responsedata["int_response_code"] = 400; //501; //410; //404;
{
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["content_type"] = "text/plain";
responsedata["int_bytes"] = 0; responsedata["keepalive"] = false;
responsedata["str_response_string"] = "Request wasn't what was expected";
string meshStr = string.Empty; string meshStr = string.Empty;
if (request.ContainsKey("mesh_id")) if (request.ContainsKey("mesh_id"))
meshStr = request["mesh_id"].ToString(); meshStr = request["mesh_id"].ToString();
if (String.IsNullOrEmpty(meshStr))
return responsedata;
UUID meshID = UUID.Zero; UUID meshID = UUID.Zero;
if(!UUID.TryParse(meshStr, out meshID)) if (!String.IsNullOrEmpty(meshStr) && UUID.TryParse(meshStr, out meshID))
return responsedata;
AssetBase mesh = m_assetService.Get(meshID.ToString());
if(mesh == null)
{ {
responsedata["int_response_code"] = (int)System.Net.HttpStatusCode.NotFound; if (m_assetService == null)
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)
{ {
responsedata["str_response_string"] = "This range doesnt exist."; responsedata["int_response_code"] = 404; //501; //410; //404;
responsedata["content_type"] = "text/plain";
responsedata["keepalive"] = false;
responsedata["str_response_string"] = "The asset service is unavailable. So is your mesh.";
return responsedata; return responsedata;
} }
end = Utils.Clamp(end, 0, mesh.Data.Length - 1); AssetBase mesh = m_assetService.Get(meshID.ToString());
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); if (mesh != null)
Hashtable headers = new Hashtable(); {
headers["Content-Range"] = String.Format("bytes {0}-{1}/{2}", start, end, mesh.Data.Length); if (mesh.Type == (SByte)AssetType.Mesh)
responsedata["headers"] = headers; {
responsedata["int_response_code"] = (int)System.Net.HttpStatusCode.PartialContent; responsedata["str_response_string"] = Convert.ToBase64String(mesh.Data);
responsedata["content_type"] = "application/vnd.ll.mesh";
byte[] d = new byte[len]; responsedata["int_response_code"] = 200;
Array.Copy(mesh.Data, start, d, 0, len); }
responsedata["bin_response_data"] = d; // Optionally add additional mesh types here
responsedata["int_bytes"] = len; else
return responsedata; {
responsedata["int_response_code"] = 404; //501; //410; //404;
responsedata["content_type"] = "text/plain";
responsedata["keepalive"] = false;
responsedata["str_response_string"] = "Unfortunately, this asset isn't a mesh.";
return responsedata;
}
}
else
{
responsedata["int_response_code"] = 404; //501; //410; //404;
responsedata["content_type"] = "text/plain";
responsedata["keepalive"] = false;
responsedata["str_response_string"] = "Your Mesh wasn't found. Sorry!";
return responsedata;
}
} }
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 responsedata;
} }
} }

View File

@ -25,13 +25,16 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * 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;
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 namespace OpenSim.Capabilities.Handlers
{ {
@ -62,17 +65,15 @@ namespace OpenSim.Capabilities.Handlers
if (m_AssetService == null) if (m_AssetService == null)
throw new Exception(String.Format("Failed to load AssetService from {0}; config is {1}", assetService, m_ConfigName)); 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); GetMeshHandler gmeshHandler = new GetMeshHandler(m_AssetService);
IRequestHandler reqHandler IRequestHandler reqHandler
= new RestHTTPHandler( = new RestHTTPHandler(
"GET", "GET",
"/" + UUID.Random(), "/CAPS/" + UUID.Random(),
httpMethod => gmeshHandler.ProcessGetMesh(httpMethod, UUID.Zero, null), httpMethod => gmeshHandler.ProcessGetMesh(httpMethod, UUID.Zero, null),
"GetMesh", "GetMesh",
null); null);
server.AddStreamHandler(reqHandler); ; server.AddStreamHandler(reqHandler);
} }
} }
} }

View File

@ -47,92 +47,85 @@ using Caps = OpenSim.Framework.Capabilities.Caps;
namespace OpenSim.Capabilities.Handlers namespace OpenSim.Capabilities.Handlers
{ {
public class GetTextureHandler public class GetTextureHandler : BaseStreamHandler
{ {
private static readonly ILog m_log = private static readonly ILog m_log =
LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private IAssetService m_assetService; private IAssetService m_assetService;
public const string DefaultFormat = "x-j2c"; public const string DefaultFormat = "x-j2c";
public GetTextureHandler(IAssetService assService) // TODO: Change this to a config option
const string REDIRECT_URL = null;
public GetTextureHandler(string path, IAssetService assService, string name, string description)
: base("GET", path, name, description)
{ {
m_assetService = assService; m_assetService = assService;
} }
public Hashtable Handle(Hashtable request) protected override byte[] ProcessRequest(string path, Stream request, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
{ {
Hashtable ret = new Hashtable(); // Try to parse the texture ID from the request URL
ret["int_response_code"] = (int)System.Net.HttpStatusCode.NotFound; NameValueCollection query = HttpUtility.ParseQueryString(httpRequest.Url.Query);
ret["content_type"] = "text/plain"; string textureStr = query.GetOne("texture_id");
ret["int_bytes"] = 0; string format = query.GetOne("format");
string textureStr = (string)request["texture_id"];
string format = (string)request["format"];
//m_log.DebugFormat("[GETTEXTURE]: called {0}", textureStr); //m_log.DebugFormat("[GETTEXTURE]: called {0}", textureStr);
if (m_assetService == null) if (m_assetService == null)
{ {
m_log.Error("[GETTEXTURE]: Cannot fetch texture " + textureStr + " without an asset service"); m_log.Error("[GETTEXTURE]: Cannot fetch texture " + textureStr + " without an asset service");
httpResponse.StatusCode = (int)System.Net.HttpStatusCode.NotFound;
} }
UUID textureID; UUID textureID;
if (!String.IsNullOrEmpty(textureStr) && UUID.TryParse(textureStr, out textureID)) if (!String.IsNullOrEmpty(textureStr) && UUID.TryParse(textureStr, out textureID))
{ {
// m_log.DebugFormat("[GETTEXTURE]: Received request for texture id {0}", textureID); // m_log.DebugFormat("[GETTEXTURE]: Received request for texture id {0}", textureID);
string[] formats; string[] formats;
if (!string.IsNullOrEmpty(format)) if (format != null && format != string.Empty)
{ {
formats = new string[1] { format.ToLower() }; formats = new string[1] { format.ToLower() };
} }
else else
{ {
formats = new string[1] { DefaultFormat }; // default formats = WebUtil.GetPreferredImageTypes(httpRequest.Headers.Get("Accept"));
if (((Hashtable)request["headers"])["Accept"] != null)
formats = WebUtil.GetPreferredImageTypes((string)((Hashtable)request["headers"])["Accept"]);
if (formats.Length == 0) if (formats.Length == 0)
formats = new string[1] { DefaultFormat }; // default formats = new string[1] { DefaultFormat }; // default
} }
// OK, we have an array with preferred formats, possibly with only one entry // 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) foreach (string f in formats)
{ {
foundtexture = FetchTexture(request, ret, textureID, f); if (FetchTexture(httpRequest, httpResponse, textureID, f))
if (foundtexture)
break; 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 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( // m_log.DebugFormat(
// "[GETTEXTURE]: For texture {0} sending back response {1}, data length {2}", // "[GETTEXTURE]: For texture {0} sending back response {1}, data length {2}",
// textureID, httpResponse.StatusCode, httpResponse.ContentLength); // textureID, httpResponse.StatusCode, httpResponse.ContentLength);
return ret;
return null;
} }
/// <summary> /// <summary>
/// ///
/// </summary> /// </summary>
/// <param name="httpRequest"></param> /// <param name="httpRequest"></param>
/// <param name="httpResponse"></param> /// <param name="httpResponse"></param>
/// <param name="textureID"></param> /// <param name="textureID"></param>
/// <param name="format"></param> /// <param name="format"></param>
/// <returns>False for "caller try another codec"; true otherwise</returns> /// <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); // m_log.DebugFormat("[GETTEXTURE]: {0} with requested format {1}", textureID, format);
AssetBase texture; AssetBase texture;
@ -141,76 +134,91 @@ namespace OpenSim.Capabilities.Handlers
if (format != DefaultFormat) if (format != DefaultFormat)
fullID = fullID + "-" + format; fullID = fullID + "-" + format;
// try the cache if (!String.IsNullOrEmpty(REDIRECT_URL))
texture = m_assetService.GetCached(fullID);
if (texture == null)
{ {
//m_log.DebugFormat("[GETTEXTURE]: texture was not in the cache"); // Only try to fetch locally cached textures. Misses are redirected
texture = m_assetService.GetCached(fullID);
// Fetch locally or remotely. Misses return a 404
texture = m_assetService.Get(textureID.ToString());
if (texture != null) if (texture != null)
{ {
if (texture.Type != (sbyte)AssetType.Texture) if (texture.Type != (sbyte)AssetType.Texture)
return true;
if (format == DefaultFormat)
{ {
WriteTextureData(request, response, texture, format); httpResponse.StatusCode = (int)System.Net.HttpStatusCode.NotFound;
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);
return true; return true;
} }
WriteTextureData(httpRequest, httpResponse, texture, format);
} }
} else
else // it was on the cache {
{ string textureUrl = REDIRECT_URL + textureID.ToString();
//m_log.DebugFormat("[GETTEXTURE]: texture was in the cache"); m_log.Debug("[GETTEXTURE]: Redirecting texture request to " + textureUrl);
WriteTextureData(request, response, texture, format); httpResponse.RedirectLocation = textureUrl;
return true; 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 // not found
//m_log.Warn("[GETTEXTURE]: Texture " + textureID + " not found"); // m_log.Warn("[GETTEXTURE]: Texture " + textureID + " not found");
return false; 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(); string range = request.Headers.GetOne("Range");
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"];
if (!String.IsNullOrEmpty(range)) // JP2's only if (!String.IsNullOrEmpty(range)) // JP2's only
{ {
// Range request // Range request
int start, end; 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 // Before clamping start make sure we can satisfy it in order to avoid
// sending back the last byte instead of an error status // sending back the last byte instead of an error status
@ -232,8 +240,10 @@ namespace OpenSim.Capabilities.Handlers
// However, if we return PartialContent (or OK) instead, the viewer will display that resolution. // However, if we return PartialContent (or OK) instead, the viewer will display that resolution.
// response.StatusCode = (int)System.Net.HttpStatusCode.RequestedRangeNotSatisfiable; // response.StatusCode = (int)System.Net.HttpStatusCode.RequestedRangeNotSatisfiable;
// viewers don't seem to handle RequestedRangeNotSatisfiable and keep retrying with same parameters // response.AddHeader("Content-Range", String.Format("bytes */{0}", texture.Data.Length));
response["int_response_code"] = (int)System.Net.HttpStatusCode.NotFound; // response.StatusCode = (int)System.Net.HttpStatusCode.OK;
response.StatusCode = (int)System.Net.HttpStatusCode.PartialContent;
response.ContentType = texture.Metadata.ContentType;
} }
else else
{ {
@ -248,35 +258,41 @@ namespace OpenSim.Capabilities.Handlers
// m_log.Debug("Serving " + start + " to " + end + " of " + texture.Data.Length + " bytes for texture " + texture.ID); // m_log.Debug("Serving " + start + " to " + end + " of " + texture.Data.Length + " bytes for texture " + texture.ID);
response["content-type"] = texture.Metadata.ContentType; // Always return PartialContent, even if the range covered the entire data length
response["int_response_code"] = (int)System.Net.HttpStatusCode.PartialContent; // We were accidentally sending back 404 before in this situation
headers["Content-Range"] = String.Format("bytes {0}-{1}/{2}", start, end, texture.Data.Length); // 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]; response.ContentLength = len;
Array.Copy(texture.Data, start, d, 0, len); response.ContentType = texture.Metadata.ContentType;
response["bin_response_data"] = d; response.AddHeader("Content-Range", String.Format("bytes {0}-{1}/{2}", start, end, texture.Data.Length));
response["int_bytes"] = len;
response.Body.Write(texture.Data, start, len);
} }
} }
else else
{ {
m_log.Warn("[GETTEXTURE]: Malformed Range header: " + range); 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 else // JP2's or other formats
{ {
// Full content request // 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) if (format == DefaultFormat)
response["content_type"] = texture.Metadata.ContentType; response.ContentType = texture.Metadata.ContentType;
else else
response["content_type"] = "image/" + format; response.ContentType = "image/" + format;
response.Body.Write(texture.Data, 0, texture.Data.Length);
response["bin_response_data"] = texture.Data;
response["int_bytes"] = texture.Data.Length;
// response.Body.Write(texture.Data, 0, texture.Data.Length);
} }
// if (response.StatusCode < 200 || response.StatusCode > 299) // if (response.StatusCode < 200 || response.StatusCode > 299)
@ -289,41 +305,86 @@ namespace OpenSim.Capabilities.Handlers
// texture.FullID, range, response.StatusCode, response.ContentLength, texture.Data.Length); // 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) private byte[] ConvertTextureData(AssetBase texture, string format)
{ {
m_log.DebugFormat("[GETTEXTURE]: Converting texture {0} to {1}", texture.ID, format); m_log.DebugFormat("[GETTEXTURE]: Converting texture {0} to {1}", texture.ID, format);
byte[] data = new byte[0]; byte[] data = new byte[0];
MemoryStream imgstream = new MemoryStream(); MemoryStream imgstream = new MemoryStream();
Bitmap mTexture = null; Bitmap mTexture = new Bitmap(1, 1);
ManagedImage managedImage = null; ManagedImage managedImage;
Image image = null; Image image = (Image)mTexture;
try try
{ {
// Taking our jpeg2000 data, decoding it, then saving it to a byte array with regular data // 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 // 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 // Save to bitmap
mTexture = new Bitmap(image); mTexture = new Bitmap(image);
using(EncoderParameters myEncoderParameters = new EncoderParameters()) EncoderParameters myEncoderParameters = new EncoderParameters();
{ myEncoderParameters.Param[0] = new EncoderParameter(Encoder.Quality, 95L);
myEncoderParameters.Param[0] = new EncoderParameter(Encoder.Quality,95L);
// Save bitmap to stream // Save bitmap to stream
ImageCodecInfo codec = GetEncoderInfo("image/" + format); ImageCodecInfo codec = GetEncoderInfo("image/" + format);
if (codec != null) if (codec != null)
{ {
mTexture.Save(imgstream, codec, myEncoderParameters); mTexture.Save(imgstream, codec, myEncoderParameters);
// Write the stream to a byte array for output // Write the stream to a byte array for output
data = imgstream.ToArray(); data = imgstream.ToArray();
}
else
m_log.WarnFormat("[GETTEXTURE]: No such codec {0}", format);
} }
else
m_log.WarnFormat("[GETTEXTURE]: No such codec {0}", format);
} }
} }
catch (Exception e) catch (Exception e)
@ -340,10 +401,11 @@ namespace OpenSim.Capabilities.Handlers
if (image != null) if (image != null)
image.Dispose(); image.Dispose();
if(managedImage != null)
managedImage.Clear();
if (imgstream != null) if (imgstream != null)
{
imgstream.Close();
imgstream.Dispose(); imgstream.Dispose();
}
} }
return data; return data;
@ -362,4 +424,4 @@ namespace OpenSim.Capabilities.Handlers
return null; 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 OpenSim.Server.Handlers.Base;
using OpenMetaverse; using OpenMetaverse;
namespace OpenSim.Capabilities.Handlers namespace OpenSim.Capabilities.Handlers
{ {
public class GetTextureServerConnector : ServiceConnector public class GetTextureServerConnector : ServiceConnector
@ -63,11 +62,8 @@ namespace OpenSim.Capabilities.Handlers
if (m_AssetService == null) if (m_AssetService == null)
throw new Exception(String.Format("Failed to load AssetService from {0}; config is {1}", assetService, m_ConfigName)); throw new Exception(String.Format("Failed to load AssetService from {0}; config is {1}", assetService, m_ConfigName));
string rurl = serverConfig.GetString("GetTextureRedirectURL");
;
server.AddStreamHandler( server.AddStreamHandler(
new GetTextureRobustHandler("/CAPS/GetTexture", m_AssetService, "GetTexture", null, rurl)); new GetTextureHandler("/CAPS/GetTexture/" /*+ UUID.Random() */, m_AssetService, "GetTexture", null));
} }
} }
} }

View File

@ -37,8 +37,8 @@ using OpenSim.Framework;
using OpenSim.Framework.Servers.HttpServer; using OpenSim.Framework.Servers.HttpServer;
using OpenSim.Region.Framework.Scenes; using OpenSim.Region.Framework.Scenes;
using OpenSim.Tests.Common; using OpenSim.Tests.Common;
using OpenSim.Tests.Common.Mock;
/*
namespace OpenSim.Capabilities.Handlers.GetTexture.Tests namespace OpenSim.Capabilities.Handlers.GetTexture.Tests
{ {
[TestFixture] [TestFixture]
@ -52,7 +52,7 @@ namespace OpenSim.Capabilities.Handlers.GetTexture.Tests
// Overkill - we only really need the asset service, not a whole scene. // Overkill - we only really need the asset service, not a whole scene.
Scene scene = new SceneHelpers().SetupScene(); Scene scene = new SceneHelpers().SetupScene();
GetTextureHandler handler = new GetTextureHandler("/gettexture", scene.AssetService, "TestGetTexture", null, null); GetTextureHandler handler = new GetTextureHandler(null, scene.AssetService, "TestGetTexture", null);
TestOSHttpRequest req = new TestOSHttpRequest(); TestOSHttpRequest req = new TestOSHttpRequest();
TestOSHttpResponse resp = new TestOSHttpResponse(); TestOSHttpResponse resp = new TestOSHttpResponse();
req.Url = new Uri("http://localhost/?texture_id=00000000-0000-1111-9999-000000000012"); req.Url = new Uri("http://localhost/?texture_id=00000000-0000-1111-9999-000000000012");
@ -60,5 +60,4 @@ namespace OpenSim.Capabilities.Handlers.GetTexture.Tests
Assert.That(resp.StatusCode, Is.EqualTo((int)System.Net.HttpStatusCode.NotFound)); Assert.That(resp.StatusCode, Is.EqualTo((int)System.Net.HttpStatusCode.NotFound));
} }
} }
} }
*/

View File

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

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

@ -29,18 +29,18 @@ using System;
using Nini.Config; using Nini.Config;
using OpenSim.Server.Base; using OpenSim.Server.Base;
using OpenSim.Services.Interfaces; using OpenSim.Services.Interfaces;
using OpenSim.Framework.ServiceAuth;
using OpenSim.Framework.Servers.HttpServer; using OpenSim.Framework.Servers.HttpServer;
using OpenSim.Server.Handlers.Base; using OpenSim.Server.Handlers.Base;
using OpenMetaverse;
namespace OpenSim.Server.Handlers.BakedTextures namespace OpenSim.Capabilities.Handlers
{ {
public class XBakesConnector : ServiceConnector public class UploadBakedTextureServerConnector : ServiceConnector
{ {
private IBakedTextureService m_BakesService; private IAssetService m_AssetService;
private string m_ConfigName = "BakedTextureService"; private string m_ConfigName = "CapsService";
public XBakesConnector(IConfigSource config, IHttpServer server, string configName) : public UploadBakedTextureServerConnector(IConfigSource config, IHttpServer server, string configName) :
base(config, server, configName) base(config, server, configName)
{ {
if (configName != String.Empty) if (configName != String.Empty)
@ -50,20 +50,27 @@ namespace OpenSim.Server.Handlers.BakedTextures
if (serverConfig == null) 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 assetService = serverConfig.GetString("LocalServiceModule", string assetService = serverConfig.GetString("AssetService", String.Empty);
String.Empty);
if (assetService == String.Empty) if (assetService == String.Empty)
throw new Exception("No BakedTextureService in config file"); throw new Exception("No AssetService in config file");
Object[] args = new Object[] { config }; Object[] args = new Object[] { config };
m_BakesService = m_AssetService =
ServerUtils.LoadPlugin<IBakedTextureService>(assetService, args); 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 BakesServerGetHandler(m_BakesService, auth)); // NEED TO FIX THIS
server.AddStreamHandler(new BakesServerPostHandler(m_BakesService, auth)); 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,438 @@
/*
* 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)
{
contents = m_InventoryService.GetFolderContent(agentID, folderID);
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 Nini.Config;
using OpenSim.Server.Base; using OpenSim.Server.Base;
using OpenSim.Services.Interfaces; using OpenSim.Services.Interfaces;
using OpenSim.Framework;
using OpenSim.Framework.Servers.HttpServer; using OpenSim.Framework.Servers.HttpServer;
using OpenSim.Server.Handlers.Base; using OpenSim.Server.Handlers.Base;
using OpenMetaverse; using OpenMetaverse;
using OpenMetaverse.StructuredData;
namespace OpenSim.Capabilities.Handlers namespace OpenSim.Capabilities.Handlers
{ {
public class FetchInvDescServerConnector : ServiceConnector public class WebFetchInvDescServerConnector : ServiceConnector
{ {
private IInventoryService m_InventoryService; private IInventoryService m_InventoryService;
private ILibraryService m_LibraryService; private ILibraryService m_LibraryService;
private string m_ConfigName = "CapsService"; 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) base(config, server, configName)
{ {
if (configName != String.Empty) if (configName != String.Empty)
@ -70,16 +67,16 @@ namespace OpenSim.Capabilities.Handlers
m_LibraryService = m_LibraryService =
ServerUtils.LoadPlugin<ILibraryService>(libService, args); ServerUtils.LoadPlugin<ILibraryService>(libService, args);
ExpiringKey<UUID> m_badRequests = new ExpiringKey<UUID>(30000); WebFetchInvDescHandler webFetchHandler = new WebFetchInvDescHandler(m_InventoryService, m_LibraryService);
IRequestHandler reqHandler
FetchInvDescHandler webFetchHandler = new FetchInvDescHandler(m_InventoryService, m_LibraryService, null); = new RestStreamHandler(
ISimpleStreamHandler reqHandler "POST",
= new SimpleStreamHandler("/CAPS/WebFetchInvDesc/", delegate(IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) "/CAPS/WebFetchInvDesc/" /*+ UUID.Random()*/,
{ webFetchHandler.FetchInventoryDescendentsRequest,
webFetchHandler.FetchInventoryDescendentsRequest(httpRequest, httpResponse, m_badRequests); "WebFetchInvDesc",
}); null);
server.AddStreamHandler(reqHandler);
server.AddSimpleStreamHandler(reqHandler);
} }
} }
} }

View File

@ -68,10 +68,7 @@ namespace OpenSim.Framework.Capabilities
/// <returns></returns> /// <returns></returns>
public static object LLSDDeserialize(byte[] b) public static object LLSDDeserialize(byte[] b)
{ {
using (MemoryStream ms = new MemoryStream(b, false)) return LLSDDeserialize(new MemoryStream(b, false));
{
return LLSDDeserialize(ms);
}
} }
/// <summary> /// <summary>
@ -81,23 +78,21 @@ namespace OpenSim.Framework.Capabilities
/// <returns></returns> /// <returns></returns>
public static object LLSDDeserialize(Stream st) public static object LLSDDeserialize(Stream st)
{ {
using (XmlTextReader reader = new XmlTextReader(st)) XmlTextReader reader = new XmlTextReader(st);
{ reader.Read();
reader.Read(); SkipWS(reader);
SkipWS(reader);
if (reader.NodeType != XmlNodeType.Element || reader.LocalName != "llsd") if (reader.NodeType != XmlNodeType.Element || reader.LocalName != "llsd")
throw new LLSDParseException("Expected <llsd>"); throw new LLSDParseException("Expected <llsd>");
reader.Read(); reader.Read();
object ret = LLSDParseOne(reader); object ret = LLSDParseOne(reader);
SkipWS(reader); SkipWS(reader);
if (reader.NodeType != XmlNodeType.EndElement || reader.LocalName != "llsd") if (reader.NodeType != XmlNodeType.EndElement || reader.LocalName != "llsd")
throw new LLSDParseException("Expected </llsd>"); throw new LLSDParseException("Expected </llsd>");
return ret; return ret;
}
} }
/// <summary> /// <summary>
@ -107,17 +102,17 @@ namespace OpenSim.Framework.Capabilities
/// <returns></returns> /// <returns></returns>
public static byte[] LLSDSerialize(object obj) public static byte[] LLSDSerialize(object obj)
{ {
using(StringWriter sw = new StringWriter()) StringWriter sw = new StringWriter();
using(XmlTextWriter writer = new XmlTextWriter(sw)) XmlTextWriter writer = new XmlTextWriter(sw);
{ writer.Formatting = Formatting.None;
writer.Formatting = Formatting.None;
writer.WriteStartElement(String.Empty, "llsd", String.Empty); writer.WriteStartElement(String.Empty, "llsd", String.Empty);
LLSDWriteOne(writer, obj); LLSDWriteOne(writer, obj);
writer.WriteEndElement(); writer.WriteEndElement();
writer.Flush();
return Util.UTF8.GetBytes(sw.ToString()); writer.Close();
}
return Util.UTF8.GetBytes(sw.ToString());
} }
/// <summary> /// <summary>
@ -566,7 +561,7 @@ namespace OpenSim.Framework.Capabilities
endPos = FindEnd(llsd, 1); endPos = FindEnd(llsd, 1);
if (Double.TryParse(llsd.Substring(1, endPos - 1), NumberStyles.Float, if (Double.TryParse(llsd.Substring(1, endPos - 1), NumberStyles.Float,
Culture.NumberFormatInfo, out value)) Utils.EnUsCulture.NumberFormat, out value))
return value; return value;
else else
throw new LLSDParseException("Failed to parse double value type"); throw new LLSDParseException("Failed to parse double value type");

View File

@ -30,20 +30,13 @@ using OpenMetaverse;
namespace OpenSim.Framework.Capabilities namespace OpenSim.Framework.Capabilities
{ {
[LLSDType("MAP")] [LLSDType("MAP")]
public class LLSDAssetUploadComplete public class LLSDAssetUploadComplete
{ {
public string new_asset = String.Empty; public string new_asset = String.Empty;
public UUID new_inventory_item = UUID.Zero; public UUID new_inventory_item = UUID.Zero;
// public UUID new_texture_folder_id = UUID.Zero;
public string state = String.Empty; public string state = String.Empty;
public LLSDAssetUploadError error = null;
//public bool success = false; //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() public LLSDAssetUploadComplete()
{ {

View File

@ -30,28 +30,15 @@ using OpenMetaverse;
namespace OpenSim.Framework.Capabilities 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] [OSDMap]
public class LLSDAssetUploadRequest public class LLSDAssetUploadRequest
{ {
public string asset_type = String.Empty; public string asset_type = String.Empty;
public string description = String.Empty; public string description = String.Empty;
public UUID folder_id = UUID.Zero; 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 inventory_type = String.Empty;
public string name = String.Empty; public string name = String.Empty;
public LLSDAssetResource asset_resources = new LLSDAssetResource();
public LLSDAssetUploadRequest() public LLSDAssetUploadRequest()
{ {
} }

View File

@ -26,51 +26,20 @@
*/ */
using System; using System;
using OpenMetaverse;
namespace OpenSim.Framework.Capabilities 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] [OSDMap]
public class LLSDAssetUploadResponse public class LLSDAssetUploadResponse
{ {
public string uploader = String.Empty; public string uploader = String.Empty;
public string state = String.Empty; public string state = String.Empty;
public int upload_price = 0;
public LLSDAssetUploadResponseData data = null;
public LLSDAssetUploadError error = null;
public LLSDAssetUploadResponse() public LLSDAssetUploadResponse()
{ {
} }
} }
[OSDMap] [OSDMap]
public class LLSDNewFileAngentInventoryVariablePriceReplyResponse public class LLSDNewFileAngentInventoryVariablePriceReplyResponse
{ {
@ -78,7 +47,7 @@ namespace OpenSim.Framework.Capabilities
public string state; public string state;
public int upload_price; public int upload_price;
public string rsvp; public string rsvp;
public LLSDNewFileAngentInventoryVariablePriceReplyResponse() public LLSDNewFileAngentInventoryVariablePriceReplyResponse()
{ {
state = "confirm_upload"; state = "confirm_upload";

View File

@ -42,7 +42,7 @@ namespace OpenSim.Framework.Capabilities
{ {
public string username; public string username;
public string display_name; 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_first_name;
public string legacy_last_name; public string legacy_last_name;
public UUID id; 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.IO;
using System.Reflection; using System.Reflection;
using System.Xml; using System.Xml;
using OpenMetaverse;
namespace OpenSim.Framework.Capabilities namespace OpenSim.Framework.Capabilities
{ {
@ -41,32 +40,17 @@ namespace OpenSim.Framework.Capabilities
public static string SerialiseLLSDReply(object obj) public static string SerialiseLLSDReply(object obj)
{ {
using(StringWriter sw = new StringWriter()) StringWriter sw = new StringWriter();
using(XmlTextWriter writer = new XmlTextWriter(sw)) XmlTextWriter writer = new XmlTextWriter(sw);
{ writer.Formatting = Formatting.None;
writer.Formatting = Formatting.None; writer.WriteStartElement(String.Empty, "llsd", String.Empty);
writer.WriteStartElement(String.Empty, "llsd", String.Empty); SerializeOSDType(writer, obj);
SerializeOSDType(writer, obj); writer.WriteEndElement();
writer.WriteEndElement(); writer.Close();
writer.Flush();
//m_log.DebugFormat("[LLSD Helpers]: Generated serialized LLSD reply {0}", sw.ToString()); //m_log.DebugFormat("[LLSD Helpers]: Generated serialized LLSD reply {0}", sw.ToString());
return 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();
}
} }
private static void SerializeOSDType(XmlTextWriter writer, object obj) 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 // 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. // 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 else
{ {
field.SetValue(obj, enumerator.Value); field.SetValue(obj, enumerator.Value);

View File

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

View File

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

View File

@ -25,15 +25,17 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
using System; using OpenMetaverse;
namespace Robust32 namespace OpenSim.Framework.Capabilities
{ {
class Program [OSDMap]
public class LLSDItemUpdate
{ {
static void Main(string[] args) public UUID item_id;
public LLSDItemUpdate()
{ {
global::OpenSim.Server.OpenSimServer.Main(args);
} }
} }
} }

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)); // OpenMetaverse.StructuredData.LLSDParser.DeserializeXml(new XmlTextReader(request));
Hashtable hash = (Hashtable) LLSD.LLSDDeserialize(request); Hashtable hash = (Hashtable) LLSD.LLSDDeserialize(request);
if(hash == null)
return new byte[0];
TRequest llsdRequest = new TRequest(); TRequest llsdRequest = new TRequest();
LLSDHelpers.DeserialiseOSDMap(hash, llsdRequest); 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.CompilerServices;
using System.Runtime.InteropServices; 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 // set of attributes. Change these attribute values to modify the information
// associated with an assembly. // associated with an assembly.
[assembly: AssemblyTitle("OpenSim.Capabilities")] [assembly: AssemblyTitle("OpenSim.Capabilities")]
@ -14,8 +14,8 @@ using System.Runtime.InteropServices;
[assembly: AssemblyTrademark("")] [assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")] [assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible // 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 // to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type. // COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)] [assembly: ComVisible(false)]
@ -25,7 +25,7 @@ using System.Runtime.InteropServices;
// Version information for an assembly consists of the following four values: // Version information for an assembly consists of the following four values:
// //
// Major Version // Major Version
// Minor Version // Minor Version
// Build Number // Build Number
// Revision // Revision
// //

View File

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

View File

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

View File

@ -37,8 +37,9 @@ namespace OpenSim.Data
public abstract class AssetDataBase : IAssetDataPlugin public abstract class AssetDataBase : IAssetDataPlugin
{ {
public abstract AssetBase GetAsset(UUID uuid); public abstract AssetBase GetAsset(UUID uuid);
public abstract bool StoreAsset(AssetBase asset);
public abstract bool[] AssetsExist(UUID[] uuids); public abstract void StoreAsset(AssetBase asset);
public abstract bool ExistsAsset(UUID uuid);
public abstract List<AssetMetadata> FetchAssetMetadataSet(int start, int count); 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 /// <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 /// supported formats into a UUID. This function is not actually DBMS-specific right
/// now /// now
/// ///
/// </summary> /// </summary>
/// <param name="id"></param> /// <param name="id"></param>
/// <returns></returns> /// <returns></returns>
@ -47,25 +47,24 @@ namespace OpenSim.Data
if ((id == null) || (id == DBNull.Value)) if ((id == null) || (id == DBNull.Value))
return UUID.Zero; return UUID.Zero;
Type idtype = id.GetType(); if (id.GetType() == typeof(Guid))
if (idtype == typeof(Guid))
return new UUID((Guid)id); return new UUID((Guid)id);
if (id.GetType() == typeof(string)) if (id.GetType() == typeof(byte[]))
{ {
Guid gg; if (((byte[])id).Length == 0)
if (Guid.TryParse((string)id, out gg)) return UUID.Zero;
return new UUID(gg); else if (((byte[])id).Length == 16)
return UUID.Zero; 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()); throw new Exception("Failed to convert db value to UUID: " + id.ToString());
} }
} }

View File

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

View File

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

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> /// <summary>
/// An interface for connecting to the user grid datastore /// An interface for connecting to the user grid datastore
/// </summary> /// </summary>
public interface IGridUserData public interface IGridUserData
{ {
GridUserData Get(string userID); GridUserData Get(string userID);
GridUserData[] GetAll(string query); GridUserData[] GetAll(string query);

View File

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

View File

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

View File

@ -1,4 +1,4 @@
/* /*
* Copyright (c) Contributors, http://opensimulator.org/ * Copyright (c) Contributors, http://opensimulator.org/
* See CONTRIBUTORS.TXT for a full list of copyright holders. * See CONTRIBUTORS.TXT for a full list of copyright holders.
* *
@ -34,12 +34,11 @@ namespace OpenSim.Data
public class OfflineIMData public class OfflineIMData
{ {
public UUID PrincipalID; public UUID PrincipalID;
public UUID FromID;
public Dictionary<string, string> Data; public Dictionary<string, string> Data;
} }
public interface IOfflineIMData public interface IOfflineIMData
{ {
OfflineIMData[] Get(string field, string val); OfflineIMData[] Get(string field, string val);
long GetCount(string field, string key); long GetCount(string field, string key);

View File

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

View File

@ -48,8 +48,6 @@ namespace OpenSim.Data
bool UpdateAvatarProperties(ref UserProfileProperties props, ref string result); bool UpdateAvatarProperties(ref UserProfileProperties props, ref string result);
bool UpdateAvatarInterests(UserProfileProperties up, ref string result); bool UpdateAvatarInterests(UserProfileProperties up, ref string result);
bool GetClassifiedInfo(ref UserClassifiedAdd ad, ref string result); bool GetClassifiedInfo(ref UserClassifiedAdd ad, 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 GetUserAppData(ref UserAppData props, ref string result);
bool SetUserAppData(UserAppData props, ref string result); bool SetUserAppData(UserAppData props, ref string result);
OSDArray GetUserImageAssets(UUID avatarId); OSDArray GetUserImageAssets(UUID avatarId);

View File

@ -52,14 +52,14 @@ namespace OpenSim.Data
public int sizeY; public int sizeY;
/// <summary> /// <summary>
/// Return the x-coordinate of this region in region units. /// Return the x-coordinate of this region.
/// </summary> /// </summary>
public int coordX { get { return (int)Util.WorldToRegionLoc((uint)posX); } } public int coordX { get { return posX / (int)Constants.RegionSize; } }
/// <summary> /// <summary>
/// Return the y-coordinate of this region in region units. /// Return the y-coordinate of this region.
/// </summary> /// </summary>
public int coordY { get { return (int)Util.WorldToRegionLoc((uint)posY); } } public int coordY { get { return posY / (int)Constants.RegionSize; } }
public Dictionary<string, object> Data; public Dictionary<string, object> Data;
} }
@ -67,12 +67,10 @@ namespace OpenSim.Data
/// <summary> /// <summary>
/// An interface for connecting to the authentication datastore /// An interface for connecting to the authentication datastore
/// </summary> /// </summary>
public interface IRegionData public interface IRegionData
{ {
RegionData Get(UUID regionID, UUID ScopeID); RegionData Get(UUID regionID, UUID ScopeID);
List<RegionData> Get(string regionName, UUID ScopeID); List<RegionData> Get(string regionName, UUID ScopeID);
RegionData GetSpecific(string regionName, UUID ScopeID);
RegionData Get(int x, int y, UUID ScopeID); RegionData Get(int x, int y, UUID ScopeID);
List<RegionData> Get(int xStart, int yStart, int xEnd, int yEnd, UUID ScopeID); List<RegionData> Get(int xStart, int yStart, int xEnd, int yEnd, UUID ScopeID);
@ -83,7 +81,6 @@ namespace OpenSim.Data
bool Delete(UUID regionID); bool Delete(UUID regionID);
List<RegionData> GetDefaultRegions(UUID scopeID); List<RegionData> GetDefaultRegions(UUID scopeID);
List<RegionData> GetDefaultHypergridRegions(UUID scopeID);
List<RegionData> GetFallbackRegions(UUID scopeID, int x, int y); List<RegionData> GetFallbackRegions(UUID scopeID, int x, int y);
List<RegionData> GetHyperlinks(UUID scopeID); List<RegionData> GetHyperlinks(UUID scopeID);
} }

View File

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

View File

@ -39,7 +39,7 @@ namespace OpenSim.Data
{ {
AssetBase GetAsset(UUID uuid); AssetBase GetAsset(UUID uuid);
void StoreAsset(AssetBase asset); void StoreAsset(AssetBase asset);
bool[] AssetsExist(UUID[] uuids); bool ExistsAsset(UUID uuid);
List<AssetMetadata> FetchAssetMetadataSet(int start, int count); List<AssetMetadata> FetchAssetMetadataSet(int start, int count);
void Initialise(string connect); void Initialise(string connect);
bool Delete(string id); bool Delete(string id);

View File

@ -38,67 +38,19 @@ namespace OpenSim.Data
public UUID ownerRoleID; public UUID ownerRoleID;
public string name; public string name;
public string charter; public string charter;
public bool showInList; public bool showInList;
public UUID insigniaID; public UUID insigniaID;
public int membershipFee; public int membershipFee;
public bool openEnrollment; public bool openEnrollment;
public bool allowPublish; public bool allowPublish;
public bool maturePublish; public bool maturePublish;
public UUID founderID; public UUID founderID;
public ulong everyonePowers; public ulong everyonePowers;
public ulong ownersPowers; public ulong ownersPowers;
public Dictionary<UUID, XGroupMember> members = new Dictionary<UUID, XGroupMember>();
public Dictionary<UUID, XGroupNotice> notices = new Dictionary<UUID, XGroupNotice>();
public XGroup Clone() public XGroup Clone()
{ {
XGroup clone = (XGroup)MemberwiseClone(); return (XGroup)MemberwiseClone();
clone.members = new Dictionary<UUID, XGroupMember>();
clone.notices = new Dictionary<UUID, XGroupNotice>();
foreach (KeyValuePair<UUID, XGroupMember> kvp in members)
clone.members[kvp.Key] = kvp.Value.Clone();
foreach (KeyValuePair<UUID, XGroupNotice> kvp in notices)
clone.notices[kvp.Key] = kvp.Value.Clone();
return clone;
}
}
public class XGroupMember
{
public UUID agentID;
public UUID groupID;
public UUID roleID;
public bool acceptNotices = true;
public bool listInProfile = true;
public XGroupMember Clone()
{
return (XGroupMember)MemberwiseClone();
}
}
public class XGroupNotice
{
public UUID groupID;
public UUID noticeID;
public uint timestamp;
public string fromName;
public string subject;
public string message;
public byte[] binaryBucket;
public bool hasAttachment;
public int assetType;
public XGroupNotice Clone()
{
XGroupNotice clone = (XGroupNotice)MemberwiseClone();
clone.binaryBucket = (byte[])binaryBucket.Clone();
return clone;
} }
} }
@ -106,13 +58,14 @@ namespace OpenSim.Data
/// Early stub interface for groups data, not final. /// Early stub interface for groups data, not final.
/// </summary> /// </summary>
/// <remarks> /// <remarks>
/// Currently in-use only for regression test purposes. /// Currently in-use only for regression test purposes. Needs to be filled out over time.
/// </remarks> /// </remarks>
public interface IXGroupData public interface IXGroupData
{ {
bool StoreGroup(XGroup group); bool StoreGroup(XGroup group);
XGroup GetGroup(UUID groupID); XGroup[] GetGroups(string field, string val);
Dictionary<UUID, XGroup> GetGroups(); XGroup[] GetGroups(string[] fields, string[] vals);
bool DeleteGroup(UUID groupID); bool DeleteGroups(string field, string val);
bool DeleteGroups(string[] fields, string[] vals);
} }
} }

View File

@ -27,20 +27,19 @@
using System; using System;
using System.Data; using System.Data;
using System.Data.SqlClient;
using System.Reflection; using System.Reflection;
using System.Collections.Generic; using System.Collections.Generic;
using OpenMetaverse; using OpenMetaverse;
using log4net; using log4net;
using OpenSim.Framework; using OpenSim.Framework;
using Npgsql;
using NpgsqlTypes;
namespace OpenSim.Data.PGSQL namespace OpenSim.Data.MSSQL
{ {
/// <summary> /// <summary>
/// A PGSQL Interface for the Asset server /// A MSSQL Interface for the Asset server
/// </summary> /// </summary>
public class PGSQLAssetData : AssetDataBase public class MSSQLAssetData : AssetDataBase
{ {
private const string _migrationStore = "AssetStore"; private const string _migrationStore = "AssetStore";
@ -49,14 +48,9 @@ namespace OpenSim.Data.PGSQL
/// <summary> /// <summary>
/// Database manager /// Database manager
/// </summary> /// </summary>
private PGSQLManager m_database; private MSSQLManager m_database;
private string m_connectionString; private string m_connectionString;
protected virtual Assembly Assembly
{
get { return GetType().Assembly; }
}
#region IPlugin Members #region IPlugin Members
override public void Dispose() { } override public void Dispose() { }
@ -67,7 +61,7 @@ namespace OpenSim.Data.PGSQL
// [Obsolete("Cannot be default-initialized!")] // [Obsolete("Cannot be default-initialized!")]
override public void Initialise() override public void Initialise()
{ {
m_log.Info("[PGSQLAssetData]: " + Name + " cannot be default-initialized!"); m_log.Info("[MSSQLAssetData]: " + Name + " cannot be default-initialized!");
throw new PluginNotInitialisedException(Name); throw new PluginNotInitialisedException(Name);
} }
@ -82,7 +76,7 @@ namespace OpenSim.Data.PGSQL
{ {
m_ticksToEpoch = new System.DateTime(1970, 1, 1).Ticks; m_ticksToEpoch = new System.DateTime(1970, 1, 1).Ticks;
m_database = new PGSQLManager(connectionString); m_database = new MSSQLManager(connectionString);
m_connectionString = connectionString; m_connectionString = connectionString;
//New migration to check for DB changes //New migration to check for DB changes
@ -102,7 +96,7 @@ namespace OpenSim.Data.PGSQL
/// </summary> /// </summary>
override public string Name override public string Name
{ {
get { return "PGSQL Asset storage engine"; } get { return "MSSQL Asset storage engine"; }
} }
#endregion #endregion
@ -116,13 +110,13 @@ namespace OpenSim.Data.PGSQL
/// <returns></returns> /// <returns></returns>
override public AssetBase GetAsset(UUID assetID) override public AssetBase GetAsset(UUID assetID)
{ {
string sql = "SELECT * FROM assets WHERE id = :id"; string sql = "SELECT * FROM assets WHERE id = @id";
using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString)) using (SqlConnection conn = new SqlConnection(m_connectionString))
using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn)) using (SqlCommand cmd = new SqlCommand(sql, conn))
{ {
cmd.Parameters.Add(m_database.CreateParameter("id", assetID)); cmd.Parameters.Add(m_database.CreateParameter("id", assetID));
conn.Open(); conn.Open();
using (NpgsqlDataReader reader = cmd.ExecuteReader()) using (SqlDataReader reader = cmd.ExecuteReader())
{ {
if (reader.Read()) if (reader.Read())
{ {
@ -149,42 +143,42 @@ namespace OpenSim.Data.PGSQL
/// Create asset in m_database /// Create asset in m_database
/// </summary> /// </summary>
/// <param name="asset">the asset</param> /// <param name="asset">the asset</param>
override public bool StoreAsset(AssetBase asset) override public void StoreAsset(AssetBase asset)
{ {
string sql = string sql =
@"UPDATE assets set name = :name, description = :description, " + "\"assetType\" " + @" = :assetType, @"IF EXISTS(SELECT * FROM assets WHERE id=@id)
local = :local, temporary = :temporary, creatorid = :creatorid, data = :data UPDATE assets set name = @name, description = @description, assetType = @assetType,
WHERE id=:id; local = @local, temporary = @temporary, creatorid = @creatorid, data = @data
WHERE id=@id
INSERT INTO assets ELSE
(id, name, description, " + "\"assetType\" " + @", local, INSERT INTO assets
temporary, create_time, access_time, creatorid, asset_flags, data) ([id], [name], [description], [assetType], [local],
Select :id, :name, :description, :assetType, :local, [temporary], [create_time], [access_time], [creatorid], [asset_flags], [data])
:temporary, :create_time, :access_time, :creatorid, :asset_flags, :data VALUES
Where not EXISTS(SELECT * FROM assets WHERE id=:id) (@id, @name, @description, @assetType, @local,
"; @temporary, @create_time, @access_time, @creatorid, @asset_flags, @data)";
string assetName = asset.Name; string assetName = asset.Name;
if (asset.Name.Length > AssetBase.MAX_ASSET_NAME) if (asset.Name.Length > 64)
{ {
assetName = asset.Name.Substring(0, AssetBase.MAX_ASSET_NAME); assetName = asset.Name.Substring(0, 64);
m_log.WarnFormat( m_log.WarnFormat(
"[ASSET DB]: Name '{0}' for asset {1} truncated from {2} to {3} characters on add", "[ASSET DB]: Name '{0}' for asset {1} truncated from {2} to {3} characters on add",
asset.Name, asset.ID, asset.Name.Length, assetName.Length); asset.Name, asset.ID, asset.Name.Length, assetName.Length);
} }
string assetDescription = asset.Description; string assetDescription = asset.Description;
if (asset.Description.Length > AssetBase.MAX_ASSET_DESC) if (asset.Description.Length > 64)
{ {
assetDescription = asset.Description.Substring(0, AssetBase.MAX_ASSET_DESC); assetDescription = asset.Description.Substring(0, 64);
m_log.WarnFormat( m_log.WarnFormat(
"[ASSET DB]: Description '{0}' for asset {1} truncated from {2} to {3} characters on add", "[ASSET DB]: Description '{0}' for asset {1} truncated from {2} to {3} characters on add",
asset.Description, asset.ID, asset.Description.Length, assetDescription.Length); asset.Description, asset.ID, asset.Description.Length, assetDescription.Length);
} }
using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString)) using (SqlConnection conn = new SqlConnection(m_connectionString))
using (NpgsqlCommand command = new NpgsqlCommand(sql, conn)) using (SqlCommand command = new SqlCommand(sql, conn))
{ {
int now = (int)((System.DateTime.Now.Ticks - m_ticksToEpoch) / 10000000); 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("id", asset.FullID));
@ -205,21 +199,20 @@ namespace OpenSim.Data.PGSQL
} }
catch(Exception e) catch(Exception e)
{ {
m_log.Error("[ASSET DB]: Error storing item :" + e.Message + " sql "+sql); m_log.Error("[ASSET DB]: Error storing item :" + e.Message);
} }
} }
return true;
} }
// Commented out since currently unused - this probably should be called in GetAsset() // Commented out since currently unused - this probably should be called in GetAsset()
// private void UpdateAccessTime(AssetBase asset) // private void UpdateAccessTime(AssetBase asset)
// { // {
// using (AutoClosingSqlCommand cmd = m_database.Query("UPDATE assets SET access_time = :access_time WHERE id=:id")) // 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); // int now = (int)((System.DateTime.Now.Ticks - m_ticksToEpoch) / 10000000);
// cmd.Parameters.AddWithValue(":id", asset.FullID.ToString()); // cmd.Parameters.AddWithValue("@id", asset.FullID.ToString());
// cmd.Parameters.AddWithValue(":access_time", now); // cmd.Parameters.AddWithValue("@access_time", now);
// try // try
// { // {
// cmd.ExecuteNonQuery(); // cmd.ExecuteNonQuery();
@ -232,38 +225,17 @@ namespace OpenSim.Data.PGSQL
// } // }
/// <summary> /// <summary>
/// Check if the assets exist in the database. /// Check if asset exist in m_database
/// </summary> /// </summary>
/// <param name="uuids">The assets' IDs</param> /// <param name="uuid"></param>
/// <returns>For each asset: true if it exists, false otherwise</returns> /// <returns>true if exist.</returns>
public override bool[] AssetsExist(UUID[] uuids) override public bool ExistsAsset(UUID uuid)
{ {
if (uuids.Length == 0) if (GetAsset(uuid) != null)
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 (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
{ {
conn.Open(); return true;
using (NpgsqlDataReader reader = cmd.ExecuteReader())
{
while (reader.Read())
{
UUID id = DBGuid.FromDB(reader["id"]);
exist.Add(id);
}
}
} }
return false;
bool[] results = new bool[uuids.Length];
for (int i = 0; i < uuids.Length; i++)
results[i] = exist.Contains(uuids[i]);
return results;
} }
/// <summary> /// <summary>
@ -277,19 +249,23 @@ namespace OpenSim.Data.PGSQL
public override List<AssetMetadata> FetchAssetMetadataSet(int start, int count) public override List<AssetMetadata> FetchAssetMetadataSet(int start, int count)
{ {
List<AssetMetadata> retList = new List<AssetMetadata>(count); List<AssetMetadata> retList = new List<AssetMetadata>(count);
string sql = @" SELECT id, name, description, " + "\"assetType\"" + @", temporary, creatorid string sql = @"WITH OrderedAssets AS
FROM assets (
order by id SELECT id, name, description, assetType, temporary, creatorid,
limit :stop RowNumber = ROW_NUMBER() OVER (ORDER BY id)
offset :start;"; FROM assets
)
SELECT *
FROM OrderedAssets
WHERE RowNumber BETWEEN @start AND @stop;";
using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString)) using (SqlConnection conn = new SqlConnection(m_connectionString))
using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn)) using (SqlCommand cmd = new SqlCommand(sql, conn))
{ {
cmd.Parameters.Add(m_database.CreateParameter("start", start)); cmd.Parameters.Add(m_database.CreateParameter("start", start));
cmd.Parameters.Add(m_database.CreateParameter("stop", start + count - 1)); cmd.Parameters.Add(m_database.CreateParameter("stop", start + count - 1));
conn.Open(); conn.Open();
using (NpgsqlDataReader reader = cmd.ExecuteReader()) using (SqlDataReader reader = cmd.ExecuteReader())
{ {
while (reader.Read()) while (reader.Read())
{ {

View File

@ -1,4 +1,4 @@
/* /*
* Copyright (c) Contributors, http://opensimulator.org/ * Copyright (c) Contributors, http://opensimulator.org/
* See CONTRIBUTORS.TXT for a full list of copyright holders. * See CONTRIBUTORS.TXT for a full list of copyright holders.
* *
@ -28,38 +28,32 @@
using System; using System;
using System.Collections; using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using System.Data;
using OpenMetaverse; using OpenMetaverse;
using OpenSim.Framework; using OpenSim.Framework;
using System.Data.SqlClient;
using System.Reflection; using System.Reflection;
using System.Text; using System.Text;
using System.Data;
using Npgsql;
using NpgsqlTypes;
namespace OpenSim.Data.PGSQL namespace OpenSim.Data.MSSQL
{ {
public class PGSQLAuthenticationData : IAuthenticationData public class MSSQLAuthenticationData : IAuthenticationData
{ {
private string m_Realm; private string m_Realm;
private List<string> m_ColumnNames = null; private List<string> m_ColumnNames = null;
private int m_LastExpire = 0; private int m_LastExpire = 0;
private string m_ConnectionString; private string m_ConnectionString;
private PGSQLManager m_database; private MSSQLManager m_database;
protected virtual Assembly Assembly public MSSQLAuthenticationData(string connectionString, string realm)
{
get { return GetType().Assembly; }
}
public PGSQLAuthenticationData(string connectionString, string realm)
{ {
m_Realm = realm; m_Realm = realm;
m_ConnectionString = connectionString; m_ConnectionString = connectionString;
using (NpgsqlConnection conn = new NpgsqlConnection(m_ConnectionString)) using (SqlConnection conn = new SqlConnection(m_ConnectionString))
{ {
conn.Open(); conn.Open();
Migration m = new Migration(conn, GetType().Assembly, "AuthStore"); Migration m = new Migration(conn, GetType().Assembly, "AuthStore");
m_database = new PGSQLManager(m_ConnectionString); m_database = new MSSQLManager(m_ConnectionString);
m.Update(); m.Update();
} }
} }
@ -69,14 +63,14 @@ namespace OpenSim.Data.PGSQL
AuthenticationData ret = new AuthenticationData(); AuthenticationData ret = new AuthenticationData();
ret.Data = new Dictionary<string, object>(); ret.Data = new Dictionary<string, object>();
string sql = string.Format("select * from {0} where uuid = :principalID", m_Realm); string sql = string.Format("select * from {0} where UUID = @principalID", m_Realm);
using (NpgsqlConnection conn = new NpgsqlConnection(m_ConnectionString)) using (SqlConnection conn = new SqlConnection(m_ConnectionString))
using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn)) using (SqlCommand cmd = new SqlCommand(sql, conn))
{ {
cmd.Parameters.Add(m_database.CreateParameter("principalID", principalID)); cmd.Parameters.Add(m_database.CreateParameter("@principalID", principalID));
conn.Open(); conn.Open();
using (NpgsqlDataReader result = cmd.ExecuteReader()) using (SqlDataReader result = cmd.ExecuteReader())
{ {
if (result.Read()) if (result.Read())
{ {
@ -93,7 +87,7 @@ namespace OpenSim.Data.PGSQL
foreach (string s in m_ColumnNames) foreach (string s in m_ColumnNames)
{ {
if (s == "UUID"||s == "uuid") if (s == "UUID")
continue; continue;
ret.Data[s] = result[s].ToString(); ret.Data[s] = result[s].ToString();
@ -109,31 +103,12 @@ namespace OpenSim.Data.PGSQL
{ {
if (data.Data.ContainsKey("UUID")) if (data.Data.ContainsKey("UUID"))
data.Data.Remove("UUID"); data.Data.Remove("UUID");
if (data.Data.ContainsKey("uuid"))
data.Data.Remove("uuid");
/*
Dictionary<string, object> oAuth = new Dictionary<string, object>();
foreach (KeyValuePair<string, object> oDado in data.Data)
{
if (oDado.Key != oDado.Key.ToLower())
{
oAuth.Add(oDado.Key.ToLower(), oDado.Value);
}
}
foreach (KeyValuePair<string, object> oDado in data.Data)
{
if (!oAuth.ContainsKey(oDado.Key.ToLower())) {
oAuth.Add(oDado.Key.ToLower(), oDado.Value);
}
}
*/
string[] fields = new List<string>(data.Data.Keys).ToArray(); string[] fields = new List<string>(data.Data.Keys).ToArray();
StringBuilder updateBuilder = new StringBuilder(); StringBuilder updateBuilder = new StringBuilder();
using (NpgsqlConnection conn = new NpgsqlConnection(m_ConnectionString)) using (SqlConnection conn = new SqlConnection(m_ConnectionString))
using (NpgsqlCommand cmd = new NpgsqlCommand()) using (SqlCommand cmd = new SqlCommand())
{ {
updateBuilder.AppendFormat("update {0} set ", m_Realm); updateBuilder.AppendFormat("update {0} set ", m_Realm);
@ -142,28 +117,27 @@ namespace OpenSim.Data.PGSQL
{ {
if (!first) if (!first)
updateBuilder.Append(", "); updateBuilder.Append(", ");
updateBuilder.AppendFormat("\"{0}\" = :{0}",field); updateBuilder.AppendFormat("{0} = @{0}",field);
first = false; first = false;
cmd.Parameters.Add(m_database.CreateParameter("@" + field, data.Data[field]));
cmd.Parameters.Add(m_database.CreateParameter("" + field, data.Data[field]));
} }
updateBuilder.Append(" where uuid = :principalID"); updateBuilder.Append(" where UUID = @principalID");
cmd.CommandText = updateBuilder.ToString(); cmd.CommandText = updateBuilder.ToString();
cmd.Connection = conn; cmd.Connection = conn;
cmd.Parameters.Add(m_database.CreateParameter("principalID", data.PrincipalID)); cmd.Parameters.Add(m_database.CreateParameter("@principalID", data.PrincipalID));
conn.Open(); conn.Open();
if (cmd.ExecuteNonQuery() < 1) if (cmd.ExecuteNonQuery() < 1)
{ {
StringBuilder insertBuilder = new StringBuilder(); StringBuilder insertBuilder = new StringBuilder();
insertBuilder.AppendFormat("insert into {0} (uuid, \"", m_Realm); insertBuilder.AppendFormat("insert into {0} (UUID, ", m_Realm);
insertBuilder.Append(String.Join("\", \"", fields)); insertBuilder.Append(String.Join(", ", fields));
insertBuilder.Append("\") values (:principalID, :"); insertBuilder.Append(") values (@principalID, @");
insertBuilder.Append(String.Join(", :", fields)); insertBuilder.Append(String.Join(", @", fields));
insertBuilder.Append(")"); insertBuilder.Append(")");
cmd.CommandText = insertBuilder.ToString(); cmd.CommandText = insertBuilder.ToString();
@ -179,11 +153,11 @@ namespace OpenSim.Data.PGSQL
public bool SetDataItem(UUID principalID, string item, string value) public bool SetDataItem(UUID principalID, string item, string value)
{ {
string sql = string.Format("update {0} set {1} = :{1} where uuid = :UUID", m_Realm, item); string sql = string.Format("update {0} set {1} = @{1} where UUID = @UUID", m_Realm, item);
using (NpgsqlConnection conn = new NpgsqlConnection(m_ConnectionString)) using (SqlConnection conn = new SqlConnection(m_ConnectionString))
using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn)) using (SqlCommand cmd = new SqlCommand(sql, conn))
{ {
cmd.Parameters.Add(m_database.CreateParameter("" + item, value)); cmd.Parameters.Add(m_database.CreateParameter("@" + item, value));
conn.Open(); conn.Open();
if (cmd.ExecuteNonQuery() > 0) if (cmd.ExecuteNonQuery() > 0)
return true; return true;
@ -195,14 +169,14 @@ namespace OpenSim.Data.PGSQL
{ {
if (System.Environment.TickCount - m_LastExpire > 30000) if (System.Environment.TickCount - m_LastExpire > 30000)
DoExpire(); DoExpire();
string sql = "insert into tokens (uuid, token, validity) values (:principalID, :token, :lifetime)"; string sql = "insert into tokens (UUID, token, validity) values (@principalID, @token, @lifetime)";
using (NpgsqlConnection conn = new NpgsqlConnection(m_ConnectionString)) using (SqlConnection conn = new SqlConnection(m_ConnectionString))
using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn)) using (SqlCommand cmd = new SqlCommand(sql, conn))
{ {
cmd.Parameters.Add(m_database.CreateParameter("principalID", principalID)); cmd.Parameters.Add(m_database.CreateParameter("@principalID", principalID));
cmd.Parameters.Add(m_database.CreateParameter("token", token)); cmd.Parameters.Add(m_database.CreateParameter("@token", token));
cmd.Parameters.Add(m_database.CreateParameter("lifetime", DateTime.Now.AddMinutes(lifetime))); cmd.Parameters.Add(m_database.CreateParameter("@lifetime", DateTime.Now.AddMinutes(lifetime)));
conn.Open(); conn.Open();
if (cmd.ExecuteNonQuery() > 0) if (cmd.ExecuteNonQuery() > 0)
@ -219,14 +193,13 @@ namespace OpenSim.Data.PGSQL
DoExpire(); DoExpire();
DateTime validDate = DateTime.Now.AddMinutes(lifetime); DateTime validDate = DateTime.Now.AddMinutes(lifetime);
string sql = "update tokens set validity = :validDate where uuid = :principalID and token = :token and validity > (CURRENT_DATE + CURRENT_TIME)"; string sql = "update tokens set validity = @validDate where UUID = @principalID and token = @token and validity > GetDate()";
using (SqlConnection conn = new SqlConnection(m_ConnectionString))
using (NpgsqlConnection conn = new NpgsqlConnection(m_ConnectionString)) using (SqlCommand cmd = new SqlCommand(sql, conn))
using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
{ {
cmd.Parameters.Add(m_database.CreateParameter("principalID", principalID)); cmd.Parameters.Add(m_database.CreateParameter("@principalID", principalID));
cmd.Parameters.Add(m_database.CreateParameter("token", token)); cmd.Parameters.Add(m_database.CreateParameter("@token", token));
cmd.Parameters.Add(m_database.CreateParameter("validDate", validDate)); cmd.Parameters.Add(m_database.CreateParameter("@validDate", validDate));
conn.Open(); conn.Open();
if (cmd.ExecuteNonQuery() > 0) if (cmd.ExecuteNonQuery() > 0)
@ -240,12 +213,12 @@ namespace OpenSim.Data.PGSQL
private void DoExpire() private void DoExpire()
{ {
DateTime currentDateTime = DateTime.Now; DateTime currentDateTime = DateTime.Now;
string sql = "delete from tokens where validity < :currentDateTime"; string sql = "delete from tokens where validity < @currentDateTime";
using (NpgsqlConnection conn = new NpgsqlConnection(m_ConnectionString)) using (SqlConnection conn = new SqlConnection(m_ConnectionString))
using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn)) using (SqlCommand cmd = new SqlCommand(sql, conn))
{ {
conn.Open(); conn.Open();
cmd.Parameters.Add(m_database.CreateParameter("currentDateTime", currentDateTime)); cmd.Parameters.Add(m_database.CreateParameter("@currentDateTime", currentDateTime));
cmd.ExecuteNonQuery(); cmd.ExecuteNonQuery();
} }
m_LastExpire = System.Environment.TickCount; m_LastExpire = System.Environment.TickCount;

View File

@ -27,39 +27,38 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Data;
using System.Reflection; using System.Reflection;
using System.Threading; using System.Threading;
using log4net; using log4net;
using OpenMetaverse; using OpenMetaverse;
using OpenSim.Framework; using OpenSim.Framework;
using Npgsql; using System.Data.SqlClient;
using NpgsqlTypes;
namespace OpenSim.Data.MSSQL
namespace OpenSim.Data.PGSQL
{ {
/// <summary> /// <summary>
/// A PGSQL Interface for Avatar Storage /// A MSSQL Interface for Avatar Storage
/// </summary> /// </summary>
public class PGSQLAvatarData : PGSQLGenericTableHandler<AvatarBaseData>, public class MSSQLAvatarData : MSSQLGenericTableHandler<AvatarBaseData>,
IAvatarData IAvatarData
{ {
// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); // private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
public PGSQLAvatarData(string connectionString, string realm) : public MSSQLAvatarData(string connectionString, string realm) :
base(connectionString, realm, "Avatar") base(connectionString, realm, "Avatar")
{ {
} }
public bool Delete(UUID principalID, string name) public bool Delete(UUID principalID, string name)
{ {
using (NpgsqlConnection conn = new NpgsqlConnection(m_ConnectionString)) using (SqlConnection conn = new SqlConnection(m_ConnectionString))
using (NpgsqlCommand cmd = new NpgsqlCommand()) using (SqlCommand cmd = new SqlCommand())
{ {
cmd.CommandText = String.Format("DELETE FROM {0} where \"PrincipalID\" = :PrincipalID and \"Name\" = :Name", m_Realm); cmd.CommandText = String.Format("DELETE FROM {0} where [PrincipalID] = @PrincipalID and [Name] = @Name", m_Realm);
cmd.Parameters.Add(m_database.CreateParameter("PrincipalID", principalID)); cmd.Parameters.Add(m_database.CreateParameter("@PrincipalID", principalID.ToString()));
cmd.Parameters.Add(m_database.CreateParameter("Name", name)); cmd.Parameters.Add(m_database.CreateParameter("@Name", name));
cmd.Connection = conn; cmd.Connection = conn;
conn.Open(); conn.Open();
if (cmd.ExecuteNonQuery() > 0) if (cmd.ExecuteNonQuery() > 0)

View File

@ -27,44 +27,38 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.Reflection; using System.Reflection;
using log4net; using log4net;
using OpenMetaverse; using OpenMetaverse;
using OpenSim.Framework; using OpenSim.Framework;
using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.Framework.Interfaces;
using System.Data;
using Npgsql;
using NpgsqlTypes;
namespace OpenSim.Data.PGSQL namespace OpenSim.Data.MSSQL
{ {
public class PGSQLEstateStore : IEstateDataStore public class MSSQLEstateStore : IEstateDataStore
{ {
private const string _migrationStore = "EstateStore"; private const string _migrationStore = "EstateStore";
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private PGSQLManager _Database; private MSSQLManager _Database;
private string m_connectionString; private string m_connectionString;
private FieldInfo[] _Fields; private FieldInfo[] _Fields;
private Dictionary<string, FieldInfo> _FieldMap = new Dictionary<string, FieldInfo>(); private Dictionary<string, FieldInfo> _FieldMap = new Dictionary<string, FieldInfo>();
#region Public methods #region Public methods
public PGSQLEstateStore() public MSSQLEstateStore()
{ {
} }
public PGSQLEstateStore(string connectionString) public MSSQLEstateStore(string connectionString)
{ {
Initialise(connectionString); Initialise(connectionString);
} }
protected virtual Assembly Assembly
{
get { return GetType().Assembly; }
}
/// <summary> /// <summary>
/// Initialises the estatedata class. /// Initialises the estatedata class.
/// </summary> /// </summary>
@ -74,11 +68,11 @@ namespace OpenSim.Data.PGSQL
if (!string.IsNullOrEmpty(connectionString)) if (!string.IsNullOrEmpty(connectionString))
{ {
m_connectionString = connectionString; m_connectionString = connectionString;
_Database = new PGSQLManager(connectionString); _Database = new MSSQLManager(connectionString);
} }
//Migration settings //Migration settings
using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString)) using (SqlConnection conn = new SqlConnection(m_connectionString))
{ {
conn.Open(); conn.Open();
Migration m = new Migration(conn, GetType().Assembly, "EstateStore"); Migration m = new Migration(conn, GetType().Assembly, "EstateStore");
@ -107,17 +101,15 @@ namespace OpenSim.Data.PGSQL
{ {
EstateSettings es = new EstateSettings(); EstateSettings es = new EstateSettings();
string sql = "select estate_settings.\"" + String.Join("\",estate_settings.\"", FieldList) + 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";
"\" 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; bool insertEstate = false;
using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString)) using (SqlConnection conn = new SqlConnection(m_connectionString))
using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn)) using (SqlCommand cmd = new SqlCommand(sql, conn))
{ {
cmd.Parameters.Add(_Database.CreateParameter("RegionID", regionID)); cmd.Parameters.Add(_Database.CreateParameter("@RegionID", regionID));
conn.Open(); conn.Open();
using (NpgsqlDataReader reader = cmd.ExecuteReader()) using (SqlDataReader reader = cmd.ExecuteReader())
{ {
if (reader.Read()) if (reader.Read())
{ {
@ -127,15 +119,11 @@ namespace OpenSim.Data.PGSQL
object v = reader[name]; object v = reader[name];
if (f.FieldType == typeof(bool)) if (f.FieldType == typeof(bool))
{ {
f.SetValue(es, v); f.SetValue(es, Convert.ToInt32(v) != 0);
} }
else if (f.FieldType == typeof(UUID)) else if (f.FieldType == typeof(UUID))
{ {
UUID estUUID = UUID.Zero; f.SetValue(es, new UUID((Guid)v)); // uuid);
UUID.TryParse(v.ToString(), out estUUID);
f.SetValue(es, estUUID);
} }
else if (f.FieldType == typeof(string)) else if (f.FieldType == typeof(string))
{ {
@ -199,37 +187,25 @@ namespace OpenSim.Data.PGSQL
names.Remove("EstateID"); names.Remove("EstateID");
string sql = string.Format("insert into estate_settings (\"{0}\") values ( :{1} )", String.Join("\",\"", names.ToArray()), String.Join(", :", names.ToArray())); string sql = string.Format("insert into estate_settings ({0}) values ( @{1})", String.Join(",", names.ToArray()), String.Join(", @", names.ToArray()));
using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString)) //_Log.Debug("[DB ESTATE]: SQL: " + sql);
using (NpgsqlCommand insertCommand = new NpgsqlCommand(sql, conn)) using (SqlConnection conn = new SqlConnection(m_connectionString))
using (SqlCommand insertCommand = new SqlCommand(sql, conn))
{ {
insertCommand.CommandText = sql; insertCommand.CommandText = sql + " SET @ID = SCOPE_IDENTITY()";
foreach (string name in names) foreach (string name in names)
{ {
insertCommand.Parameters.Add(_Database.CreateParameter("" + name, _FieldMap[name].GetValue(es))); insertCommand.Parameters.Add(_Database.CreateParameter("@" + name, _FieldMap[name].GetValue(es)));
} }
//NpgsqlParameter idParameter = new NpgsqlParameter("ID", SqlDbType.Int); SqlParameter idParameter = new SqlParameter("@ID", SqlDbType.Int);
//idParameter.Direction = ParameterDirection.Output; idParameter.Direction = ParameterDirection.Output;
//insertCommand.Parameters.Add(idParameter); insertCommand.Parameters.Add(idParameter);
conn.Open(); conn.Open();
insertCommand.ExecuteNonQuery();
es.EstateID = 100; es.EstateID = Convert.ToUInt32(idParameter.Value);
if (insertCommand.ExecuteNonQuery() > 0)
{
insertCommand.CommandText = "Select cast(lastval() as int) as ID ;";
using (NpgsqlDataReader result = insertCommand.ExecuteReader())
{
if (result.Read())
{
es.EstateID = (uint)result.GetInt32(0);
}
}
}
} }
//TODO check if this is needed?? //TODO check if this is needed??
@ -249,20 +225,20 @@ namespace OpenSim.Data.PGSQL
string sql = string.Format("UPDATE estate_settings SET "); string sql = string.Format("UPDATE estate_settings SET ");
foreach (string name in names) foreach (string name in names)
{ {
sql += "\"" + name + "\" = :" + name + ", "; sql += name + " = @" + name + ", ";
} }
sql = sql.Remove(sql.LastIndexOf(",")); sql = sql.Remove(sql.LastIndexOf(","));
sql += " WHERE \"EstateID\" = :EstateID"; sql += " WHERE EstateID = @EstateID";
using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString)) using (SqlConnection conn = new SqlConnection(m_connectionString))
using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn)) using (SqlCommand cmd = new SqlCommand(sql, conn))
{ {
foreach (string name in names) foreach (string name in names)
{ {
cmd.Parameters.Add(_Database.CreateParameter("" + name, _FieldMap[name].GetValue(es))); cmd.Parameters.Add(_Database.CreateParameter("@" + name, _FieldMap[name].GetValue(es)));
} }
cmd.Parameters.Add(_Database.CreateParameter("EstateID", es.EstateID)); cmd.Parameters.Add(_Database.CreateParameter("@EstateID", es.EstateID));
conn.Open(); conn.Open();
cmd.ExecuteNonQuery(); cmd.ExecuteNonQuery();
} }
@ -286,24 +262,22 @@ namespace OpenSim.Data.PGSQL
{ {
es.ClearBans(); es.ClearBans();
string sql = "select * from estateban where \"EstateID\" = :EstateID"; string sql = "select bannedUUID from estateban where EstateID = @EstateID";
using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString)) using (SqlConnection conn = new SqlConnection(m_connectionString))
using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn)) using (SqlCommand cmd = new SqlCommand(sql, conn))
{ {
NpgsqlParameter idParameter = new NpgsqlParameter("EstateID", DbType.Int32); SqlParameter idParameter = new SqlParameter("@EstateID", SqlDbType.Int);
idParameter.Value = es.EstateID; idParameter.Value = es.EstateID;
cmd.Parameters.Add(idParameter); cmd.Parameters.Add(idParameter);
conn.Open(); conn.Open();
using (NpgsqlDataReader reader = cmd.ExecuteReader()) using (SqlDataReader reader = cmd.ExecuteReader())
{ {
while (reader.Read()) while (reader.Read())
{ {
EstateBan eb = new EstateBan(); EstateBan eb = new EstateBan();
eb.BannedUserID = new UUID((Guid)reader["bannedUUID"]); //uuid; eb.BannedUserID = new UUID((Guid)reader["bannedUUID"]); //uuid;
eb.BanningUserID = new UUID((Guid)reader["banningUUID"]); //uuid;
eb.BanTime = Convert.ToInt32(reader["banTime"]);
eb.BannedHostAddress = "0.0.0.0"; eb.BannedHostAddress = "0.0.0.0";
eb.BannedHostIPMask = "0.0.0.0"; eb.BannedHostIPMask = "0.0.0.0";
es.AddBan(eb); es.AddBan(eb);
@ -316,14 +290,14 @@ namespace OpenSim.Data.PGSQL
{ {
List<UUID> uuids = new List<UUID>(); List<UUID> uuids = new List<UUID>();
string sql = string.Format("select uuid from {0} where \"EstateID\" = :EstateID", table); string sql = string.Format("select uuid from {0} where EstateID = @EstateID", table);
using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString)) using (SqlConnection conn = new SqlConnection(m_connectionString))
using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn)) using (SqlCommand cmd = new SqlCommand(sql, conn))
{ {
cmd.Parameters.Add(_Database.CreateParameter("EstateID", estateID)); cmd.Parameters.Add(_Database.CreateParameter("@EstateID", estateID));
conn.Open(); conn.Open();
using (NpgsqlDataReader reader = cmd.ExecuteReader()) using (SqlDataReader reader = cmd.ExecuteReader())
{ {
while (reader.Read()) while (reader.Read())
{ {
@ -338,25 +312,21 @@ namespace OpenSim.Data.PGSQL
private void SaveBanList(EstateSettings es) private void SaveBanList(EstateSettings es)
{ {
//Delete first //Delete first
using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString)) using (SqlConnection conn = new SqlConnection(m_connectionString))
{ {
conn.Open(); conn.Open();
using (NpgsqlCommand cmd = conn.CreateCommand()) using (SqlCommand cmd = conn.CreateCommand())
{ {
cmd.CommandText = "delete from estateban where \"EstateID\" = :EstateID"; cmd.CommandText = "delete from estateban where EstateID = @EstateID";
cmd.Parameters.AddWithValue("EstateID", (int)es.EstateID); cmd.Parameters.AddWithValue("@EstateID", (int)es.EstateID);
cmd.ExecuteNonQuery(); cmd.ExecuteNonQuery();
//Insert after //Insert after
cmd.CommandText = "insert into estateban (\"EstateID\", \"bannedUUID\",\"bannedIp\", \"bannedIpHostMask\", \"bannedNameMask\", \"banningUUID\",\"banTime\" ) values ( :EstateID, :bannedUUID, '','','', :banningUUID, :banTime )"; cmd.CommandText = "insert into estateban (EstateID, bannedUUID,bannedIp, bannedIpHostMask, bannedNameMask) values ( @EstateID, @bannedUUID, '','','' )";
cmd.Parameters.AddWithValue("bannedUUID", Guid.Empty); cmd.Parameters.AddWithValue("@bannedUUID", Guid.Empty);
foreach (EstateBan b in es.EstateBans) foreach (EstateBan b in es.EstateBans)
{ {
cmd.Parameters["EstateID"].Value = b.EstateID; cmd.Parameters["@bannedUUID"].Value = b.BannedUserID.Guid;
cmd.Parameters["bannedUUID"].Value = b.BannedUserID.Guid;
cmd.Parameters["banningUUID"].Value = b.BanningUserID.Guid;
cmd.Parameters["banTime"].Value = b.BanTime;
cmd.ExecuteNonQuery(); cmd.ExecuteNonQuery();
} }
} }
@ -365,20 +335,20 @@ namespace OpenSim.Data.PGSQL
private void SaveUUIDList(uint estateID, string table, UUID[] data) private void SaveUUIDList(uint estateID, string table, UUID[] data)
{ {
using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString)) using (SqlConnection conn = new SqlConnection(m_connectionString))
{ {
conn.Open(); conn.Open();
using (NpgsqlCommand cmd = conn.CreateCommand()) using (SqlCommand cmd = conn.CreateCommand())
{ {
cmd.Parameters.AddWithValue("EstateID", (int)estateID); cmd.Parameters.AddWithValue("@EstateID", (int)estateID);
cmd.CommandText = string.Format("delete from {0} where \"EstateID\" = :EstateID", table); cmd.CommandText = string.Format("delete from {0} where EstateID = @EstateID", table);
cmd.ExecuteNonQuery(); cmd.ExecuteNonQuery();
cmd.CommandText = string.Format("insert into {0} (\"EstateID\", uuid) values ( :EstateID, :uuid )", table); cmd.CommandText = string.Format("insert into {0} (EstateID, uuid) values ( @EstateID, @uuid )", table);
cmd.Parameters.AddWithValue("uuid", Guid.Empty); cmd.Parameters.AddWithValue("@uuid", Guid.Empty);
foreach (UUID uuid in data) foreach (UUID uuid in data)
{ {
cmd.Parameters["uuid"].Value = uuid.Guid; //.ToString(); //TODO check if this works cmd.Parameters["@uuid"].Value = uuid.Guid; //.ToString(); //TODO check if this works
cmd.ExecuteNonQuery(); cmd.ExecuteNonQuery();
} }
} }
@ -388,14 +358,14 @@ namespace OpenSim.Data.PGSQL
public EstateSettings LoadEstateSettings(int estateID) public EstateSettings LoadEstateSettings(int estateID)
{ {
EstateSettings es = new EstateSettings(); EstateSettings es = new EstateSettings();
string sql = "select estate_settings.\"" + String.Join("\",estate_settings.\"", FieldList) + "\" from estate_settings where \"EstateID\" = :EstateID"; string sql = "select estate_settings." + String.Join(",estate_settings.", FieldList) + " from estate_settings where EstateID = @EstateID";
using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString)) using (SqlConnection conn = new SqlConnection(m_connectionString))
{ {
conn.Open(); conn.Open();
using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn)) using (SqlCommand cmd = new SqlCommand(sql, conn))
{ {
cmd.Parameters.AddWithValue("EstateID", (int)estateID); cmd.Parameters.AddWithValue("@EstateID", (int)estateID);
using (NpgsqlDataReader reader = cmd.ExecuteReader()) using (SqlDataReader reader = cmd.ExecuteReader())
{ {
if (reader.Read()) if (reader.Read())
{ {
@ -458,13 +428,13 @@ namespace OpenSim.Data.PGSQL
public List<int> GetEstates(string search) public List<int> GetEstates(string search)
{ {
List<int> result = new List<int>(); List<int> result = new List<int>();
string sql = "select \"EstateID\" from estate_settings where lower(\"EstateName\") = lower(:EstateName)"; string sql = "select estateID from estate_settings where EstateName = @EstateName";
using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString)) using (SqlConnection conn = new SqlConnection(m_connectionString))
{ {
conn.Open(); conn.Open();
using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn)) using (SqlCommand cmd = new SqlCommand(sql, conn))
{ {
cmd.Parameters.AddWithValue("EstateName", search); cmd.Parameters.AddWithValue("@EstateName", search);
using (IDataReader reader = cmd.ExecuteReader()) using (IDataReader reader = cmd.ExecuteReader())
{ {
@ -483,11 +453,11 @@ namespace OpenSim.Data.PGSQL
public List<int> GetEstatesAll() public List<int> GetEstatesAll()
{ {
List<int> result = new List<int>(); List<int> result = new List<int>();
string sql = "select \"EstateID\" from estate_settings"; string sql = "select estateID from estate_settings";
using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString)) using (SqlConnection conn = new SqlConnection(m_connectionString))
{ {
conn.Open(); conn.Open();
using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn)) using (SqlCommand cmd = new SqlCommand(sql, conn))
{ {
using (IDataReader reader = cmd.ExecuteReader()) using (IDataReader reader = cmd.ExecuteReader())
{ {
@ -506,13 +476,13 @@ namespace OpenSim.Data.PGSQL
public List<int> GetEstatesByOwner(UUID ownerID) public List<int> GetEstatesByOwner(UUID ownerID)
{ {
List<int> result = new List<int>(); List<int> result = new List<int>();
string sql = "select \"EstateID\" from estate_settings where \"EstateOwner\" = :EstateOwner"; string sql = "select estateID from estate_settings where EstateOwner = @EstateOwner";
using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString)) using (SqlConnection conn = new SqlConnection(m_connectionString))
{ {
conn.Open(); conn.Open();
using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn)) using (SqlCommand cmd = new SqlCommand(sql, conn))
{ {
cmd.Parameters.AddWithValue("EstateOwner", ownerID); cmd.Parameters.AddWithValue("@EstateOwner", ownerID);
using (IDataReader reader = cmd.ExecuteReader()) using (IDataReader reader = cmd.ExecuteReader())
{ {
@ -530,29 +500,28 @@ namespace OpenSim.Data.PGSQL
public bool LinkRegion(UUID regionID, int estateID) public bool LinkRegion(UUID regionID, int estateID)
{ {
string deleteSQL = "delete from estate_map where \"RegionID\" = :RegionID"; string deleteSQL = "delete from estate_map where RegionID = @RegionID";
string insertSQL = "insert into estate_map values (:RegionID, :EstateID)"; string insertSQL = "insert into estate_map values (@RegionID, @EstateID)";
using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString)) using (SqlConnection conn = new SqlConnection(m_connectionString))
{ {
conn.Open(); conn.Open();
SqlTransaction transaction = conn.BeginTransaction();
NpgsqlTransaction transaction = conn.BeginTransaction();
try try
{ {
using (NpgsqlCommand cmd = new NpgsqlCommand(deleteSQL, conn)) using (SqlCommand cmd = new SqlCommand(deleteSQL, conn))
{ {
cmd.Transaction = transaction; cmd.Transaction = transaction;
cmd.Parameters.AddWithValue("RegionID", regionID.Guid); cmd.Parameters.AddWithValue("@RegionID", regionID.Guid);
cmd.ExecuteNonQuery(); cmd.ExecuteNonQuery();
} }
using (NpgsqlCommand cmd = new NpgsqlCommand(insertSQL, conn)) using (SqlCommand cmd = new SqlCommand(insertSQL, conn))
{ {
cmd.Transaction = transaction; cmd.Transaction = transaction;
cmd.Parameters.AddWithValue("RegionID", regionID.Guid); cmd.Parameters.AddWithValue("@RegionID", regionID.Guid);
cmd.Parameters.AddWithValue("EstateID", estateID); cmd.Parameters.AddWithValue("@EstateID", estateID);
int ret = cmd.ExecuteNonQuery(); int ret = cmd.ExecuteNonQuery();
@ -576,13 +545,13 @@ namespace OpenSim.Data.PGSQL
public List<UUID> GetRegions(int estateID) public List<UUID> GetRegions(int estateID)
{ {
List<UUID> result = new List<UUID>(); List<UUID> result = new List<UUID>();
string sql = "select \"RegionID\" from estate_map where \"EstateID\" = :EstateID"; string sql = "select RegionID from estate_map where EstateID = @EstateID";
using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString)) using (SqlConnection conn = new SqlConnection(m_connectionString))
{ {
conn.Open(); conn.Open();
using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn)) using (SqlCommand cmd = new SqlCommand(sql, conn))
{ {
cmd.Parameters.AddWithValue("EstateID", estateID); cmd.Parameters.AddWithValue("@EstateID", estateID);
using (IDataReader reader = cmd.ExecuteReader()) using (IDataReader reader = cmd.ExecuteReader())
{ {
@ -600,7 +569,7 @@ namespace OpenSim.Data.PGSQL
public bool DeleteEstate(int estateID) public bool DeleteEstate(int estateID)
{ {
// TODO: Implementation! // TODO: Implementation!
return false; return false;
} }
#endregion #endregion

View File

@ -1,4 +1,4 @@
/* /*
* Copyright (c) Contributors, http://opensimulator.org/ * Copyright (c) Contributors, http://opensimulator.org/
* See CONTRIBUTORS.TXT for a full list of copyright holders. * See CONTRIBUTORS.TXT for a full list of copyright holders.
* *
@ -31,18 +31,18 @@ using System.Collections.Generic;
using System.Data; using System.Data;
using OpenMetaverse; using OpenMetaverse;
using OpenSim.Framework; using OpenSim.Framework;
using System.Data.SqlClient;
using System.Reflection; using System.Reflection;
using System.Text; using System.Text;
using Npgsql;
namespace OpenSim.Data.PGSQL namespace OpenSim.Data.MSSQL
{ {
public class PGSQLFriendsData : PGSQLGenericTableHandler<FriendsData>, IFriendsData public class MSSQLFriendsData : MSSQLGenericTableHandler<FriendsData>, IFriendsData
{ {
public PGSQLFriendsData(string connectionString, string realm) public MSSQLFriendsData(string connectionString, string realm)
: base(connectionString, realm, "FriendsStore") : base(connectionString, realm, "FriendsStore")
{ {
using (NpgsqlConnection conn = new NpgsqlConnection(m_ConnectionString)) using (SqlConnection conn = new SqlConnection(m_ConnectionString))
{ {
conn.Open(); conn.Open();
Migration m = new Migration(conn, GetType().Assembly, "FriendsStore"); Migration m = new Migration(conn, GetType().Assembly, "FriendsStore");
@ -50,27 +50,19 @@ namespace OpenSim.Data.PGSQL
} }
} }
public override bool Delete(string principalID, string friend)
{
UUID princUUID = UUID.Zero;
bool ret = UUID.TryParse(principalID, out princUUID);
if (ret)
return Delete(princUUID, friend);
else
return false;
}
public bool Delete(UUID principalID, string friend) public bool Delete(UUID principalID, string friend)
{ {
using (NpgsqlConnection conn = new NpgsqlConnection(m_ConnectionString)) return Delete(principalID.ToString(), friend);
using (NpgsqlCommand cmd = new NpgsqlCommand()) }
public 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.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("@PrincipalID", principalID.ToString()));
cmd.Parameters.Add(m_database.CreateParameter("Friend", friend)); cmd.Parameters.Add(m_database.CreateParameter("@Friend", friend));
cmd.Connection = conn; cmd.Connection = conn;
conn.Open(); conn.Open();
cmd.ExecuteNonQuery(); cmd.ExecuteNonQuery();
@ -79,28 +71,19 @@ namespace OpenSim.Data.PGSQL
} }
} }
public FriendsData[] GetFriends(string principalID)
{
UUID princUUID = UUID.Zero;
bool ret = UUID.TryParse(principalID, out princUUID);
if (ret)
return GetFriends(princUUID);
else
return new FriendsData[0];
}
public FriendsData[] GetFriends(UUID principalID) public FriendsData[] GetFriends(UUID principalID)
{ {
using (NpgsqlConnection conn = new NpgsqlConnection(m_ConnectionString)) return GetFriends(principalID.ToString());
using (NpgsqlCommand cmd = new NpgsqlCommand()) }
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 " + 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);
" left join {0} as b on a.\"PrincipalID\" = b.\"Friend\" and a.\"Friend\" = b.\"PrincipalID\" " + cmd.Parameters.Add(m_database.CreateParameter("@PrincipalID", principalID.ToString()));
" where a.\"PrincipalID\" = :PrincipalID", m_Realm);
cmd.Parameters.Add(m_database.CreateParameter("PrincipalID", principalID.ToString()));
cmd.Connection = conn; cmd.Connection = conn;
conn.Open(); conn.Open();
return DoQuery(cmd); return DoQuery(cmd);
@ -109,8 +92,8 @@ namespace OpenSim.Data.PGSQL
public FriendsData[] GetFriends(Guid principalID) public FriendsData[] GetFriends(Guid principalID)
{ {
return GetFriends(principalID); return GetFriends(principalID.ToString());
} }
} }
} }

View File

@ -30,46 +30,38 @@ using System.Collections.Generic;
using System.Data; using System.Data;
using System.Reflection; using System.Reflection;
using log4net; using log4net;
using System.Data.SqlClient;
using OpenMetaverse; using OpenMetaverse;
using OpenSim.Framework; using OpenSim.Framework;
using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.Framework.Interfaces;
using System.Text; using System.Text;
using Npgsql;
namespace OpenSim.Data.PGSQL namespace OpenSim.Data.MSSQL
{ {
public class PGSQLGenericTableHandler<T> : PGSqlFramework where T : class, new() public class MSSQLGenericTableHandler<T> where T : class, new()
{ {
private static readonly ILog m_log = // private static readonly ILog m_log =
LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); // LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
protected string m_ConnectionString; protected string m_ConnectionString;
protected PGSQLManager m_database; //used for parameter type translation protected MSSQLManager m_database; //used for parameter type translation
protected Dictionary<string, FieldInfo> m_Fields = protected Dictionary<string, FieldInfo> m_Fields =
new Dictionary<string, FieldInfo>(); new Dictionary<string, FieldInfo>();
protected Dictionary<string, string> m_FieldTypes = new Dictionary<string, string>();
protected List<string> m_ColumnNames = null; protected List<string> m_ColumnNames = null;
protected string m_Realm; protected string m_Realm;
protected FieldInfo m_DataField = null; protected FieldInfo m_DataField = null;
protected virtual Assembly Assembly public MSSQLGenericTableHandler(string connectionString,
{
get { return GetType().Assembly; }
}
public PGSQLGenericTableHandler(string connectionString,
string realm, string storeName) string realm, string storeName)
: base(connectionString)
{ {
m_Realm = realm; m_Realm = realm;
m_ConnectionString = connectionString; m_ConnectionString = connectionString;
if (storeName != String.Empty) if (storeName != String.Empty)
{ {
using (NpgsqlConnection conn = new NpgsqlConnection(m_ConnectionString)) using (SqlConnection conn = new SqlConnection(m_ConnectionString))
{ {
conn.Open(); conn.Open();
Migration m = new Migration(conn, GetType().Assembly, storeName); Migration m = new Migration(conn, GetType().Assembly, storeName);
@ -77,15 +69,13 @@ namespace OpenSim.Data.PGSQL
} }
} }
m_database = new PGSQLManager(m_ConnectionString); m_database = new MSSQLManager(m_ConnectionString);
Type t = typeof(T); Type t = typeof(T);
FieldInfo[] fields = t.GetFields(BindingFlags.Public | FieldInfo[] fields = t.GetFields(BindingFlags.Public |
BindingFlags.Instance | BindingFlags.Instance |
BindingFlags.DeclaredOnly); BindingFlags.DeclaredOnly);
LoadFieldTypes();
if (fields.Length == 0) if (fields.Length == 0)
return; return;
@ -99,31 +89,7 @@ namespace OpenSim.Data.PGSQL
} }
private void LoadFieldTypes() private void CheckColumnNames(SqlDataReader reader)
{
m_FieldTypes = new Dictionary<string, string>();
string query = string.Format(@"select column_name,data_type
from INFORMATION_SCHEMA.COLUMNS
where table_name = lower('{0}');
", m_Realm);
using (NpgsqlConnection conn = new NpgsqlConnection(m_ConnectionString))
using (NpgsqlCommand cmd = new NpgsqlCommand(query, conn))
{
conn.Open();
using (NpgsqlDataReader rdr = cmd.ExecuteReader())
{
while (rdr.Read())
{
// query produces 0 to many rows of single column, so always add the first item in each row
m_FieldTypes.Add((string)rdr[0], (string)rdr[1]);
}
}
}
}
private void CheckColumnNames(NpgsqlDataReader reader)
{ {
if (m_ColumnNames != null) if (m_ColumnNames != null)
return; return;
@ -131,7 +97,6 @@ namespace OpenSim.Data.PGSQL
m_ColumnNames = new List<string>(); m_ColumnNames = new List<string>();
DataTable schemaTable = reader.GetSchemaTable(); DataTable schemaTable = reader.GetSchemaTable();
foreach (DataRow row in schemaTable.Rows) foreach (DataRow row in schemaTable.Rows)
{ {
if (row["ColumnName"] != null && if (row["ColumnName"] != null &&
@ -141,32 +106,21 @@ namespace OpenSim.Data.PGSQL
} }
} }
// TODO GET CONSTRAINTS FROM POSTGRESQL
private List<string> GetConstraints() private List<string> GetConstraints()
{ {
List<string> constraints = new List<string>(); List<string> constraints = new List<string>();
string query = string.Format(@"select string query = string.Format(@"SELECT
a.attname as column_name COL_NAME(ic.object_id,ic.column_id) AS column_name
from FROM sys.indexes AS i
pg_class t, INNER JOIN sys.index_columns AS ic
pg_class i, ON i.object_id = ic.object_id AND i.index_id = ic.index_id
pg_index ix, WHERE i.is_primary_key = 1
pg_attribute a AND i.object_id = OBJECT_ID('{0}');", m_Realm);
where using (SqlConnection conn = new SqlConnection(m_ConnectionString))
t.oid = ix.indrelid using (SqlCommand cmd = new SqlCommand(query, conn))
and i.oid = ix.indexrelid
and a.attrelid = t.oid
and a.attnum = ANY(ix.indkey)
and t.relkind = 'r'
and ix.indisunique = true
and t.relname = lower('{0}')
;", m_Realm);
using (NpgsqlConnection conn = new NpgsqlConnection(m_ConnectionString))
using (NpgsqlCommand cmd = new NpgsqlCommand(query, conn))
{ {
conn.Open(); conn.Open();
using (NpgsqlDataReader rdr = cmd.ExecuteReader()) using (SqlDataReader rdr = cmd.ExecuteReader())
{ {
while (rdr.Read()) while (rdr.Read())
{ {
@ -180,54 +134,7 @@ namespace OpenSim.Data.PGSQL
public virtual T[] Get(string field, string key) public virtual T[] Get(string field, string key)
{ {
using (NpgsqlConnection conn = new NpgsqlConnection(m_ConnectionString)) return Get(new string[] { field }, new string[] { key });
using (NpgsqlCommand cmd = new NpgsqlCommand())
{
if ( m_FieldTypes.ContainsKey(field) )
cmd.Parameters.Add(m_database.CreateParameter(field, key, m_FieldTypes[field]));
else
cmd.Parameters.Add(m_database.CreateParameter(field, key));
string query = String.Format("SELECT * FROM {0} WHERE \"{1}\" = :{1}", m_Realm, field, field);
cmd.Connection = conn;
cmd.CommandText = query;
conn.Open();
return DoQuery(cmd);
}
}
public virtual T[] Get(string field, string[] keys)
{
int flen = keys.Length;
if(flen == 0)
return new T[0];
int flast = flen - 1;
StringBuilder sb = new StringBuilder(1024);
sb.AppendFormat("select * from {0} where {1} IN ('", m_Realm, field);
using (NpgsqlConnection conn = new NpgsqlConnection(m_ConnectionString))
using (NpgsqlCommand cmd = new NpgsqlCommand())
{
for (int i = 0 ; i < flen ; i++)
{
sb.Append(keys[i]);
if(i < flast)
sb.Append("','");
else
sb.Append("')");
}
string query = sb.ToString();
cmd.Connection = conn;
cmd.CommandText = query;
conn.Open();
return DoQuery(cmd);
}
} }
public virtual T[] Get(string[] fields, string[] keys) public virtual T[] Get(string[] fields, string[] keys)
@ -237,18 +144,14 @@ namespace OpenSim.Data.PGSQL
List<string> terms = new List<string>(); List<string> terms = new List<string>();
using (NpgsqlConnection conn = new NpgsqlConnection(m_ConnectionString)) using (SqlConnection conn = new SqlConnection(m_ConnectionString))
using (NpgsqlCommand cmd = new NpgsqlCommand()) using (SqlCommand cmd = new SqlCommand())
{ {
for (int i = 0; i < fields.Length; i++) for (int i = 0; i < fields.Length; i++)
{ {
if ( m_FieldTypes.ContainsKey(fields[i]) ) cmd.Parameters.Add(m_database.CreateParameter(fields[i], keys[i]));
cmd.Parameters.Add(m_database.CreateParameter(fields[i], keys[i], m_FieldTypes[fields[i]])); terms.Add("[" + fields[i] + "] = @" + fields[i]);
else
cmd.Parameters.Add(m_database.CreateParameter(fields[i], keys[i]));
terms.Add(" \"" + fields[i] + "\" = :" + fields[i]);
} }
string where = String.Join(" AND ", terms.ToArray()); string where = String.Join(" AND ", terms.ToArray());
@ -263,23 +166,15 @@ namespace OpenSim.Data.PGSQL
} }
} }
protected T[] DoQuery(NpgsqlCommand cmd) protected T[] DoQuery(SqlCommand cmd)
{ {
List<T> result = new List<T>(); List<T> result = new List<T>();
if (cmd.Connection == null) using (SqlDataReader reader = cmd.ExecuteReader())
{
cmd.Connection = new NpgsqlConnection(m_connectionString);
}
if (cmd.Connection.State == ConnectionState.Closed)
{
cmd.Connection.Open();
}
using (NpgsqlDataReader reader = cmd.ExecuteReader())
{ {
if (reader == null) if (reader == null)
return new T[0]; return new T[0];
CheckColumnNames(reader); CheckColumnNames(reader);
while (reader.Read()) while (reader.Read())
{ {
@ -318,7 +213,6 @@ namespace OpenSim.Data.PGSQL
foreach (string col in m_ColumnNames) foreach (string col in m_ColumnNames)
{ {
data[col] = reader[col].ToString(); data[col] = reader[col].ToString();
if (data[col] == null) if (data[col] == null)
data[col] = String.Empty; data[col] = String.Empty;
} }
@ -334,34 +228,16 @@ namespace OpenSim.Data.PGSQL
public virtual T[] Get(string where) public virtual T[] Get(string where)
{ {
using (NpgsqlConnection conn = new NpgsqlConnection(m_ConnectionString)) using (SqlConnection conn = new SqlConnection(m_ConnectionString))
using (NpgsqlCommand cmd = new NpgsqlCommand()) using (SqlCommand cmd = new SqlCommand())
{ {
string query = String.Format("SELECT * FROM {0} WHERE {1}", string query = String.Format("SELECT * FROM {0} WHERE {1}",
m_Realm, where); m_Realm, where);
cmd.Connection = conn; cmd.Connection = conn;
cmd.CommandText = query; cmd.CommandText = query;
//m_log.WarnFormat("[PGSQLGenericTable]: SELECT {0} WHERE {1}", m_Realm, where);
conn.Open(); //m_log.WarnFormat("[MSSQLGenericTable]: SELECT {0} WHERE {1}", m_Realm, where);
return DoQuery(cmd);
}
}
public virtual T[] Get(string where, NpgsqlParameter parameter)
{
using (NpgsqlConnection conn = new NpgsqlConnection(m_ConnectionString))
using (NpgsqlCommand cmd = new NpgsqlCommand())
{
string query = String.Format("SELECT * FROM {0} WHERE {1}",
m_Realm, where);
cmd.Connection = conn;
cmd.CommandText = query;
//m_log.WarnFormat("[PGSQLGenericTable]: SELECT {0} WHERE {1}", m_Realm, where);
cmd.Parameters.Add(parameter);
conn.Open(); conn.Open();
return DoQuery(cmd); return DoQuery(cmd);
@ -373,8 +249,8 @@ namespace OpenSim.Data.PGSQL
List<string> constraintFields = GetConstraints(); List<string> constraintFields = GetConstraints();
List<KeyValuePair<string, string>> constraints = new List<KeyValuePair<string, string>>(); List<KeyValuePair<string, string>> constraints = new List<KeyValuePair<string, string>>();
using (NpgsqlConnection conn = new NpgsqlConnection(m_ConnectionString)) using (SqlConnection conn = new SqlConnection(m_ConnectionString))
using (NpgsqlCommand cmd = new NpgsqlCommand()) using (SqlCommand cmd = new SqlCommand())
{ {
StringBuilder query = new StringBuilder(); StringBuilder query = new StringBuilder();
@ -384,24 +260,21 @@ namespace OpenSim.Data.PGSQL
foreach (FieldInfo fi in m_Fields.Values) foreach (FieldInfo fi in m_Fields.Values)
{ {
names.Add(fi.Name); names.Add(fi.Name);
values.Add(":" + fi.Name); values.Add("@" + fi.Name);
// Temporarily return more information about what field is unexpectedly null for // 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 // 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. // InventoryTransferModule or we may be required to substitute a DBNull here.
if (fi.GetValue(row) == null) if (fi.GetValue(row) == null)
throw new NullReferenceException( throw new NullReferenceException(
string.Format( string.Format(
"[PGSQL GENERIC TABLE HANDLER]: Trying to store field {0} for {1} which is unexpectedly null", "[MSSQL GENERIC TABLE HANDLER]: Trying to store field {0} for {1} which is unexpectedly null",
fi.Name, row)); fi.Name, row));
if (constraintFields.Count > 0 && constraintFields.Contains(fi.Name)) if (constraintFields.Count > 0 && constraintFields.Contains(fi.Name))
{ {
constraints.Add(new KeyValuePair<string, string>(fi.Name, fi.GetValue(row).ToString() )); constraints.Add(new KeyValuePair<string, string>(fi.Name, fi.GetValue(row).ToString()));
} }
if (m_FieldTypes.ContainsKey(fi.Name)) cmd.Parameters.Add(m_database.CreateParameter(fi.Name, fi.GetValue(row).ToString()));
cmd.Parameters.Add(m_database.CreateParameter(fi.Name, fi.GetValue(row), m_FieldTypes[fi.Name]));
else
cmd.Parameters.Add(m_database.CreateParameter(fi.Name, fi.GetValue(row)));
} }
if (m_DataField != null) if (m_DataField != null)
@ -416,12 +289,8 @@ namespace OpenSim.Data.PGSQL
constraints.Add(new KeyValuePair<string, string>(kvp.Key, kvp.Key)); constraints.Add(new KeyValuePair<string, string>(kvp.Key, kvp.Key));
} }
names.Add(kvp.Key); names.Add(kvp.Key);
values.Add(":" + kvp.Key); values.Add("@" + kvp.Key);
cmd.Parameters.Add(m_database.CreateParameter("@" + kvp.Key, kvp.Value));
if (m_FieldTypes.ContainsKey(kvp.Key))
cmd.Parameters.Add(m_database.CreateParameter("" + kvp.Key, kvp.Value, m_FieldTypes[kvp.Key]));
else
cmd.Parameters.Add(m_database.CreateParameter("" + kvp.Key, kvp.Value));
} }
} }
@ -430,27 +299,27 @@ namespace OpenSim.Data.PGSQL
int i = 0; int i = 0;
for (i = 0; i < names.Count - 1; i++) for (i = 0; i < names.Count - 1; i++)
{ {
query.AppendFormat("\"{0}\" = {1}, ", names[i], values[i]); query.AppendFormat("[{0}] = {1}, ", names[i], values[i]);
} }
query.AppendFormat("\"{0}\" = {1} ", names[i], values[i]); query.AppendFormat("[{0}] = {1} ", names[i], values[i]);
if (constraints.Count > 0) if (constraints.Count > 0)
{ {
List<string> terms = new List<string>(); List<string> terms = new List<string>();
for (int j = 0; j < constraints.Count; j++) for (int j = 0; j < constraints.Count; j++)
{ {
terms.Add(String.Format(" \"{0}\" = :{0}", constraints[j].Key)); terms.Add(" [" + constraints[j].Key + "] = @" + constraints[j].Key);
} }
string where = String.Join(" AND ", terms.ToArray()); string where = String.Join(" AND ", terms.ToArray());
query.AppendFormat(" WHERE {0} ", where); query.AppendFormat(" WHERE {0} ", where);
} }
cmd.Connection = conn; cmd.Connection = conn;
cmd.CommandText = query.ToString(); cmd.CommandText = query.ToString();
conn.Open(); conn.Open();
if (cmd.ExecuteNonQuery() > 0) if (cmd.ExecuteNonQuery() > 0)
{ {
//m_log.WarnFormat("[PGSQLGenericTable]: Updating {0}", m_Realm); //m_log.WarnFormat("[MSSQLGenericTable]: Updating {0}", m_Realm);
return true; return true;
} }
else else
@ -458,14 +327,12 @@ namespace OpenSim.Data.PGSQL
// assume record has not yet been inserted // assume record has not yet been inserted
query = new StringBuilder(); query = new StringBuilder();
query.AppendFormat("INSERT INTO {0} (\"", m_Realm); query.AppendFormat("INSERT INTO {0} ([", m_Realm);
query.Append(String.Join("\",\"", names.ToArray())); query.Append(String.Join("],[", names.ToArray()));
query.Append("\") values (" + String.Join(",", values.ToArray()) + ")"); query.Append("]) values (" + String.Join(",", values.ToArray()) + ")");
cmd.Connection = conn; cmd.Connection = conn;
cmd.CommandText = query.ToString(); cmd.CommandText = query.ToString();
//m_log.WarnFormat("[MSSQLGenericTable]: Inserting into {0}", m_Realm);
// m_log.WarnFormat("[PGSQLGenericTable]: Inserting into {0} sql {1}", m_Realm, cmd.CommandText);
if (conn.State != ConnectionState.Open) if (conn.State != ConnectionState.Open)
conn.Open(); conn.Open();
if (cmd.ExecuteNonQuery() > 0) if (cmd.ExecuteNonQuery() > 0)
@ -488,17 +355,13 @@ namespace OpenSim.Data.PGSQL
List<string> terms = new List<string>(); List<string> terms = new List<string>();
using (NpgsqlConnection conn = new NpgsqlConnection(m_ConnectionString)) using (SqlConnection conn = new SqlConnection(m_ConnectionString))
using (NpgsqlCommand cmd = new NpgsqlCommand()) using (SqlCommand cmd = new SqlCommand())
{ {
for (int i = 0; i < fields.Length; i++) for (int i = 0; i < fields.Length; i++)
{ {
if (m_FieldTypes.ContainsKey(fields[i])) cmd.Parameters.Add(m_database.CreateParameter(fields[i], keys[i]));
cmd.Parameters.Add(m_database.CreateParameter(fields[i], keys[i], m_FieldTypes[fields[i]])); terms.Add("[" + fields[i] + "] = @" + fields[i]);
else
cmd.Parameters.Add(m_database.CreateParameter(fields[i], keys[i]));
terms.Add(" \"" + fields[i] + "\" = :" + fields[i]);
} }
string where = String.Join(" AND ", terms.ToArray()); string where = String.Join(" AND ", terms.ToArray());
@ -511,69 +374,11 @@ namespace OpenSim.Data.PGSQL
if (cmd.ExecuteNonQuery() > 0) if (cmd.ExecuteNonQuery() > 0)
{ {
//m_log.Warn("[PGSQLGenericTable]: " + deleteCommand); //m_log.Warn("[MSSQLGenericTable]: " + deleteCommand);
return true; return true;
} }
return false; return false;
} }
} }
public long GetCount(string field, string key)
{
return GetCount(new string[] { field }, new string[] { key });
}
public long GetCount(string[] fields, string[] keys)
{
if (fields.Length != keys.Length)
return 0;
List<string> terms = new List<string>();
using (NpgsqlCommand cmd = new NpgsqlCommand())
{
for (int i = 0; i < fields.Length; i++)
{
cmd.Parameters.AddWithValue(fields[i], keys[i]);
terms.Add("\"" + fields[i] + "\" = :" + fields[i]);
}
string where = String.Join(" and ", terms.ToArray());
string query = String.Format("select count(*) from {0} where {1}",
m_Realm, where);
cmd.CommandText = query;
Object result = DoQueryScalar(cmd);
return Convert.ToInt64(result);
}
}
public long GetCount(string where)
{
using (NpgsqlCommand cmd = new NpgsqlCommand())
{
string query = String.Format("select count(*) from {0} where {1}",
m_Realm, where);
cmd.CommandText = query;
object result = DoQueryScalar(cmd);
return Convert.ToInt64(result);
}
}
public object DoQueryScalar(NpgsqlCommand cmd)
{
using (NpgsqlConnection dbcon = new NpgsqlConnection(m_ConnectionString))
{
dbcon.Open();
cmd.Connection = dbcon;
return cmd.ExecuteScalar();
}
}
} }
} }

View File

@ -33,18 +33,19 @@ using System.Threading;
using log4net; using log4net;
using OpenMetaverse; using OpenMetaverse;
using OpenSim.Framework; using OpenSim.Framework;
using System.Data.SqlClient;
namespace OpenSim.Data.PGSQL namespace OpenSim.Data.MSSQL
{ {
/// <summary> /// <summary>
/// A PGSQL Interface for Avatar Storage /// A MSSQL Interface for Avatar Storage
/// </summary> /// </summary>
public class PGSQLGridUserData : PGSQLGenericTableHandler<GridUserData>, public class MSSQLGridUserData : MSSQLGenericTableHandler<GridUserData>,
IGridUserData IGridUserData
{ {
// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); // private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
public PGSQLGridUserData(string connectionString, string realm) : public MSSQLGridUserData(string connectionString, string realm) :
base(connectionString, realm, "GridUserStore") base(connectionString, realm, "GridUserStore")
{ {
} }
@ -61,7 +62,7 @@ namespace OpenSim.Data.PGSQL
public GridUserData[] GetAll(string userID) public GridUserData[] GetAll(string userID)
{ {
return base.Get(String.Format("\"UserID\" LIKE '{0}%'", userID)); return base.Get(String.Format("UserID LIKE '{0}%'", userID));
} }
} }

View File

@ -28,18 +28,18 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Data; using System.Data;
using System.Data.SqlClient;
using System.Reflection; using System.Reflection;
using log4net; using log4net;
using OpenMetaverse; using OpenMetaverse;
using OpenSim.Framework; using OpenSim.Framework;
using Npgsql;
namespace OpenSim.Data.PGSQL namespace OpenSim.Data.MSSQL
{ {
/// <summary> /// <summary>
/// A PGSQL interface for the inventory server /// A MSSQL interface for the inventory server
/// </summary> /// </summary>
public class PGSQLInventoryData : IInventoryDataPlugin public class MSSQLInventoryData : IInventoryDataPlugin
{ {
private const string _migrationStore = "InventoryStore"; private const string _migrationStore = "InventoryStore";
@ -48,7 +48,7 @@ namespace OpenSim.Data.PGSQL
/// <summary> /// <summary>
/// The database manager /// The database manager
/// </summary> /// </summary>
private PGSQLManager database; private MSSQLManager database;
private string m_connectionString; private string m_connectionString;
#region IPlugin members #region IPlugin members
@ -56,20 +56,20 @@ namespace OpenSim.Data.PGSQL
[Obsolete("Cannot be default-initialized!")] [Obsolete("Cannot be default-initialized!")]
public void Initialise() public void Initialise()
{ {
m_log.Info("[PGSQLInventoryData]: " + Name + " cannot be default-initialized!"); m_log.Info("[MSSQLInventoryData]: " + Name + " cannot be default-initialized!");
throw new PluginNotInitialisedException(Name); throw new PluginNotInitialisedException(Name);
} }
/// <summary> /// <summary>
/// Loads and initialises the PGSQL inventory storage interface /// Loads and initialises the MSSQL inventory storage interface
/// </summary> /// </summary>
/// <param name="connectionString">connect string</param> /// <param name="connectionString">connect string</param>
/// <remarks>use PGSQL_connection.ini</remarks> /// <remarks>use mssql_connection.ini</remarks>
public void Initialise(string connectionString) public void Initialise(string connectionString)
{ {
m_connectionString = connectionString; m_connectionString = connectionString;
database = new PGSQLManager(connectionString); database = new MSSQLManager(connectionString);
//New migrations check of store //New migrations check of store
database.CheckMigration(_migrationStore); database.CheckMigration(_migrationStore);
} }
@ -80,7 +80,7 @@ namespace OpenSim.Data.PGSQL
/// <returns>A string containing the name of the DB provider</returns> /// <returns>A string containing the name of the DB provider</returns>
public string Name public string Name
{ {
get { return "PGSQL Inventory Data Interface"; } get { return "MSSQL Inventory Data Interface"; }
} }
/// <summary> /// <summary>
@ -158,13 +158,13 @@ namespace OpenSim.Data.PGSQL
/// <returns>A folder class</returns> /// <returns>A folder class</returns>
public InventoryFolderBase getInventoryFolder(UUID folderID) public InventoryFolderBase getInventoryFolder(UUID folderID)
{ {
string sql = "SELECT * FROM inventoryfolders WHERE \"folderID\" = :folderID"; string sql = "SELECT * FROM inventoryfolders WHERE folderID = @folderID";
using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString)) using (SqlConnection conn = new SqlConnection(m_connectionString))
using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn)) using (SqlCommand cmd = new SqlCommand(sql, conn))
{ {
cmd.Parameters.Add(database.CreateParameter("folderID", folderID)); cmd.Parameters.Add(database.CreateParameter("folderID", folderID));
conn.Open(); conn.Open();
using (NpgsqlDataReader reader = cmd.ExecuteReader()) using (SqlDataReader reader = cmd.ExecuteReader())
{ {
if (reader.Read()) if (reader.Read())
{ {
@ -190,8 +190,8 @@ namespace OpenSim.Data.PGSQL
/* NOTE: the implementation below is very inefficient (makes a separate request to get subfolders for /* 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 * every found folder, recursively). Inventory code for other DBs has been already rewritten to get ALL
* inventory for a specific user at once. * inventory for a specific user at once.
* *
* Meanwhile, one little thing is corrected: getFolderHierarchy(UUID.Zero) doesn't make sense and should never * 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. * be used, so check for that and return an empty list.
*/ */
@ -200,11 +200,11 @@ namespace OpenSim.Data.PGSQL
if (parentID == UUID.Zero) if (parentID == UUID.Zero)
return folders; return folders;
string sql = "SELECT * FROM inventoryfolders WHERE \"parentFolderID\" = :parentID"; string sql = "SELECT * FROM inventoryfolders WHERE parentFolderID = @parentID";
using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString)) using (SqlConnection conn = new SqlConnection(m_connectionString))
using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn)) using (SqlCommand cmd = new SqlCommand(sql, conn))
{ {
cmd.Parameters.Add(database.CreateParameter("parentID", parentID)); cmd.Parameters.Add(database.CreateParameter("@parentID", parentID));
conn.Open(); conn.Open();
folders.AddRange(getInventoryFolders(cmd)); folders.AddRange(getInventoryFolders(cmd));
@ -228,8 +228,8 @@ namespace OpenSim.Data.PGSQL
/// <param name="folder">Folder to create</param> /// <param name="folder">Folder to create</param>
public void addInventoryFolder(InventoryFolderBase folder) public void addInventoryFolder(InventoryFolderBase folder)
{ {
string sql = "INSERT INTO inventoryfolders (\"folderID\", \"agentID\", \"parentFolderID\", \"folderName\", type, version) " + string sql = @"INSERT INTO inventoryfolders ([folderID], [agentID], [parentFolderID], [folderName], [type], [version])
" VALUES (:folderID, :agentID, :parentFolderID, :folderName, :type, :version);"; VALUES (@folderID, @agentID, @parentFolderID, @folderName, @type, @version);";
string folderName = folder.Name; string folderName = folder.Name;
if (folderName.Length > 64) if (folderName.Length > 64)
@ -237,8 +237,8 @@ namespace OpenSim.Data.PGSQL
folderName = folderName.Substring(0, 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"); m_log.Warn("[INVENTORY DB]: Name field truncated from " + folder.Name.Length.ToString() + " to " + folderName.Length + " characters on add");
} }
using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString)) using (SqlConnection conn = new SqlConnection(m_connectionString))
using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn)) using (SqlCommand cmd = new SqlCommand(sql, conn))
{ {
cmd.Parameters.Add(database.CreateParameter("folderID", folder.ID)); cmd.Parameters.Add(database.CreateParameter("folderID", folder.ID));
cmd.Parameters.Add(database.CreateParameter("agentID", folder.Owner)); cmd.Parameters.Add(database.CreateParameter("agentID", folder.Owner));
@ -264,12 +264,12 @@ namespace OpenSim.Data.PGSQL
/// <param name="folder">Folder to update</param> /// <param name="folder">Folder to update</param>
public void updateInventoryFolder(InventoryFolderBase folder) public void updateInventoryFolder(InventoryFolderBase folder)
{ {
string sql = @"UPDATE inventoryfolders SET ""agentID"" = :agentID, string sql = @"UPDATE inventoryfolders SET agentID = @agentID,
""parentFolderID"" = :parentFolderID, parentFolderID = @parentFolderID,
""folderName"" = :folderName, folderName = @folderName,
type = :type, type = @type,
version = :version version = @version
WHERE folderID = :folderID"; WHERE folderID = @folderID";
string folderName = folder.Name; string folderName = folder.Name;
if (folderName.Length > 64) if (folderName.Length > 64)
@ -277,8 +277,8 @@ namespace OpenSim.Data.PGSQL
folderName = folderName.Substring(0, 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"); m_log.Warn("[INVENTORY DB]: Name field truncated from " + folder.Name.Length.ToString() + " to " + folderName.Length + " characters on update");
} }
using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString)) using (SqlConnection conn = new SqlConnection(m_connectionString))
using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn)) using (SqlCommand cmd = new SqlCommand(sql, conn))
{ {
cmd.Parameters.Add(database.CreateParameter("folderID", folder.ID)); cmd.Parameters.Add(database.CreateParameter("folderID", folder.ID));
cmd.Parameters.Add(database.CreateParameter("agentID", folder.Owner)); cmd.Parameters.Add(database.CreateParameter("agentID", folder.Owner));
@ -304,9 +304,9 @@ namespace OpenSim.Data.PGSQL
/// <param name="folder">Folder to update</param> /// <param name="folder">Folder to update</param>
public void moveInventoryFolder(InventoryFolderBase folder) public void moveInventoryFolder(InventoryFolderBase folder)
{ {
string sql = @"UPDATE inventoryfolders SET ""parentFolderID"" = :parentFolderID WHERE ""folderID"" = :folderID"; string sql = @"UPDATE inventoryfolders SET parentFolderID = @parentFolderID WHERE folderID = @folderID";
using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString)) using (SqlConnection conn = new SqlConnection(m_connectionString))
using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn)) using (SqlCommand cmd = new SqlCommand(sql, conn))
{ {
cmd.Parameters.Add(database.CreateParameter("parentFolderID", folder.ParentID)); cmd.Parameters.Add(database.CreateParameter("parentFolderID", folder.ParentID));
cmd.Parameters.Add(database.CreateParameter("folderID", folder.ID)); cmd.Parameters.Add(database.CreateParameter("folderID", folder.ID));
@ -328,16 +328,16 @@ namespace OpenSim.Data.PGSQL
/// <param name="folderID">Id of folder to delete</param> /// <param name="folderID">Id of folder to delete</param>
public void deleteInventoryFolder(UUID folderID) public void deleteInventoryFolder(UUID folderID)
{ {
string sql = @"SELECT * FROM inventoryfolders WHERE ""parentFolderID"" = :parentID"; string sql = "SELECT * FROM inventoryfolders WHERE parentFolderID = @parentID";
using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString)) using (SqlConnection conn = new SqlConnection(m_connectionString))
using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn)) using (SqlCommand cmd = new SqlCommand(sql, conn))
{ {
List<InventoryFolderBase> subFolders; List<InventoryFolderBase> subFolders;
cmd.Parameters.Add(database.CreateParameter("parentID", UUID.Zero)); cmd.Parameters.Add(database.CreateParameter("@parentID", UUID.Zero));
conn.Open(); conn.Open();
subFolders = getFolderHierarchy(folderID, cmd); subFolders = getFolderHierarchy(folderID, cmd);
//Delete all sub-folders //Delete all sub-folders
foreach (InventoryFolderBase f in subFolders) foreach (InventoryFolderBase f in subFolders)
@ -363,15 +363,15 @@ namespace OpenSim.Data.PGSQL
/// <returns>A list containing inventory items</returns> /// <returns>A list containing inventory items</returns>
public List<InventoryItemBase> getInventoryInFolder(UUID folderID) public List<InventoryItemBase> getInventoryInFolder(UUID folderID)
{ {
string sql = @"SELECT * FROM inventoryitems WHERE ""parentFolderID"" = :parentFolderID"; string sql = "SELECT * FROM inventoryitems WHERE parentFolderID = @parentFolderID";
using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString)) using (SqlConnection conn = new SqlConnection(m_connectionString))
using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn)) using (SqlCommand cmd = new SqlCommand(sql, conn))
{ {
cmd.Parameters.Add(database.CreateParameter("parentFolderID", folderID)); cmd.Parameters.Add(database.CreateParameter("parentFolderID", folderID));
conn.Open(); conn.Open();
List<InventoryItemBase> items = new List<InventoryItemBase>(); List<InventoryItemBase> items = new List<InventoryItemBase>();
using (NpgsqlDataReader reader = cmd.ExecuteReader()) using (SqlDataReader reader = cmd.ExecuteReader())
{ {
while (reader.Read()) while (reader.Read())
{ {
@ -389,13 +389,13 @@ namespace OpenSim.Data.PGSQL
/// <returns>An inventory item</returns> /// <returns>An inventory item</returns>
public InventoryItemBase getInventoryItem(UUID itemID) public InventoryItemBase getInventoryItem(UUID itemID)
{ {
string sql = @"SELECT * FROM inventoryitems WHERE ""inventoryID"" = :inventoryID"; string sql = "SELECT * FROM inventoryitems WHERE inventoryID = @inventoryID";
using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString)) using (SqlConnection conn = new SqlConnection(m_connectionString))
using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn)) using (SqlCommand cmd = new SqlCommand(sql, conn))
{ {
cmd.Parameters.Add(database.CreateParameter("inventoryID", itemID)); cmd.Parameters.Add(database.CreateParameter("inventoryID", itemID));
conn.Open(); conn.Open();
using (NpgsqlDataReader reader = cmd.ExecuteReader()) using (SqlDataReader reader = cmd.ExecuteReader())
{ {
if (reader.Read()) if (reader.Read())
{ {
@ -403,7 +403,7 @@ namespace OpenSim.Data.PGSQL
} }
} }
} }
m_log.InfoFormat("[INVENTORY DB]: Found no inventory item with ID : {0}", itemID); m_log.InfoFormat("[INVENTORY DB]: Found no inventory item with ID : {0}", itemID);
return null; return null;
} }
@ -420,24 +420,24 @@ namespace OpenSim.Data.PGSQL
return; return;
} }
string sql = @"INSERT INTO inventoryitems string sql = @"INSERT INTO inventoryitems
(""inventoryID"", ""assetID"", ""assetType"", ""parentFolderID"", ""avatarID"", ""inventoryName"", ([inventoryID], [assetID], [assetType], [parentFolderID], [avatarID], [inventoryName],
""inventoryDescription"", ""inventoryNextPermissions"", ""inventoryCurrentPermissions"", [inventoryDescription], [inventoryNextPermissions], [inventoryCurrentPermissions],
""invType"", ""creatorID"", ""inventoryBasePermissions"", ""inventoryEveryOnePermissions"", ""inventoryGroupPermissions"", [invType], [creatorID], [inventoryBasePermissions], [inventoryEveryOnePermissions], [inventoryGroupPermissions],
""salePrice"", ""SaleType"", ""creationDate"", ""groupID"", ""groupOwned"", flags) [salePrice], [saleType], [creationDate], [groupID], [groupOwned], [flags])
VALUES VALUES
(:inventoryID, :assetID, :assetType, :parentFolderID, :avatarID, :inventoryName, :inventoryDescription, (@inventoryID, @assetID, @assetType, @parentFolderID, @avatarID, @inventoryName, @inventoryDescription,
:inventoryNextPermissions, :inventoryCurrentPermissions, :invType, :creatorID, @inventoryNextPermissions, @inventoryCurrentPermissions, @invType, @creatorID,
:inventoryBasePermissions, :inventoryEveryOnePermissions, :inventoryGroupPermissions, :SalePrice, :SaleType, @inventoryBasePermissions, @inventoryEveryOnePermissions, @inventoryGroupPermissions, @salePrice, @saleType,
:creationDate, :groupID, :groupOwned, :flags)"; @creationDate, @groupID, @groupOwned, @flags)";
string itemName = item.Name; string itemName = item.Name;
if (item.Name.Length > 64) if (item.Name.Length > 64)
{ {
itemName = item.Name.Substring(0, 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"); m_log.Warn("[INVENTORY DB]: Name field truncated from " + item.Name.Length.ToString() + " to " + itemName.Length.ToString() + " characters");
} }
string itemDesc = item.Description; string itemDesc = item.Description;
if (item.Description.Length > 128) if (item.Description.Length > 128)
{ {
@ -445,8 +445,8 @@ namespace OpenSim.Data.PGSQL
m_log.Warn("[INVENTORY DB]: Description field truncated from " + item.Description.Length.ToString() + " to " + itemDesc.Length.ToString() + " characters"); m_log.Warn("[INVENTORY DB]: Description field truncated from " + item.Description.Length.ToString() + " to " + itemDesc.Length.ToString() + " characters");
} }
using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString)) using (SqlConnection conn = new SqlConnection(m_connectionString))
using (NpgsqlCommand command = new NpgsqlCommand(sql, conn)) using (SqlCommand command = new SqlCommand(sql, conn))
{ {
command.Parameters.Add(database.CreateParameter("inventoryID", item.ID)); command.Parameters.Add(database.CreateParameter("inventoryID", item.ID));
command.Parameters.Add(database.CreateParameter("assetID", item.AssetID)); command.Parameters.Add(database.CreateParameter("assetID", item.AssetID));
@ -462,8 +462,8 @@ namespace OpenSim.Data.PGSQL
command.Parameters.Add(database.CreateParameter("inventoryBasePermissions", item.BasePermissions)); command.Parameters.Add(database.CreateParameter("inventoryBasePermissions", item.BasePermissions));
command.Parameters.Add(database.CreateParameter("inventoryEveryOnePermissions", item.EveryOnePermissions)); command.Parameters.Add(database.CreateParameter("inventoryEveryOnePermissions", item.EveryOnePermissions));
command.Parameters.Add(database.CreateParameter("inventoryGroupPermissions", item.GroupPermissions)); command.Parameters.Add(database.CreateParameter("inventoryGroupPermissions", item.GroupPermissions));
command.Parameters.Add(database.CreateParameter("SalePrice", item.SalePrice)); command.Parameters.Add(database.CreateParameter("salePrice", item.SalePrice));
command.Parameters.Add(database.CreateParameter("SaleType", item.SaleType)); command.Parameters.Add(database.CreateParameter("saleType", item.SaleType));
command.Parameters.Add(database.CreateParameter("creationDate", item.CreationDate)); command.Parameters.Add(database.CreateParameter("creationDate", item.CreationDate));
command.Parameters.Add(database.CreateParameter("groupID", item.GroupID)); command.Parameters.Add(database.CreateParameter("groupID", item.GroupID));
command.Parameters.Add(database.CreateParameter("groupOwned", item.GroupOwned)); command.Parameters.Add(database.CreateParameter("groupOwned", item.GroupOwned));
@ -479,9 +479,9 @@ namespace OpenSim.Data.PGSQL
} }
} }
sql = @"UPDATE inventoryfolders SET version = version + 1 WHERE ""folderID"" = @folderID"; sql = "UPDATE inventoryfolders SET version = version + 1 WHERE folderID = @folderID";
using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString)) using (SqlConnection conn = new SqlConnection(m_connectionString))
using (NpgsqlCommand command = new NpgsqlCommand(sql, conn)) using (SqlCommand command = new SqlCommand(sql, conn))
{ {
command.Parameters.Add(database.CreateParameter("folderID", item.Folder.ToString())); command.Parameters.Add(database.CreateParameter("folderID", item.Folder.ToString()));
conn.Open(); conn.Open();
@ -502,26 +502,26 @@ namespace OpenSim.Data.PGSQL
/// <param name="item">Inventory item to update</param> /// <param name="item">Inventory item to update</param>
public void updateInventoryItem(InventoryItemBase item) public void updateInventoryItem(InventoryItemBase item)
{ {
string sql = @"UPDATE inventoryitems SET ""assetID"" = :assetID, string sql = @"UPDATE inventoryitems SET assetID = @assetID,
""assetType"" = :assetType, assetType = @assetType,
""parentFolderID"" = :parentFolderID, parentFolderID = @parentFolderID,
""avatarID"" = :avatarID, avatarID = @avatarID,
""inventoryName"" = :inventoryName, inventoryName = @inventoryName,
""inventoryDescription"" = :inventoryDescription, inventoryDescription = @inventoryDescription,
""inventoryNextPermissions"" = :inventoryNextPermissions, inventoryNextPermissions = @inventoryNextPermissions,
""inventoryCurrentPermissions"" = :inventoryCurrentPermissions, inventoryCurrentPermissions = @inventoryCurrentPermissions,
""invType"" = :invType, invType = @invType,
""creatorID"" = :creatorID, creatorID = @creatorID,
""inventoryBasePermissions"" = :inventoryBasePermissions, inventoryBasePermissions = @inventoryBasePermissions,
""inventoryEveryOnePermissions"" = :inventoryEveryOnePermissions, inventoryEveryOnePermissions = @inventoryEveryOnePermissions,
""inventoryGroupPermissions"" = :inventoryGroupPermissions, inventoryGroupPermissions = @inventoryGroupPermissions,
""salePrice"" = :SalePrice, salePrice = @salePrice,
""saleType"" = :SaleType, saleType = @saleType,
""creationDate"" = :creationDate, creationDate = @creationDate,
""groupID"" = :groupID, groupID = @groupID,
""groupOwned"" = :groupOwned, groupOwned = @groupOwned,
flags = :flags flags = @flags
WHERE ""inventoryID"" = :inventoryID"; WHERE inventoryID = @inventoryID";
string itemName = item.Name; string itemName = item.Name;
if (item.Name.Length > 64) if (item.Name.Length > 64)
@ -529,7 +529,7 @@ namespace OpenSim.Data.PGSQL
itemName = item.Name.Substring(0, 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"); m_log.Warn("[INVENTORY DB]: Name field truncated from " + item.Name.Length.ToString() + " to " + itemName.Length.ToString() + " characters on update");
} }
string itemDesc = item.Description; string itemDesc = item.Description;
if (item.Description.Length > 128) if (item.Description.Length > 128)
{ {
@ -537,8 +537,8 @@ namespace OpenSim.Data.PGSQL
m_log.Warn("[INVENTORY DB]: Description field truncated from " + item.Description.Length.ToString() + " to " + itemDesc.Length.ToString() + " characters on update"); m_log.Warn("[INVENTORY DB]: Description field truncated from " + item.Description.Length.ToString() + " to " + itemDesc.Length.ToString() + " characters on update");
} }
using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString)) using (SqlConnection conn = new SqlConnection(m_connectionString))
using (NpgsqlCommand command = new NpgsqlCommand(sql, conn)) using (SqlCommand command = new SqlCommand(sql, conn))
{ {
command.Parameters.Add(database.CreateParameter("inventoryID", item.ID)); command.Parameters.Add(database.CreateParameter("inventoryID", item.ID));
command.Parameters.Add(database.CreateParameter("assetID", item.AssetID)); command.Parameters.Add(database.CreateParameter("assetID", item.AssetID));
@ -554,8 +554,8 @@ namespace OpenSim.Data.PGSQL
command.Parameters.Add(database.CreateParameter("inventoryBasePermissions", item.BasePermissions)); command.Parameters.Add(database.CreateParameter("inventoryBasePermissions", item.BasePermissions));
command.Parameters.Add(database.CreateParameter("inventoryEveryOnePermissions", item.EveryOnePermissions)); command.Parameters.Add(database.CreateParameter("inventoryEveryOnePermissions", item.EveryOnePermissions));
command.Parameters.Add(database.CreateParameter("inventoryGroupPermissions", item.GroupPermissions)); command.Parameters.Add(database.CreateParameter("inventoryGroupPermissions", item.GroupPermissions));
command.Parameters.Add(database.CreateParameter("SalePrice", item.SalePrice)); command.Parameters.Add(database.CreateParameter("salePrice", item.SalePrice));
command.Parameters.Add(database.CreateParameter("SaleType", item.SaleType)); command.Parameters.Add(database.CreateParameter("saleType", item.SaleType));
command.Parameters.Add(database.CreateParameter("creationDate", item.CreationDate)); command.Parameters.Add(database.CreateParameter("creationDate", item.CreationDate));
command.Parameters.Add(database.CreateParameter("groupID", item.GroupID)); command.Parameters.Add(database.CreateParameter("groupID", item.GroupID));
command.Parameters.Add(database.CreateParameter("groupOwned", item.GroupOwned)); command.Parameters.Add(database.CreateParameter("groupOwned", item.GroupOwned));
@ -580,9 +580,9 @@ namespace OpenSim.Data.PGSQL
/// <param name="itemID">the item UUID</param> /// <param name="itemID">the item UUID</param>
public void deleteInventoryItem(UUID itemID) public void deleteInventoryItem(UUID itemID)
{ {
string sql = @"DELETE FROM inventoryitems WHERE ""inventoryID""=:inventoryID"; string sql = "DELETE FROM inventoryitems WHERE inventoryID=@inventoryID";
using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString)) using (SqlConnection conn = new SqlConnection(m_connectionString))
using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn)) using (SqlCommand cmd = new SqlCommand(sql, conn))
{ {
cmd.Parameters.Add(database.CreateParameter("inventoryID", itemID)); cmd.Parameters.Add(database.CreateParameter("inventoryID", itemID));
try try
@ -616,14 +616,14 @@ namespace OpenSim.Data.PGSQL
/// </returns> /// </returns>
public List<InventoryItemBase> fetchActiveGestures(UUID avatarID) public List<InventoryItemBase> fetchActiveGestures(UUID avatarID)
{ {
string sql = @"SELECT * FROM inventoryitems WHERE ""avatarID"" = :uuid AND ""assetType"" = :assetType and flags = 1"; string sql = "SELECT * FROM inventoryitems WHERE avatarId = @uuid AND assetType = @assetType and flags = 1";
using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString)) using (SqlConnection conn = new SqlConnection(m_connectionString))
using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn)) using (SqlCommand cmd = new SqlCommand(sql, conn))
{ {
cmd.Parameters.Add(database.CreateParameter("uuid", avatarID)); cmd.Parameters.Add(database.CreateParameter("uuid", avatarID));
cmd.Parameters.Add(database.CreateParameter("assetType", (int)AssetType.Gesture)); cmd.Parameters.Add(database.CreateParameter("assetType", (int)AssetType.Gesture));
conn.Open(); conn.Open();
using (NpgsqlDataReader reader = cmd.ExecuteReader()) using (SqlDataReader reader = cmd.ExecuteReader())
{ {
List<InventoryItemBase> gestureList = new List<InventoryItemBase>(); List<InventoryItemBase> gestureList = new List<InventoryItemBase>();
while (reader.Read()) while (reader.Read())
@ -644,9 +644,9 @@ namespace OpenSim.Data.PGSQL
/// </summary> /// </summary>
/// <param name="folderID">the item ID</param> /// <param name="folderID">the item ID</param>
/// <param name="connection">connection to the database</param> /// <param name="connection">connection to the database</param>
private void DeleteItemsInFolder(UUID folderID, NpgsqlConnection connection) private void DeleteItemsInFolder(UUID folderID, SqlConnection connection)
{ {
using (NpgsqlCommand command = new NpgsqlCommand(@"DELETE FROM inventoryitems WHERE ""folderID""=:folderID", connection)) using (SqlCommand command = new SqlCommand("DELETE FROM inventoryitems WHERE folderID=@folderID", connection))
{ {
command.Parameters.Add(database.CreateParameter("folderID", folderID)); command.Parameters.Add(database.CreateParameter("folderID", folderID));
@ -667,9 +667,9 @@ namespace OpenSim.Data.PGSQL
/// <param name="parentID">parent ID.</param> /// <param name="parentID">parent ID.</param>
/// <param name="command">SQL command/connection to database</param> /// <param name="command">SQL command/connection to database</param>
/// <returns></returns> /// <returns></returns>
private static List<InventoryFolderBase> getFolderHierarchy(UUID parentID, NpgsqlCommand command) private static List<InventoryFolderBase> getFolderHierarchy(UUID parentID, SqlCommand command)
{ {
command.Parameters["parentID"].Value = parentID.Guid; //.ToString(); command.Parameters["@parentID"].Value = parentID.Guid; //.ToString();
List<InventoryFolderBase> folders = getInventoryFolders(command); List<InventoryFolderBase> folders = getInventoryFolders(command);
@ -698,9 +698,9 @@ namespace OpenSim.Data.PGSQL
/// <returns></returns> /// <returns></returns>
private List<InventoryFolderBase> getInventoryFolders(UUID parentID, UUID user) private List<InventoryFolderBase> getInventoryFolders(UUID parentID, UUID user)
{ {
string sql = @"SELECT * FROM inventoryfolders WHERE ""parentFolderID"" = :parentID AND ""agentID"" = :uuid"; string sql = "SELECT * FROM inventoryfolders WHERE parentFolderID = @parentID AND agentID LIKE @uuid";
using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString)) using (SqlConnection conn = new SqlConnection(m_connectionString))
using (NpgsqlCommand command = new NpgsqlCommand(sql, conn)) using (SqlCommand command = new SqlCommand(sql, conn))
{ {
if (user == UUID.Zero) if (user == UUID.Zero)
{ {
@ -721,9 +721,9 @@ namespace OpenSim.Data.PGSQL
/// </summary> /// </summary>
/// <param name="command">SQLcommand.</param> /// <param name="command">SQLcommand.</param>
/// <returns></returns> /// <returns></returns>
private static List<InventoryFolderBase> getInventoryFolders(NpgsqlCommand command) private static List<InventoryFolderBase> getInventoryFolders(SqlCommand command)
{ {
using (NpgsqlDataReader reader = command.ExecuteReader()) using (SqlDataReader reader = command.ExecuteReader())
{ {
List<InventoryFolderBase> items = new List<InventoryFolderBase>(); List<InventoryFolderBase> items = new List<InventoryFolderBase>();
@ -738,9 +738,9 @@ namespace OpenSim.Data.PGSQL
/// <summary> /// <summary>
/// Reads a list of inventory folders returned by a query. /// Reads a list of inventory folders returned by a query.
/// </summary> /// </summary>
/// <param name="reader">A PGSQL Data Reader</param> /// <param name="reader">A MSSQL Data Reader</param>
/// <returns>A List containing inventory folders</returns> /// <returns>A List containing inventory folders</returns>
protected static InventoryFolderBase readInventoryFolder(NpgsqlDataReader reader) protected static InventoryFolderBase readInventoryFolder(SqlDataReader reader)
{ {
try try
{ {
@ -796,7 +796,7 @@ namespace OpenSim.Data.PGSQL
return item; return item;
} }
catch (NpgsqlException e) catch (SqlException e)
{ {
m_log.Error("[INVENTORY DB]: Error reading inventory item :" + e.Message); m_log.Error("[INVENTORY DB]: Error reading inventory item :" + e.Message);
} }
@ -809,18 +809,18 @@ namespace OpenSim.Data.PGSQL
/// </summary> /// </summary>
/// <param name="folderID">the folder UUID</param> /// <param name="folderID">the folder UUID</param>
/// <param name="connection">connection to database</param> /// <param name="connection">connection to database</param>
private void DeleteOneFolder(UUID folderID, NpgsqlConnection connection) private void DeleteOneFolder(UUID folderID, SqlConnection connection)
{ {
try try
{ {
using (NpgsqlCommand command = new NpgsqlCommand(@"DELETE FROM inventoryfolders WHERE ""folderID""=:folderID and type=-1", connection)) using (SqlCommand command = new SqlCommand("DELETE FROM inventoryfolders WHERE folderID=@folderID and type=-1", connection))
{ {
command.Parameters.Add(database.CreateParameter("folderID", folderID)); command.Parameters.Add(database.CreateParameter("folderID", folderID));
command.ExecuteNonQuery(); command.ExecuteNonQuery();
} }
} }
catch (NpgsqlException e) catch (SqlException e)
{ {
m_log.Error("[INVENTORY DB]: Error deleting folder :" + e.Message); m_log.Error("[INVENTORY DB]: Error deleting folder :" + e.Message);
} }

View File

@ -28,20 +28,18 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Data; using System.Data;
using System.Data.SqlClient;
using System.IO; using System.IO;
using System.Reflection; using System.Reflection;
using OpenSim.Framework;
using log4net; using log4net;
using OpenMetaverse; using OpenMetaverse;
using Npgsql;
using NpgsqlTypes;
namespace OpenSim.Data.PGSQL namespace OpenSim.Data.MSSQL
{ {
/// <summary> /// <summary>
/// A management class for the MS SQL Storage Engine /// A management class for the MS SQL Storage Engine
/// </summary> /// </summary>
public class PGSQLManager public class MSSQLManager
{ {
// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); // private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
@ -54,37 +52,9 @@ namespace OpenSim.Data.PGSQL
/// Initialize the manager and set the connectionstring /// Initialize the manager and set the connectionstring
/// </summary> /// </summary>
/// <param name="connection"></param> /// <param name="connection"></param>
public PGSQLManager(string connection) public MSSQLManager(string connection)
{ {
connectionString = connection; connectionString = connection;
InitializeMonoSecurity();
}
public void InitializeMonoSecurity()
{
if (!Util.IsPlatformMono)
{
if (AppDomain.CurrentDomain.GetData("MonoSecurityPostgresAdded") == null)
{
AppDomain.CurrentDomain.SetData("MonoSecurityPostgresAdded", "true");
AppDomain currentDomain = AppDomain.CurrentDomain;
currentDomain.AssemblyResolve += new ResolveEventHandler(ResolveEventHandlerMonoSec);
}
}
}
private System.Reflection.Assembly ResolveEventHandlerMonoSec(object sender, ResolveEventArgs args)
{
Assembly MyAssembly = null;
if (args.Name.Substring(0, args.Name.IndexOf(",")) == "Mono.Security")
{
MyAssembly = Assembly.LoadFrom("lib/NET/Mono.Security.dll");
}
//Return the loaded assembly.
return MyAssembly;
} }
/// <summary> /// <summary>
@ -92,97 +62,54 @@ namespace OpenSim.Data.PGSQL
/// </summary> /// </summary>
/// <param name="type"></param> /// <param name="type"></param>
/// <returns></returns> /// <returns></returns>
internal NpgsqlDbType DbtypeFromType(Type type) internal SqlDbType DbtypeFromType(Type type)
{ {
if (type == typeof(string)) if (type == typeof(string))
{ {
return NpgsqlDbType.Varchar; return SqlDbType.VarChar;
} }
if (type == typeof(double)) if (type == typeof(double))
{ {
return NpgsqlDbType.Double; return SqlDbType.Float;
} }
if (type == typeof(Single)) if (type == typeof(Single))
{ {
return NpgsqlDbType.Double; return SqlDbType.Float;
} }
if (type == typeof(int)) if (type == typeof(int))
{ {
return NpgsqlDbType.Integer; return SqlDbType.Int;
} }
if (type == typeof(bool)) if (type == typeof(bool))
{ {
return NpgsqlDbType.Boolean; return SqlDbType.Bit;
} }
if (type == typeof(UUID)) if (type == typeof(UUID))
{ {
return NpgsqlDbType.Uuid; return SqlDbType.UniqueIdentifier;
}
if (type == typeof(byte))
{
return NpgsqlDbType.Smallint;
} }
if (type == typeof(sbyte)) if (type == typeof(sbyte))
{ {
return NpgsqlDbType.Integer; return SqlDbType.Int;
} }
if (type == typeof(Byte[])) if (type == typeof(Byte[]))
{ {
return NpgsqlDbType.Bytea; return SqlDbType.Image;
} }
if (type == typeof(uint) || type == typeof(ushort)) if (type == typeof(uint) || type == typeof(ushort))
{ {
return NpgsqlDbType.Integer; return SqlDbType.Int;
} }
if (type == typeof(ulong)) if (type == typeof(ulong))
{ {
return NpgsqlDbType.Bigint; return SqlDbType.BigInt;
} }
if (type == typeof(DateTime)) if (type == typeof(DateTime))
{ {
return NpgsqlDbType.Timestamp; return SqlDbType.DateTime;
} }
return NpgsqlDbType.Varchar; return SqlDbType.VarChar;
}
internal NpgsqlDbType DbtypeFromString(Type type, string PGFieldType)
{
if (PGFieldType == "")
{
return DbtypeFromType(type);
}
if (PGFieldType == "character varying")
{
return NpgsqlDbType.Varchar;
}
if (PGFieldType == "double precision")
{
return NpgsqlDbType.Double;
}
if (PGFieldType == "integer")
{
return NpgsqlDbType.Integer;
}
if (PGFieldType == "smallint")
{
return NpgsqlDbType.Smallint;
}
if (PGFieldType == "boolean")
{
return NpgsqlDbType.Boolean;
}
if (PGFieldType == "uuid")
{
return NpgsqlDbType.Uuid;
}
if (PGFieldType == "bytea")
{
return NpgsqlDbType.Bytea;
}
return DbtypeFromType(type);
} }
/// <summary> /// <summary>
@ -204,7 +131,7 @@ namespace OpenSim.Data.PGSQL
} }
if (valueType == typeof(bool)) if (valueType == typeof(bool))
{ {
return (bool)value; return (bool)value ? 1 : 0;
} }
if (valueType == typeof(Byte[])) if (valueType == typeof(Byte[]))
{ {
@ -217,52 +144,13 @@ namespace OpenSim.Data.PGSQL
return value; return value;
} }
/// <summary>
/// Create value for parameter based on PGSQL Schema
/// </summary>
/// <param name="value"></param>
/// <param name="PGFieldType"></param>
/// <returns></returns>
internal static object CreateParameterValue(object value, string PGFieldType)
{
if (PGFieldType == "uuid")
{
UUID uidout;
UUID.TryParse(value.ToString(), out uidout);
return uidout;
}
if (PGFieldType == "integer")
{
int intout;
int.TryParse(value.ToString(), out intout);
return intout;
}
if (PGFieldType == "boolean")
{
return (value.ToString() == "true");
}
if (PGFieldType == "timestamp with time zone")
{
return (DateTime)value;
}
if (PGFieldType == "timestamp without time zone")
{
return (DateTime)value;
}
if (PGFieldType == "double precision")
{
return Convert.ToDouble(value);
}
return CreateParameterValue(value);
}
/// <summary> /// <summary>
/// Create a parameter for a command /// Create a parameter for a command
/// </summary> /// </summary>
/// <param name="parameterName">Name of the parameter.</param> /// <param name="parameterName">Name of the parameter.</param>
/// <param name="parameterObject">parameter object.</param> /// <param name="parameterObject">parameter object.</param>
/// <returns></returns> /// <returns></returns>
internal NpgsqlParameter CreateParameter(string parameterName, object parameterObject) internal SqlParameter CreateParameter(string parameterName, object parameterObject)
{ {
return CreateParameter(parameterName, parameterObject, false); return CreateParameter(parameterName, parameterObject, false);
} }
@ -274,15 +162,15 @@ namespace OpenSim.Data.PGSQL
/// <param name="parameterObject">parameter object.</param> /// <param name="parameterObject">parameter object.</param>
/// <param name="parameterOut">if set to <c>true</c> parameter is a output parameter</param> /// <param name="parameterOut">if set to <c>true</c> parameter is a output parameter</param>
/// <returns></returns> /// <returns></returns>
internal NpgsqlParameter CreateParameter(string parameterName, object parameterObject, bool parameterOut) internal SqlParameter CreateParameter(string parameterName, object parameterObject, bool parameterOut)
{ {
//Tweak so we dont always have to add : sign //Tweak so we dont always have to add @ sign
if (parameterName.StartsWith(":")) parameterName = parameterName.Replace(":",""); if (!parameterName.StartsWith("@")) parameterName = "@" + parameterName;
//HACK if object is null, it is turned into a string, there are no nullable type till now //HACK if object is null, it is turned into a string, there are no nullable type till now
if (parameterObject == null) parameterObject = ""; if (parameterObject == null) parameterObject = "";
NpgsqlParameter parameter = new NpgsqlParameter(parameterName, DbtypeFromType(parameterObject.GetType())); SqlParameter parameter = new SqlParameter(parameterName, DbtypeFromType(parameterObject.GetType()));
if (parameterOut) if (parameterOut)
{ {
@ -297,40 +185,17 @@ namespace OpenSim.Data.PGSQL
return parameter; return parameter;
} }
/// <summary>
/// Create a parameter with PGSQL schema type
/// </summary>
/// <param name="parameterName"></param>
/// <param name="parameterObject"></param>
/// <param name="PGFieldType"></param>
/// <returns></returns>
internal NpgsqlParameter CreateParameter(string parameterName, object parameterObject, string PGFieldType)
{
//Tweak so we dont always have to add : sign
if (parameterName.StartsWith(":")) parameterName = parameterName.Replace(":", "");
//HACK if object is null, it is turned into a string, there are no nullable type till now
if (parameterObject == null) parameterObject = "";
NpgsqlParameter parameter = new NpgsqlParameter(parameterName, DbtypeFromString(parameterObject.GetType(), PGFieldType));
parameter.Direction = ParameterDirection.Input;
parameter.Value = CreateParameterValue(parameterObject, PGFieldType);
return parameter;
}
/// <summary> /// <summary>
/// Checks if we need to do some migrations to the database /// Checks if we need to do some migrations to the database
/// </summary> /// </summary>
/// <param name="migrationStore">migrationStore.</param> /// <param name="migrationStore">migrationStore.</param>
public void CheckMigration(string migrationStore) public void CheckMigration(string migrationStore)
{ {
using (NpgsqlConnection connection = new NpgsqlConnection(connectionString)) using (SqlConnection connection = new SqlConnection(connectionString))
{ {
connection.Open(); connection.Open();
Assembly assem = GetType().Assembly; Assembly assem = GetType().Assembly;
PGSQLMigration migration = new PGSQLMigration(connection, assem, migrationStore); MSSQLMigration migration = new MSSQLMigration(connection, assem, migrationStore);
migration.Update(); migration.Update();
} }

View File

@ -25,22 +25,22 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
using Npgsql;
using System; using System;
using System.Data; using System.Data;
using System.Data.Common; using System.Data.Common;
using System.Reflection; using System.Reflection;
using System.Data.SqlClient;
namespace OpenSim.Data.PGSQL namespace OpenSim.Data.MSSQL
{ {
public class PGSQLMigration : Migration public class MSSQLMigration : Migration
{ {
public PGSQLMigration(NpgsqlConnection conn, Assembly assem, string type) public MSSQLMigration(DbConnection conn, Assembly assem, string type)
: base(conn, assem, type) : base(conn, assem, type)
{ {
} }
public PGSQLMigration(NpgsqlConnection conn, Assembly assem, string subtype, string type) public MSSQLMigration(DbConnection conn, Assembly assem, string subtype, string type)
: base(conn, assem, subtype, type) : base(conn, assem, subtype, type)
{ {
} }
@ -48,15 +48,12 @@ namespace OpenSim.Data.PGSQL
protected override int FindVersion(DbConnection conn, string type) protected override int FindVersion(DbConnection conn, string type)
{ {
int version = 0; int version = 0;
NpgsqlConnection lcConn = (NpgsqlConnection)conn; using (DbCommand cmd = conn.CreateCommand())
using (NpgsqlCommand cmd = lcConn.CreateCommand())
{ {
try try
{ {
cmd.CommandText = "select version from migrations where name = '" + type + "' " + cmd.CommandText = "select top 1 version from migrations where name = '" + type + "' order by version desc"; //Must be
" order by version desc limit 1"; //Must be using (IDataReader reader = cmd.ExecuteReader())
using (NpgsqlDataReader reader = cmd.ExecuteReader())
{ {
if (reader.Read()) if (reader.Read())
{ {
@ -76,7 +73,7 @@ namespace OpenSim.Data.PGSQL
protected override void ExecuteScript(DbConnection conn, string[] script) protected override void ExecuteScript(DbConnection conn, string[] script)
{ {
if (!(conn is NpgsqlConnection)) if (!(conn is SqlConnection))
{ {
base.ExecuteScript(conn, script); base.ExecuteScript(conn, script);
return; return;
@ -86,7 +83,7 @@ namespace OpenSim.Data.PGSQL
{ {
try try
{ {
using (NpgsqlCommand cmd = new NpgsqlCommand(sql, (NpgsqlConnection)conn)) using (SqlCommand cmd = new SqlCommand(sql, (SqlConnection)conn))
{ {
cmd.ExecuteNonQuery(); cmd.ExecuteNonQuery();
} }

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