Compare commits
No commits in common. "0.6b-realxtend" and "master" have entirely different histories.
0.6b-realx
...
master
|
@ -0,0 +1,116 @@
|
||||||
|
.project
|
||||||
|
.settings
|
||||||
|
.gitignore
|
||||||
|
*.csproj
|
||||||
|
*.csproj.user
|
||||||
|
*.build
|
||||||
|
*.mdb
|
||||||
|
*.mdp
|
||||||
|
*.mds
|
||||||
|
*.pdb
|
||||||
|
*.pidb
|
||||||
|
*.dll.build
|
||||||
|
*.dll
|
||||||
|
*.log
|
||||||
|
|
||||||
|
# Ignore .user and .suo files as these are user preference specific
|
||||||
|
# http://stackoverflow.com/questions/72298/should-i-add-the-visual-studio-suo-and-user-files-to-source-control
|
||||||
|
*.suo
|
||||||
|
*.user
|
||||||
|
|
||||||
|
*.VisualState.xml
|
||||||
|
*/*/obj
|
||||||
|
*/*/*/obj
|
||||||
|
*/*/*/*/obj
|
||||||
|
*/*/*/*/*/obj
|
||||||
|
*/*/*/*/*/*/obj
|
||||||
|
*/*/*/*/*/*/*/obj
|
||||||
|
*/*/bin
|
||||||
|
*/*/*/bin
|
||||||
|
*/*/*/*/bin
|
||||||
|
*/*/*/*/*/bin
|
||||||
|
*/*/*/*/*/*/bin
|
||||||
|
*/*/*/*/*/*/*/bin
|
||||||
|
.vs/
|
||||||
|
addon-modules/
|
||||||
|
bin/Debug/*.dll
|
||||||
|
bin/*.dll.mdb
|
||||||
|
bin/*.db
|
||||||
|
bin/*.db-journal
|
||||||
|
bin/addin-db-*
|
||||||
|
bin/*.dll
|
||||||
|
bin/OpenSim.vshost.exe.config
|
||||||
|
bin/OpenSim.32BitLaunch.vshost.exe.config
|
||||||
|
bin/OpenSim.32BitLaunch.log
|
||||||
|
UpgradeLog.XML
|
||||||
|
_UpgradeReport_Files/
|
||||||
|
bin/ScriptEngines/*-*-*-*-*
|
||||||
|
bin/ScriptEngines/*.dll
|
||||||
|
bin/ScriptEngines/*/*.dll
|
||||||
|
bin/ScriptEngines/*/*.state
|
||||||
|
bin/*.maddin
|
||||||
|
bin/*.exe
|
||||||
|
bin/*.ini
|
||||||
|
bin/j2kDecodeCache
|
||||||
|
bin/Physics*
|
||||||
|
bin/Terrain*
|
||||||
|
bin/Regions/*
|
||||||
|
bin/UserAssets
|
||||||
|
bin/assetcache
|
||||||
|
bin/maptiles
|
||||||
|
bin/bakes
|
||||||
|
bin/estate_settings.xml
|
||||||
|
bin/config-include/CenomeCache.ini
|
||||||
|
bin/config-include/FlotsamCache.ini
|
||||||
|
bin/config-include/GridCommon.ini
|
||||||
|
bin/config-include/StandaloneCommon.ini
|
||||||
|
bin/OpenSim.Grid.AssetInventoryServer.log
|
||||||
|
bin/OpenSim.Grid.AssetServer.log
|
||||||
|
bin/OpenSim.Grid.GridServer.log
|
||||||
|
bin/OpenSim.Grid.InventoryServer.log
|
||||||
|
bin/OpenSim.Grid.MessagingServer.log
|
||||||
|
bin/OpenSim.Grid.UserServer.log
|
||||||
|
bin/OpenSim.log
|
||||||
|
bin/OpenSimStats.log
|
||||||
|
bin/Robust.log
|
||||||
|
bin/RobustStats.log
|
||||||
|
bin/OpenSimConsoleHistory.txt
|
||||||
|
bin/RobustConsoleHistory.txt
|
||||||
|
bin/*.Tests.log
|
||||||
|
bin/*.manifest
|
||||||
|
bin/crashes/
|
||||||
|
Examples/*.dll
|
||||||
|
OpenSim.build
|
||||||
|
OpenSim.sln
|
||||||
|
OpenSim.userprefs
|
||||||
|
Prebuild/Prebuild.build
|
||||||
|
Prebuild/Prebuild.sln
|
||||||
|
TestResult.xml
|
||||||
|
cov/*
|
||||||
|
OpenSim/OpenSim.userprefs
|
||||||
|
OpenSim/OpenSim.usertasks
|
||||||
|
TAGS
|
||||||
|
*~
|
||||||
|
Makefile.local
|
||||||
|
bin/.version
|
||||||
|
compile.bat
|
||||||
|
OpenSim/Data/Tests/test-results/
|
||||||
|
OpenSim/Framework/Serialization/Tests/test-results/
|
||||||
|
OpenSim/Framework/Servers/Tests/test-results/
|
||||||
|
OpenSim/Framework/Tests/test-results/
|
||||||
|
OpenSim/Region/ClientStack/Linden/Caps/test-results/
|
||||||
|
OpenSim/Region/ClientStack/Linden/UDP/Tests/test-results/
|
||||||
|
OpenSim/Region/CoreModules/test-results/
|
||||||
|
OpenSim/Region/Framework/test-results/
|
||||||
|
OpenSim/Region/OptionalModules/test-results/
|
||||||
|
OpenSim/Region/Physics/BulletDotNETPlugin/
|
||||||
|
OpenSim/Region/Physics/Manager/test-results/
|
||||||
|
OpenSim/Region/Physics/OdePlugin/Tests/test-results/
|
||||||
|
OpenSim/Region/ScriptEngine/test-results/
|
||||||
|
OpenSim/Tests/Common/test-results/
|
||||||
|
OpenSim/Tests/test-results/
|
||||||
|
test-results/
|
||||||
|
doc/html
|
||||||
|
doc/doxygen.error.log
|
||||||
|
|
||||||
|
*.patch
|
|
@ -0,0 +1,23 @@
|
||||||
|
^tailor.state.old$
|
||||||
|
^tailor.state.journal$
|
||||||
|
\.csproj$
|
||||||
|
\.csproj\.user$
|
||||||
|
\.mdp$
|
||||||
|
\.mds$
|
||||||
|
\.dll\.build$
|
||||||
|
^bin/Debug/.+\.dll$
|
||||||
|
^bin/.+\.db$
|
||||||
|
^bin/OpenSim\.ini$
|
||||||
|
^bin/OpenSim\.log$
|
||||||
|
^bin/estate_settings\.xml$
|
||||||
|
^bin/Regions
|
||||||
|
bin/.+\.dll.mdb$
|
||||||
|
bin/addin-db-
|
||||||
|
bin/.+\.dll$
|
||||||
|
bin/.+\.maddin$
|
||||||
|
Examples/.+\.dll$
|
||||||
|
^bin/.+\.exe
|
||||||
|
^(OpenSim|Prebuild)/.+\.(exe|exe\.build|exe\.mdb)$
|
||||||
|
^OpenSim\.(build|sln)$
|
||||||
|
^Prebuild/Prebuild\.(build|sln)$
|
||||||
|
.+~$
|
|
@ -0,0 +1,289 @@
|
||||||
|
<!-- -*- xml -*- -->
|
||||||
|
<!-- please leave the top comment for us emacs folks -->
|
||||||
|
<property name="nunitcmd" value="nunit-console" />
|
||||||
|
|
||||||
|
<!-- This target produces a source distribution of OpenSimulator -->
|
||||||
|
<!-- TODO: A few parameters still need to be tweaked after running this - need to do this automatically with sed or similar -->
|
||||||
|
<target name="distsrc">
|
||||||
|
<copy file="bin/OpenSim.ini.example" tofile="bin/OpenSim.ini"/>
|
||||||
|
<copy file="bin/config-include/StandaloneCommon.ini.example" tofile="bin/config-include/StandaloneCommon.ini"/>
|
||||||
|
<copy file="bin/config-include/FlotsamCache.ini.example" tofile="bin/config-include/FlotsamCache.ini"/>
|
||||||
|
<!-- delete files generated by runprebuild.sh which had to be run in order to generate the build file for this target-->
|
||||||
|
<delete>
|
||||||
|
<fileset basedir="OpenSim">
|
||||||
|
<include name="**/*.build"/>
|
||||||
|
<include name="**/*.csproj*"/>
|
||||||
|
<include name="**/*.dll.build"/>
|
||||||
|
<include name="**/*.pidb"/>
|
||||||
|
<exclude name="Tools/OpenSim.32BitLaunch/**"/>
|
||||||
|
<exclude name="Tools/Robust.32BitLaunch/**"/>
|
||||||
|
<exclude name="Tools/LaunchSLClient/**"/>
|
||||||
|
</fileset>
|
||||||
|
</delete>
|
||||||
|
<delete>
|
||||||
|
<fileset>
|
||||||
|
<include name="OpenSim.build"/>
|
||||||
|
<include name="OpenSim.sln"/>
|
||||||
|
</fileset>
|
||||||
|
</delete>
|
||||||
|
</target>
|
||||||
|
|
||||||
|
<property name="distbindir" value="distbin" />
|
||||||
|
<!-- This target produces a binary directory called distbin/ in OpenSim/bin which contains everything needed for binary distribution -->
|
||||||
|
<!-- For safety/laziness sake, we're going to take the approach of deleting known extraneous files here rather than
|
||||||
|
trying to copy across only the essential ones -->
|
||||||
|
<target name="distbin">
|
||||||
|
<delete dir="${distbindir}"/>
|
||||||
|
<copy todir="${distbindir}">
|
||||||
|
<fileset>
|
||||||
|
<include name="**"/>
|
||||||
|
</fileset>
|
||||||
|
</copy>
|
||||||
|
<delete dir="${distbindir}/OpenSim"/>
|
||||||
|
<delete dir="${distbindir}/Prebuild"/>
|
||||||
|
<delete dir="${distbindir}/%temp%"/>
|
||||||
|
<delete dir="${distbindir}/.nant"/>
|
||||||
|
<delete dir="${distbindir}/ThirdParty"/>
|
||||||
|
<delete>
|
||||||
|
<fileset basedir="${distbindir}">
|
||||||
|
<include name="compile.bat"/>
|
||||||
|
<include name="BUILDING.md"/>
|
||||||
|
<include name="Makefile"/>
|
||||||
|
<include name="nant-color"/>
|
||||||
|
<include name="OpenSim.*"/>
|
||||||
|
<include name="prebuild.xml"/>
|
||||||
|
<include name="runprebuild*"/>
|
||||||
|
<include name="TESTING.txt"/>
|
||||||
|
<include name="TestResult.xml"/>
|
||||||
|
<include name="bin/OpenSim.Server.ini"/>
|
||||||
|
<include name="bin/Regions/Regions.ini"/>
|
||||||
|
<include name="bin/*.db"/>
|
||||||
|
<include name="**/.git/**"/>
|
||||||
|
<include name=".gitignore"/>
|
||||||
|
<include name=".hgignore"/>
|
||||||
|
</fileset>
|
||||||
|
</delete>
|
||||||
|
</target>
|
||||||
|
|
||||||
|
<target name="test" depends="build, find-nunit">
|
||||||
|
<setenv name="MONO_THREADS_PER_CPU" value="100" />
|
||||||
|
|
||||||
|
<!-- Unit Test Assembly -->
|
||||||
|
<!-- if you want to add more unit tests it's important that you add
|
||||||
|
the assembly here as an exec, and you add the fail clause later.
|
||||||
|
This lets all the unit tests run and tells you if they fail at the
|
||||||
|
end, instead of stopping short -->
|
||||||
|
<exec program="${nunitcmd}" failonerror="true" resultproperty="testresult.opensim.tests">
|
||||||
|
<arg value="./bin/OpenSim.Tests.dll" />
|
||||||
|
</exec>
|
||||||
|
<fail message="Failures reported in unit tests." unless="${int::parse(testresult.opensim.tests)==0}" />
|
||||||
|
|
||||||
|
<exec program="${nunitcmd}" failonerror="true" resultproperty="testresult.opensim.framework.tests">
|
||||||
|
<arg value="./bin/OpenSim.Framework.Tests.dll" />
|
||||||
|
</exec>
|
||||||
|
<fail message="Failures reported in unit tests." unless="${int::parse(testresult.opensim.framework.tests)==0}" />
|
||||||
|
|
||||||
|
<exec program="${nunitcmd}" failonerror="true" resultproperty="testresult.opensim.framework.servers.tests">
|
||||||
|
<arg value="./bin/OpenSim.Framework.Servers.Tests.dll" />
|
||||||
|
</exec>
|
||||||
|
<fail message="Failures reported in unit tests." unless="${int::parse(testresult.opensim.framework.servers.tests)==0}" />
|
||||||
|
|
||||||
|
<exec program="${nunitcmd}" failonerror="true" resultproperty="testresult.opensim.framework.serialization.tests">
|
||||||
|
<arg value="./bin/OpenSim.Framework.Serialization.Tests.dll" />
|
||||||
|
</exec>
|
||||||
|
<fail message="Failures reported in unit tests." unless="${int::parse(testresult.opensim.framework.serialization.tests)==0}" />
|
||||||
|
|
||||||
|
<exec program="${nunitcmd}" failonerror="true" resultproperty="testresult.opensim.region.clientstack.lindencaps.tests">
|
||||||
|
<arg value="./bin/OpenSim.Region.ClientStack.LindenCaps.Tests.dll" />
|
||||||
|
</exec>
|
||||||
|
<fail message="Failures reported in unit tests." unless="${int::parse(testresult.opensim.region.clientstack.lindencaps.tests)==0}" />
|
||||||
|
|
||||||
|
<exec program="${nunitcmd}" failonerror="true" resultproperty="testresult.opensim.region.clientstack.lindenudp.tests">
|
||||||
|
<arg value="./bin/OpenSim.Region.ClientStack.LindenUDP.Tests.dll" />
|
||||||
|
</exec>
|
||||||
|
<fail message="Failures reported in unit tests." unless="${int::parse(testresult.opensim.region.clientstack.lindenudp.tests)==0}" />
|
||||||
|
|
||||||
|
<exec program="${nunitcmd}" failonerror="true" resultproperty="testresult.opensim.region.scriptengine.tests">
|
||||||
|
<arg value="./bin/OpenSim.Region.ScriptEngine.Tests.dll" />
|
||||||
|
</exec>
|
||||||
|
<fail message="Failures reported in unit tests." unless="${int::parse(testresult.opensim.region.scriptengine.tests)==0}" />
|
||||||
|
|
||||||
|
<exec program="${nunitcmd}" failonerror="true" resultproperty="testresult.opensim.region.coremodules.tests">
|
||||||
|
<arg value="./bin/OpenSim.Region.CoreModules.Tests.dll" />
|
||||||
|
</exec>
|
||||||
|
<fail message="Failures reported in unit tests." unless="${int::parse(testresult.opensim.region.coremodules.tests)==0}" />
|
||||||
|
|
||||||
|
<!--
|
||||||
|
<exec program="${nunitcmd}" failonerror="true" resultproperty="testresult.opensim.region.optionalmodules.tests">
|
||||||
|
<arg value="./bin/OpenSim.Region.OptionalModules.Tests.dll" />
|
||||||
|
</exec>
|
||||||
|
<fail message="Failures reported in unit tests." unless="${int::parse(testresult.opensim.region.optionalmodules.tests)==0}" />
|
||||||
|
-->
|
||||||
|
|
||||||
|
<exec program="${nunitcmd}" failonerror="true" resultproperty="testresult.opensim.region.framework.tests">
|
||||||
|
<arg value="./bin/OpenSim.Region.Framework.Tests.dll" />
|
||||||
|
</exec>
|
||||||
|
<fail message="Failures reported in unit tests." unless="${int::parse(testresult.opensim.region.framework.tests)==0}" />
|
||||||
|
|
||||||
|
<exec program="${nunitcmd}" failonerror="true" resultproperty="testresult.opensim.data.tests">
|
||||||
|
<arg value="./bin/OpenSim.Data.Tests.dll" />
|
||||||
|
</exec>
|
||||||
|
<fail message="Failures reported in unit tests." unless="${int::parse(testresult.opensim.data.tests)==0}" />
|
||||||
|
|
||||||
|
<exec program="${nunitcmd}" failonerror="true" resultproperty="testresult.opensim.capabilities.handlers.tests">
|
||||||
|
<arg value="./bin/OpenSim.Capabilities.Handlers.Tests.dll" />
|
||||||
|
</exec>
|
||||||
|
<fail message="Failures reported in unit tests." unless="${int::parse(testresult.opensim.capabilities.handlers.tests)==0}" />
|
||||||
|
|
||||||
|
<exec program="${nunitcmd}" failonerror="true" resultproperty="testresult.opensim.server.handlers.tests">
|
||||||
|
<arg value="./bin/OpenSim.Server.Handlers.Tests.dll" />
|
||||||
|
</exec>
|
||||||
|
<fail message="Failures reported in unit tests." unless="${int::parse(testresult.opensim.server.handlers.tests)==0}" />
|
||||||
|
|
||||||
|
<exec program="${nunitcmd}" failonerror="true" resultproperty="testresult.opensim.services.inventoryservice.tests">
|
||||||
|
<arg value="./bin/OpenSim.Services.InventoryService.Tests.dll" />
|
||||||
|
</exec>
|
||||||
|
<fail message="Failures reported in unit tests." unless="${int::parse(testresult.opensim.services.inventoryservice.tests)==0}" />
|
||||||
|
|
||||||
|
<exec program="${nunitcmd}" failonerror="true" resultproperty="testresult.opensim.tests.permissions">
|
||||||
|
<arg value="./bin/OpenSim.Tests.Permissions.dll" />
|
||||||
|
</exec>
|
||||||
|
<fail message="Failures reported in unit tests." unless="${int::parse(testresult.opensim.tests.permissions)==0}" />
|
||||||
|
|
||||||
|
<delete dir="%temp%"/>
|
||||||
|
</target>
|
||||||
|
|
||||||
|
<target name="test-stress" depends="build, find-nunit">
|
||||||
|
<setenv name="MONO_THREADS_PER_CPU" value="100" />
|
||||||
|
|
||||||
|
<exec program="${nunitcmd}" failonerror="true" resultproperty="testresult.opensim.tests.stress">
|
||||||
|
<arg value="./bin/OpenSim.Tests.Stress.dll" />
|
||||||
|
</exec>
|
||||||
|
|
||||||
|
<fail message="Failures reported in stress tests." unless="${int::parse(testresult.opensim.tests.stress)==0}" />
|
||||||
|
<delete dir="%temp%"/>
|
||||||
|
</target>
|
||||||
|
|
||||||
|
<target name="test-perf" depends="build, find-nunit">
|
||||||
|
<setenv name="MONO_THREADS_PER_CPU" value="100" />
|
||||||
|
|
||||||
|
<exec program="${nunitcmd}" failonerror="true" resultproperty="testresult.opensim.tests.performance">
|
||||||
|
<arg value="./bin/OpenSim.Tests.Performance.dll" />
|
||||||
|
</exec>
|
||||||
|
|
||||||
|
<fail message="Failures reported in performance tests." unless="${int::parse(testresult.opensim.tests.performance)==0}" />
|
||||||
|
<delete dir="%temp%"/>
|
||||||
|
</target>
|
||||||
|
|
||||||
|
<target name="find-nunit">
|
||||||
|
<exec program="which" failonerror="false"
|
||||||
|
resultproperty="hasnunit2">
|
||||||
|
<arg value="nunit-console2" />
|
||||||
|
</exec>
|
||||||
|
|
||||||
|
<property name="nunitcmd" value="nunit-console2"
|
||||||
|
if="${int::parse(hasnunit2)==0}" />
|
||||||
|
<property name="nunitcmd" value="nunit-console"
|
||||||
|
if="${int::parse(hasnunit2)==1}" />
|
||||||
|
</target>
|
||||||
|
|
||||||
|
<!-- this is used for panda test execution -->
|
||||||
|
<!-- work in progress -->
|
||||||
|
|
||||||
|
<target name="test-xml" depends="build, find-nunit">
|
||||||
|
<mkdir dir="test-results" failonerror="false" />
|
||||||
|
<!-- Unit Test Assembly -->
|
||||||
|
<exec program="${nunitcmd}" failonerror="false" resultproperty="testresult.opensim.tests">
|
||||||
|
<arg value="./bin/OpenSim.Tests.dll" />
|
||||||
|
<arg value="-xml=test-results/OpenSim.Tests.dll-Results.xml" />
|
||||||
|
</exec>
|
||||||
|
|
||||||
|
<exec program="${nunitcmd}" failonerror="false" resultproperty="testresult.opensim.framework.tests">
|
||||||
|
<arg value="./bin/OpenSim.Framework.Tests.dll" />
|
||||||
|
<arg value="-xml=test-results/OpenSim.Framework.Tests.dll-Results.xml" />
|
||||||
|
</exec>
|
||||||
|
|
||||||
|
<exec program="${nunitcmd}" failonerror="false" resultproperty="testresult.opensim.framework.serialization.tests">
|
||||||
|
<arg value="./bin/OpenSim.Framework.Serialization.Tests.dll" />
|
||||||
|
<arg value="-xml=test-results/OpenSim.Framework.Serialization.Tests.dll-Results.xml" />
|
||||||
|
</exec>
|
||||||
|
|
||||||
|
<exec program="${nunitcmd}" failonerror="false" resultproperty="testresult.opensim.framework.servers.tests">
|
||||||
|
<arg value="./bin/OpenSim.Framework.Servers.Tests.dll" />
|
||||||
|
<arg value="-xml=test-results/OpenSim.Framework.Servers.Tests.dll-Results.xml" />
|
||||||
|
</exec>
|
||||||
|
|
||||||
|
<exec program="${nunitcmd}" failonerror="false" resultproperty="testresult.opensim.region.clientstack.lindencaps.tests">
|
||||||
|
<arg value="./bin/OpenSim.Region.ClientStack.LindenCaps.Tests.dll" />
|
||||||
|
<arg value="-xml=test-results/OpenSim.Region.ClientStack.LindenCaps.Tests.dll-Results.xml" />
|
||||||
|
</exec>
|
||||||
|
|
||||||
|
<exec program="${nunitcmd}" failonerror="false" resultproperty="testresult.opensim.region.clientstack.lindenudp.tests">
|
||||||
|
<arg value="./bin/OpenSim.Region.ClientStack.LindenUDP.Tests.dll" />
|
||||||
|
<arg value="-xml=test-results/OpenSim.Region.ClientStack.LindenUDP.Tests.dll-Results.xml" />
|
||||||
|
</exec>
|
||||||
|
|
||||||
|
<exec program="${nunitcmd}" failonerror="false" resultproperty="testresult.opensim.region.scriptengine.tests">
|
||||||
|
<arg value="./bin/OpenSim.Region.ScriptEngine.Tests.dll" />
|
||||||
|
<arg value="-xml=test-results/OpenSim.Region.ScriptEngine.Tests.dll-Results.xml" />
|
||||||
|
</exec>
|
||||||
|
|
||||||
|
<exec program="${nunitcmd}" failonerror="false" resultproperty="testresult.opensim.region.coremodules.tests">
|
||||||
|
<arg value="./bin/OpenSim.Region.CoreModules.Tests.dll" />
|
||||||
|
<arg value="-xml=test-results/OpenSim.Region.CoreModules.Tests.dll-Results.xml" />
|
||||||
|
</exec>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
<exec program="${nunitcmd}" failonerror="false" resultproperty="testresult.opensim.region.optionalmodules.tests">
|
||||||
|
<arg value="./bin/OpenSim.Region.OptionalModules.Tests.dll" />
|
||||||
|
<arg value="-xml=test-results/OpenSim.Region.OptionalModules.Tests.dll-Results.xml" />
|
||||||
|
</exec>
|
||||||
|
-->
|
||||||
|
|
||||||
|
<exec program="${nunitcmd}" failonerror="false" resultproperty="testresult.opensim.region.framework.tests">
|
||||||
|
<arg value="./bin/OpenSim.Region.Framework.Tests.dll" />
|
||||||
|
<arg value="-xml=test-results/OpenSim.Region.Framework.Tests.dll-Results.xml" />
|
||||||
|
</exec>
|
||||||
|
|
||||||
|
<exec program="${nunitcmd}" failonerror="false" resultproperty="testresult.opensim.data.tests">
|
||||||
|
<arg value="./bin/OpenSim.Data.Tests.dll" />
|
||||||
|
<arg value="-xml=test-results/OpenSim.Data.Tests.dll-Results.xml" />
|
||||||
|
</exec>
|
||||||
|
|
||||||
|
<exec program="${nunitcmd}" failonerror="false" resultproperty="testresult.opensim.capabilities.handlers.tests">
|
||||||
|
<arg value="./bin/OpenSim.Capabilities.Handlers.Tests.dll" />
|
||||||
|
<arg value="-xml=test-results/OpenSim.Capabilities.Handlers.Tests.dll-Results.xml" />
|
||||||
|
</exec>
|
||||||
|
|
||||||
|
<exec program="${nunitcmd}" failonerror="false" resultproperty="testresult.opensim.server.handlers.tests">
|
||||||
|
<arg value="./bin/OpenSim.Server.Handlers.Tests.dll" />
|
||||||
|
<arg value="-xml=test-results/OpenSim.Server.Handlers.Tests.dll-Results.xml" />
|
||||||
|
</exec>
|
||||||
|
|
||||||
|
<exec program="${nunitcmd}" failonerror="false" resultproperty="testresult.opensim.services.inventoryservice.tests">
|
||||||
|
<arg value="./bin/OpenSim.Services.InventoryService.Tests.dll" />
|
||||||
|
<arg value="-xml=test-results/OpenSim.Services.InventoryService.Tests.dll-Results.xml" />
|
||||||
|
</exec>
|
||||||
|
|
||||||
|
<exec program="${nunitcmd}" failonerror="false" resultproperty="testresult.opensim.tests.permissions">
|
||||||
|
<arg value="./bin/OpenSim.Tests.Permissions.dll" />
|
||||||
|
<arg value="-xml=test-results/OpenSim.Tests.Permissions.dll-Results.xml" />
|
||||||
|
</exec>
|
||||||
|
|
||||||
|
<fail message="Failures reported in unit tests." unless="${int::parse(testresult.opensim.tests)==0}" />
|
||||||
|
<fail message="Failures reported in unit tests." unless="${int::parse(testresult.opensim.framework.tests)==0}" />
|
||||||
|
<fail message="Failures reported in unit tests." unless="${int::parse(testresult.opensim.framework.servers.tests)==0}" />
|
||||||
|
<fail message="Failures reported in unit tests." unless="${int::parse(testresult.opensim.region.clientstack.lindenudp.tests)==0}" />
|
||||||
|
<fail message="Failures reported in unit tests." unless="${int::parse(testresult.opensim.region.scriptengine.tests)==0}" />
|
||||||
|
<fail message="Failures reported in unit tests." unless="${int::parse(testresult.opensim.region.coremodules.tests)==0}" />
|
||||||
|
<!-- <fail message="Failures reported in unit tests." unless="${int::parse(testresult.opensim.region.optionalmodules.tests)==0}" /> -->
|
||||||
|
<fail message="Failures reported in unit tests." unless="${int::parse(testresult.opensim.region.framework.tests)==0}" />
|
||||||
|
<fail message="Failures reported in unit tests." unless="${int::parse(testresult.opensim.data.tests)==0}" />
|
||||||
|
<fail message="Failures reported in unit tests." unless="${int::parse(testresult.opensim.capabilities.handlers.tests)==0}" />
|
||||||
|
<fail message="Failures reported in unit tests." unless="${int::parse(testresult.opensim.services.inventoryservice.tests)==0}" />
|
||||||
|
<fail message="Failures reported in unit tests." unless="${int::parse(testresult.opensim.tests.permissions)==0}" />
|
||||||
|
</target>
|
||||||
|
|
||||||
|
<target name="doxygen">
|
||||||
|
<exec program="doxygen" workingdir="doc" commandline="doxygen.conf" />
|
||||||
|
</target>
|
|
@ -0,0 +1,37 @@
|
||||||
|
# Building on Windows
|
||||||
|
|
||||||
|
Steps:
|
||||||
|
|
||||||
|
* runprebuild.bat
|
||||||
|
* Load OpenSim.sln into Visual Studio .NET and build the solution.
|
||||||
|
* chdir bin
|
||||||
|
* copy OpenSim.ini.example to OpenSim.ini and other appropriate files in bin/config-include
|
||||||
|
* run OpenSim.exe
|
||||||
|
|
||||||
|
# Building on Linux / Mac
|
||||||
|
|
||||||
|
Prereqs:
|
||||||
|
|
||||||
|
* Mono > 5.0
|
||||||
|
* On some Linux distributions you may need to install additional packages.
|
||||||
|
* msbuild or xbuild if still supported by the mono version
|
||||||
|
* See http://opensimulator.org/wiki/Dependencies for more information.
|
||||||
|
|
||||||
|
From the distribution type:
|
||||||
|
|
||||||
|
* ./runprebuild.sh
|
||||||
|
* type msbuild or xbuild
|
||||||
|
* cd bin
|
||||||
|
* copy OpenSim.ini.example to OpenSim.ini and other appropriate files in bin/config-include
|
||||||
|
* review and change those ini files according to your needs
|
||||||
|
* windows: execute opensim.exe or opensim32.exe for small regions
|
||||||
|
* linux: run ./opensim.sh
|
||||||
|
* msbuild (xbuild) option switches
|
||||||
|
* clean: msbuild /target:clean
|
||||||
|
* debug: (default) msbuild /property:Configuration=Debug
|
||||||
|
* release: msbuild /property:Configuration=Release
|
||||||
|
|
||||||
|
# References
|
||||||
|
|
||||||
|
Helpful resources:
|
||||||
|
* http://opensimulator.org/wiki/Build_Instructions
|
|
@ -0,0 +1,254 @@
|
||||||
|
The following people have contributed to OpenSim (Thank you for your effort!)
|
||||||
|
|
||||||
|
= Current OpenSim Developers (in very rough order of appearance) =
|
||||||
|
These folks represent the current core team for OpenSim, and are the
|
||||||
|
people that make the day to day of OpenSim happen.
|
||||||
|
|
||||||
|
* Melanie Thielker
|
||||||
|
* Diva (Crista Lopes, University of California, Irvine)
|
||||||
|
* Robert Adams (MisterBlue)
|
||||||
|
* Kevin Cozens
|
||||||
|
* Leal Duarte (Ubit Umarov)
|
||||||
|
|
||||||
|
= Core Developers Following the White Rabbit =
|
||||||
|
Core developers who have temporarily (we hope) gone chasing the white rabbit.
|
||||||
|
They are in all similar to the active core developers, except that they haven't
|
||||||
|
been that active lately, so their voting rights are awaiting their come back.
|
||||||
|
|
||||||
|
* Nebadon Izumi (Michael Cerquoni, OSgrid)
|
||||||
|
* Alicia Raven
|
||||||
|
|
||||||
|
= Past Open Sim Developers =
|
||||||
|
These folks are alumns of the OpenSim core group, but are now
|
||||||
|
currently not active. Their great contributions helped get us to
|
||||||
|
where we are today.
|
||||||
|
|
||||||
|
* Gareth
|
||||||
|
* Andy-
|
||||||
|
* MorphW
|
||||||
|
* CW
|
||||||
|
* Babblefrog
|
||||||
|
* Danx0r
|
||||||
|
* Dalien
|
||||||
|
* Darok
|
||||||
|
* Alondria
|
||||||
|
* Sean Dague / sdague (IBM)
|
||||||
|
* Tedd
|
||||||
|
* MingChen (DeepThink Pty Ltd)
|
||||||
|
* adjohn (Genkii)
|
||||||
|
* idb (Ian Brown)
|
||||||
|
* Johan Berntsson (3Di)
|
||||||
|
* MW (Tribal Media AB)
|
||||||
|
* Adam Frisby (DeepThink Pty Ltd)
|
||||||
|
* lbsa71 (Tribal Media AB)
|
||||||
|
* Ckrinke (Charles Krinke)
|
||||||
|
* Dr Scofield aka Dirk Husemann (IBM Research - Zurich)
|
||||||
|
* mikem (3Di)
|
||||||
|
* Homer_Horwitz
|
||||||
|
* nlin (3Di)
|
||||||
|
* John Hurliman
|
||||||
|
* chi11ken (Genkii)
|
||||||
|
* dahlia
|
||||||
|
* justincc (OSVW Consulting, justincc.org)
|
||||||
|
* Arthur Rodrigo S Valadares (IBM)
|
||||||
|
* BlueWall (James Hughes)
|
||||||
|
* Dan Lake
|
||||||
|
* Marck
|
||||||
|
* Mic Bowman
|
||||||
|
* Oren Hurvitz (Kitely)
|
||||||
|
* Snoopy Pfeffer
|
||||||
|
* Teravus (w3z)
|
||||||
|
|
||||||
|
= Additional OpenSim Contributors =
|
||||||
|
These folks have contributed code patches or content to OpenSimulator to help make it
|
||||||
|
what it is today.
|
||||||
|
|
||||||
|
* A_Biondi
|
||||||
|
* aduffy70
|
||||||
|
* Ai Austin
|
||||||
|
* alex_carnell
|
||||||
|
* Alan Webb (IBM)
|
||||||
|
* Aleric
|
||||||
|
* Allen Kerensky
|
||||||
|
* BigFootAg
|
||||||
|
* Bill Blight
|
||||||
|
* BlueWall Slade
|
||||||
|
* bobshaffer2
|
||||||
|
* brianw/Sir_Ahzz
|
||||||
|
* CharlieO
|
||||||
|
* ChrisDown
|
||||||
|
* Chris Yeoh (IBM)
|
||||||
|
* cinderblocks
|
||||||
|
* controlbreak
|
||||||
|
* coyled
|
||||||
|
* ctrlaltdavid (David Rowe)
|
||||||
|
* Daedius
|
||||||
|
* daTwitch
|
||||||
|
* Dev Random
|
||||||
|
* devalnor-#708
|
||||||
|
* dmiles (Daxtron Labs)
|
||||||
|
* Dong Jun Lan (IBM)
|
||||||
|
* DoranZemlja
|
||||||
|
* Drake Arconis
|
||||||
|
* dr0b3rts
|
||||||
|
* dslake
|
||||||
|
* eeyore
|
||||||
|
* FredoChaplin
|
||||||
|
* FreakyTech
|
||||||
|
* Garmin Kawaguichi
|
||||||
|
* Gavin Hird
|
||||||
|
* Gerhard
|
||||||
|
* Godfrey
|
||||||
|
* Greg C.
|
||||||
|
* Grumly57
|
||||||
|
* GuduleLapointe
|
||||||
|
* Ewe Loon
|
||||||
|
* Fernando Oliveira
|
||||||
|
* Fly-Man
|
||||||
|
* Flyte Xevious
|
||||||
|
* Freaky Tech
|
||||||
|
* Garmin Kawaguichi
|
||||||
|
* Geir Noklebye
|
||||||
|
* Glenn Martin (MOSES)
|
||||||
|
* Gryc Ueusp
|
||||||
|
* H-H-H (ginge264)
|
||||||
|
* Hiro Lecker
|
||||||
|
* Iain Oliver
|
||||||
|
* Imaze Rhiano
|
||||||
|
* Intimidated
|
||||||
|
* Jak Daniels
|
||||||
|
* Jeff Kelly
|
||||||
|
* Jeremy Bongio (IBM)
|
||||||
|
* jhurliman
|
||||||
|
* John R Sohn (XenReborn)
|
||||||
|
* jonc
|
||||||
|
* Jon Cundill
|
||||||
|
* Junta Kohime
|
||||||
|
* Kayne
|
||||||
|
* kinoc (Daxtron Labs)
|
||||||
|
* Kira
|
||||||
|
* Kitto Flora
|
||||||
|
* KittyLiu
|
||||||
|
* Kurt Taylor (IBM)
|
||||||
|
* Lani Global
|
||||||
|
* lickx
|
||||||
|
* lillith_xue
|
||||||
|
* lkalif
|
||||||
|
* LuciusSirnah
|
||||||
|
* lulurun
|
||||||
|
* M.Igarashi
|
||||||
|
* Magnuz Binder
|
||||||
|
* maimedleech
|
||||||
|
* Mana Janus
|
||||||
|
* Mandarinka Tasty
|
||||||
|
* MarcelEdward
|
||||||
|
* Matt Lehmann
|
||||||
|
* mewtwo0641
|
||||||
|
* Mic Bowman
|
||||||
|
* Michelle Argus
|
||||||
|
* Michael Cortez (The Flotsam Project, http://osflotsam.org/)
|
||||||
|
* Michael Heilmann (MOSES)
|
||||||
|
* Micheil Merlin
|
||||||
|
* Mike Osias (IBM)
|
||||||
|
* Mike Pitman (IBM)
|
||||||
|
* Mike Rieker (Dreamnation)
|
||||||
|
* mikemig
|
||||||
|
* mikkopa/_someone - RealXtend
|
||||||
|
* Misterblue
|
||||||
|
* Mircea Kitsune
|
||||||
|
* mpallari
|
||||||
|
* MrMonkE
|
||||||
|
* Nebadon Izumi (Michael Cerquoni - http://OSgrid.org)
|
||||||
|
* Neil Canham
|
||||||
|
* nornalbion
|
||||||
|
* Omar Vera Ustariz (IBM)
|
||||||
|
* openlifegrid.com
|
||||||
|
* otakup0pe
|
||||||
|
* Pixel Tomsen
|
||||||
|
* Quill Littlefeather
|
||||||
|
* ralphos
|
||||||
|
* RemedyTomm
|
||||||
|
* Revolution
|
||||||
|
* Richard Alimi (IBM)
|
||||||
|
* Rick Alther (IBM)
|
||||||
|
* Rob Smart (IBM)
|
||||||
|
* Robert Louden (MOSES)
|
||||||
|
* Roger Kirkman (zadark)
|
||||||
|
* rtomita
|
||||||
|
* Ruud Lathorp
|
||||||
|
* SachaMagne
|
||||||
|
* Salahzar Stenvaag
|
||||||
|
* satguru p srivastava
|
||||||
|
* sempuki
|
||||||
|
* Shy Robbiani
|
||||||
|
* SignpostMarv
|
||||||
|
* SpotOn3D
|
||||||
|
* Stefan_Boom / stoehr
|
||||||
|
* Steven Zielinski (MOSES)
|
||||||
|
* Stolen Ruby
|
||||||
|
* Strawberry Fride
|
||||||
|
* Talun
|
||||||
|
* TechplexEngineer (Blake Bourque)
|
||||||
|
* TBG Renfold
|
||||||
|
* Terry Ford
|
||||||
|
* tglion
|
||||||
|
* tlaukkan/Tommil (Tommi S. E. Laukkanen, Bubble Cloud)
|
||||||
|
* TomDataWorks
|
||||||
|
* TomTheDragon (muckwaddle)
|
||||||
|
* tyre
|
||||||
|
* uriesk
|
||||||
|
* Vegaslon <vegaslon@gmail.com>
|
||||||
|
* Vincent Sylvester
|
||||||
|
* VikingErik
|
||||||
|
* Vytek
|
||||||
|
* webmage (IBM)
|
||||||
|
* Xantor
|
||||||
|
* Y. Nitta
|
||||||
|
* YoshikoFazuku
|
||||||
|
* YZh
|
||||||
|
* Zackary Geers aka Kunnis Basiat
|
||||||
|
* Zha Ewry
|
||||||
|
* ziah
|
||||||
|
|
||||||
|
= LSL Devs =
|
||||||
|
* Alondria
|
||||||
|
* CharlieO
|
||||||
|
* Tedd
|
||||||
|
* Melanie Thielker
|
||||||
|
|
||||||
|
= Testers =
|
||||||
|
* Ai Austin
|
||||||
|
* CharlieO (LSL)
|
||||||
|
* Ckrinke
|
||||||
|
* openlifegrid.com
|
||||||
|
|
||||||
|
This software uses components from the following developers:
|
||||||
|
* Sleepycat Software (Berkeley DB)
|
||||||
|
* Aurora-Sim (http://aurora-sim.org)
|
||||||
|
* SQLite (Public Domain)
|
||||||
|
* XmlRpcCS (http://xmlrpccs.sf.net/)
|
||||||
|
* MySQL, Inc. (MySQL Connector/NET)
|
||||||
|
* NUnit (http://www.nunit.org)
|
||||||
|
* AGEIA Inc. (PhysX)
|
||||||
|
* Russel L. Smith (ODE)
|
||||||
|
* Erwin Coumans (Bullet)
|
||||||
|
* Prebuild (http://sourceforge.net/projects/dnpb/)
|
||||||
|
* LibOpenMetaverse (http://lib.openmetaverse.org/)
|
||||||
|
* DotNetOpenMail v0.5.8b (http://dotnetopenmail.sourceforge.net)
|
||||||
|
* Prototype JavaScript Framework ajax (http://www.prototypejs.org/)
|
||||||
|
* C5 GENERIC COLLECTION LIBRARY FOR C#/CLI
|
||||||
|
* Nini (http://nini.sourceforge.net/)
|
||||||
|
* log4net (http://logging.apache.org/log4net/)
|
||||||
|
* GlynnTucker.Cache (http://gtcache.sourceforge.net/)
|
||||||
|
* NDesk.Options 0.2.1 (http://www.ndesk.org/Options)
|
||||||
|
* Json.NET 3.5 Release 6. The binary used is actually Newtonsoft.Json.Net20.dll for Mono 2.4 compatability (http://james.newtonking.com/projects/json-net.aspx)
|
||||||
|
* zlib.net for C# 1.0.4 (http://www.componentace.com/zlib_.NET.htm)
|
||||||
|
|
||||||
|
Some plugins are based on Cable Beach
|
||||||
|
Cable Beach is Copyright (c) 2008 Intel Corporation
|
||||||
|
see http://forge.opensimulator.org/gf/project/assetserver/
|
||||||
|
|
||||||
|
In addition, we would like to thank:
|
||||||
|
* The Mono Project
|
||||||
|
* The NANT Developers
|
||||||
|
* Microsoft (.NET, MSSQL-Adapters)
|
|
@ -0,0 +1,25 @@
|
||||||
|
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.
|
|
@ -0,0 +1,43 @@
|
||||||
|
# hey, emacs! this is a -*- makefile -*-
|
||||||
|
#
|
||||||
|
# OpenSim makefile
|
||||||
|
#
|
||||||
|
|
||||||
|
RUBY = $(strip $(shell which ruby 2>/dev/null))
|
||||||
|
ifeq ($(RUBY),)
|
||||||
|
NANT = nant
|
||||||
|
else
|
||||||
|
NANT = $(shell if test "$$EMACS" = "t" ; then echo "nant"; else echo "./nant-color"; fi)
|
||||||
|
endif
|
||||||
|
|
||||||
|
all: prebuild
|
||||||
|
# @export PATH=/usr/local/bin:$(PATH)
|
||||||
|
${NANT}
|
||||||
|
find OpenSim -name \*.mdb -exec cp {} bin \;
|
||||||
|
|
||||||
|
release: prebuild
|
||||||
|
${NANT} -D:project.config=Release
|
||||||
|
find OpenSim -name \*.mdb -exec cp {} bin \;
|
||||||
|
|
||||||
|
prebuild:
|
||||||
|
./runprebuild.sh
|
||||||
|
|
||||||
|
clean:
|
||||||
|
# @export PATH=/usr/local/bin:$(PATH)
|
||||||
|
-${NANT} clean
|
||||||
|
|
||||||
|
test: prebuild
|
||||||
|
${NANT} test
|
||||||
|
|
||||||
|
test-xml: prebuild
|
||||||
|
${NANT} test-xml
|
||||||
|
|
||||||
|
tags:
|
||||||
|
find OpenSim -name \*\.cs | xargs etags
|
||||||
|
|
||||||
|
cscope-tags:
|
||||||
|
find OpenSim -name \*\.cs -fprint cscope.files
|
||||||
|
cscope -b
|
||||||
|
|
||||||
|
include $(wildcard Makefile.local)
|
||||||
|
|
|
@ -0,0 +1,78 @@
|
||||||
|
/*
|
||||||
|
* 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 OpenSim.Framework;
|
||||||
|
using OpenSim.Region.Framework.Interfaces;
|
||||||
|
using OpenSim.Services.Interfaces;
|
||||||
|
|
||||||
|
namespace OpenSim.Groups
|
||||||
|
{
|
||||||
|
public class ForeignImporter
|
||||||
|
{
|
||||||
|
IUserManagement m_UserManagement;
|
||||||
|
public ForeignImporter(IUserManagement uman)
|
||||||
|
{
|
||||||
|
m_UserManagement = uman;
|
||||||
|
}
|
||||||
|
|
||||||
|
public GroupMembersData ConvertGroupMembersData(ExtendedGroupMembersData _m)
|
||||||
|
{
|
||||||
|
GroupMembersData m = new GroupMembersData();
|
||||||
|
m.AcceptNotices = _m.AcceptNotices;
|
||||||
|
m.AgentPowers = _m.AgentPowers;
|
||||||
|
m.Contribution = _m.Contribution;
|
||||||
|
m.IsOwner = _m.IsOwner;
|
||||||
|
m.ListInProfile = _m.ListInProfile;
|
||||||
|
m.OnlineStatus = _m.OnlineStatus;
|
||||||
|
m.Title = _m.Title;
|
||||||
|
|
||||||
|
string url = string.Empty, first = string.Empty, last = string.Empty, tmp = string.Empty;
|
||||||
|
Util.ParseUniversalUserIdentifier(_m.AgentID, out m.AgentID, out url, out first, out last, out tmp);
|
||||||
|
if (url != string.Empty)
|
||||||
|
m_UserManagement.AddUser(m.AgentID, first, last, url);
|
||||||
|
|
||||||
|
return m;
|
||||||
|
}
|
||||||
|
|
||||||
|
public GroupRoleMembersData ConvertGroupRoleMembersData(ExtendedGroupRoleMembersData _rm)
|
||||||
|
{
|
||||||
|
GroupRoleMembersData rm = new GroupRoleMembersData();
|
||||||
|
rm.RoleID = _rm.RoleID;
|
||||||
|
|
||||||
|
string url = string.Empty, first = string.Empty, last = string.Empty, tmp = string.Empty;
|
||||||
|
Util.ParseUniversalUserIdentifier(_rm.MemberID, out rm.MemberID, out url, out first, out last, out tmp);
|
||||||
|
if (url != string.Empty)
|
||||||
|
m_UserManagement.AddUser(rm.MemberID, first, last, url);
|
||||||
|
|
||||||
|
return rm;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,533 @@
|
||||||
|
/*
|
||||||
|
* 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 OpenSim.Framework;
|
||||||
|
using OpenMetaverse;
|
||||||
|
|
||||||
|
namespace OpenSim.Groups
|
||||||
|
{
|
||||||
|
public class ExtendedGroupRecord : GroupRecord
|
||||||
|
{
|
||||||
|
public int MemberCount;
|
||||||
|
public int RoleCount;
|
||||||
|
public string ServiceLocation;
|
||||||
|
public string FounderUUI;
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ExtendedGroupMembershipData : GroupMembershipData
|
||||||
|
{
|
||||||
|
public string AccessToken;
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ExtendedGroupMembersData
|
||||||
|
{
|
||||||
|
// This is the only difference: this is a string
|
||||||
|
public string AgentID;
|
||||||
|
public int Contribution;
|
||||||
|
public string OnlineStatus;
|
||||||
|
public ulong AgentPowers;
|
||||||
|
public string Title;
|
||||||
|
public bool IsOwner;
|
||||||
|
public bool ListInProfile;
|
||||||
|
public bool AcceptNotices;
|
||||||
|
public string AccessToken;
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ExtendedGroupRoleMembersData
|
||||||
|
{
|
||||||
|
public UUID RoleID;
|
||||||
|
// This is the only difference: this is a string
|
||||||
|
public string MemberID;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public struct ExtendedGroupNoticeData
|
||||||
|
{
|
||||||
|
public UUID NoticeID;
|
||||||
|
public uint Timestamp;
|
||||||
|
public string FromName;
|
||||||
|
public string Subject;
|
||||||
|
public bool HasAttachment;
|
||||||
|
public byte AttachmentType;
|
||||||
|
public string AttachmentName;
|
||||||
|
public UUID AttachmentItemID;
|
||||||
|
public string AttachmentOwnerID;
|
||||||
|
|
||||||
|
public GroupNoticeData ToGroupNoticeData()
|
||||||
|
{
|
||||||
|
GroupNoticeData n = new GroupNoticeData();
|
||||||
|
n.FromName = this.FromName;
|
||||||
|
n.AssetType = this.AttachmentType;
|
||||||
|
n.HasAttachment = this.HasAttachment;
|
||||||
|
n.NoticeID = this.NoticeID;
|
||||||
|
n.Subject = this.Subject;
|
||||||
|
n.Timestamp = this.Timestamp;
|
||||||
|
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class GroupsDataUtils
|
||||||
|
{
|
||||||
|
public static string Sanitize(string s)
|
||||||
|
{
|
||||||
|
return s == null ? string.Empty : s;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Dictionary<string, object> GroupRecord(ExtendedGroupRecord grec)
|
||||||
|
{
|
||||||
|
Dictionary<string, object> dict = new Dictionary<string, object>();
|
||||||
|
if (grec == null)
|
||||||
|
return dict;
|
||||||
|
|
||||||
|
dict["AllowPublish"] = grec.AllowPublish.ToString();
|
||||||
|
dict["Charter"] = Sanitize(grec.Charter);
|
||||||
|
dict["FounderID"] = grec.FounderID.ToString();
|
||||||
|
dict["FounderUUI"] = Sanitize(grec.FounderUUI);
|
||||||
|
dict["GroupID"] = grec.GroupID.ToString();
|
||||||
|
dict["GroupName"] = Sanitize(grec.GroupName);
|
||||||
|
dict["InsigniaID"] = grec.GroupPicture.ToString();
|
||||||
|
dict["MaturePublish"] = grec.MaturePublish.ToString();
|
||||||
|
dict["MembershipFee"] = grec.MembershipFee.ToString();
|
||||||
|
dict["OpenEnrollment"] = grec.OpenEnrollment.ToString();
|
||||||
|
dict["OwnerRoleID"] = grec.OwnerRoleID.ToString();
|
||||||
|
dict["ServiceLocation"] = Sanitize(grec.ServiceLocation);
|
||||||
|
dict["ShownInList"] = grec.ShowInList.ToString();
|
||||||
|
dict["MemberCount"] = grec.MemberCount.ToString();
|
||||||
|
dict["RoleCount"] = grec.RoleCount.ToString();
|
||||||
|
|
||||||
|
return dict;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ExtendedGroupRecord GroupRecord(Dictionary<string, object> dict)
|
||||||
|
{
|
||||||
|
if (dict == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
ExtendedGroupRecord grec = new ExtendedGroupRecord();
|
||||||
|
if (dict.ContainsKey("AllowPublish") && dict["AllowPublish"] != null)
|
||||||
|
grec.AllowPublish = bool.Parse(dict["AllowPublish"].ToString());
|
||||||
|
|
||||||
|
if (dict.ContainsKey("Charter") && dict["Charter"] != null)
|
||||||
|
grec.Charter = dict["Charter"].ToString();
|
||||||
|
else
|
||||||
|
grec.Charter = string.Empty;
|
||||||
|
|
||||||
|
if (dict.ContainsKey("FounderID") && dict["FounderID"] != null)
|
||||||
|
grec.FounderID = UUID.Parse(dict["FounderID"].ToString());
|
||||||
|
|
||||||
|
if (dict.ContainsKey("FounderUUI") && dict["FounderUUI"] != null)
|
||||||
|
grec.FounderUUI = dict["FounderUUI"].ToString();
|
||||||
|
else
|
||||||
|
grec.FounderUUI = string.Empty;
|
||||||
|
|
||||||
|
if (dict.ContainsKey("GroupID") && dict["GroupID"] != null)
|
||||||
|
grec.GroupID = UUID.Parse(dict["GroupID"].ToString());
|
||||||
|
|
||||||
|
if (dict.ContainsKey("GroupName") && dict["GroupName"] != null)
|
||||||
|
grec.GroupName = dict["GroupName"].ToString();
|
||||||
|
else
|
||||||
|
grec.GroupName = string.Empty;
|
||||||
|
|
||||||
|
if (dict.ContainsKey("InsigniaID") && dict["InsigniaID"] != null)
|
||||||
|
grec.GroupPicture = UUID.Parse(dict["InsigniaID"].ToString());
|
||||||
|
|
||||||
|
if (dict.ContainsKey("MaturePublish") && dict["MaturePublish"] != null)
|
||||||
|
grec.MaturePublish = bool.Parse(dict["MaturePublish"].ToString());
|
||||||
|
|
||||||
|
if (dict.ContainsKey("MembershipFee") && dict["MembershipFee"] != null)
|
||||||
|
grec.MembershipFee = Int32.Parse(dict["MembershipFee"].ToString());
|
||||||
|
|
||||||
|
if (dict.ContainsKey("OpenEnrollment") && dict["OpenEnrollment"] != null)
|
||||||
|
grec.OpenEnrollment = bool.Parse(dict["OpenEnrollment"].ToString());
|
||||||
|
|
||||||
|
if (dict.ContainsKey("OwnerRoleID") && dict["OwnerRoleID"] != null)
|
||||||
|
grec.OwnerRoleID = UUID.Parse(dict["OwnerRoleID"].ToString());
|
||||||
|
|
||||||
|
if (dict.ContainsKey("ServiceLocation") && dict["ServiceLocation"] != null)
|
||||||
|
grec.ServiceLocation = dict["ServiceLocation"].ToString();
|
||||||
|
else
|
||||||
|
grec.ServiceLocation = string.Empty;
|
||||||
|
|
||||||
|
if (dict.ContainsKey("ShownInList") && dict["ShownInList"] != null)
|
||||||
|
grec.ShowInList = bool.Parse(dict["ShownInList"].ToString());
|
||||||
|
|
||||||
|
if (dict.ContainsKey("MemberCount") && dict["MemberCount"] != null)
|
||||||
|
grec.MemberCount = Int32.Parse(dict["MemberCount"].ToString());
|
||||||
|
|
||||||
|
if (dict.ContainsKey("RoleCount") && dict["RoleCount"] != null)
|
||||||
|
grec.RoleCount = Int32.Parse(dict["RoleCount"].ToString());
|
||||||
|
|
||||||
|
return grec;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Dictionary<string, object> GroupMembershipData(ExtendedGroupMembershipData membership)
|
||||||
|
{
|
||||||
|
Dictionary<string, object> dict = new Dictionary<string, object>();
|
||||||
|
if (membership == null)
|
||||||
|
return dict;
|
||||||
|
|
||||||
|
dict["AcceptNotices"] = membership.AcceptNotices.ToString();
|
||||||
|
dict["AccessToken"] = Sanitize(membership.AccessToken);
|
||||||
|
dict["Active"] = membership.Active.ToString();
|
||||||
|
dict["ActiveRole"] = membership.ActiveRole.ToString();
|
||||||
|
dict["AllowPublish"] = membership.AllowPublish.ToString();
|
||||||
|
dict["Charter"] = Sanitize(membership.Charter);
|
||||||
|
dict["Contribution"] = membership.Contribution.ToString();
|
||||||
|
dict["FounderID"] = membership.FounderID.ToString();
|
||||||
|
dict["GroupID"] = membership.GroupID.ToString();
|
||||||
|
dict["GroupName"] = Sanitize(membership.GroupName);
|
||||||
|
dict["GroupPicture"] = membership.GroupPicture.ToString();
|
||||||
|
dict["GroupPowers"] = membership.GroupPowers.ToString();
|
||||||
|
dict["GroupTitle"] = Sanitize(membership.GroupTitle);
|
||||||
|
dict["ListInProfile"] = membership.ListInProfile.ToString();
|
||||||
|
dict["MaturePublish"] = membership.MaturePublish.ToString();
|
||||||
|
dict["MembershipFee"] = membership.MembershipFee.ToString();
|
||||||
|
dict["OpenEnrollment"] = membership.OpenEnrollment.ToString();
|
||||||
|
dict["ShowInList"] = membership.ShowInList.ToString();
|
||||||
|
|
||||||
|
return dict;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ExtendedGroupMembershipData GroupMembershipData(Dictionary<string, object> dict)
|
||||||
|
{
|
||||||
|
if (dict == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
ExtendedGroupMembershipData membership = new ExtendedGroupMembershipData();
|
||||||
|
|
||||||
|
if (dict.ContainsKey("AcceptNotices") && dict["AcceptNotices"] != null)
|
||||||
|
membership.AcceptNotices = bool.Parse(dict["AcceptNotices"].ToString());
|
||||||
|
|
||||||
|
if (dict.ContainsKey("AccessToken") && dict["AccessToken"] != null)
|
||||||
|
membership.AccessToken = dict["AccessToken"].ToString();
|
||||||
|
else
|
||||||
|
membership.AccessToken = string.Empty;
|
||||||
|
|
||||||
|
if (dict.ContainsKey("Active") && dict["Active"] != null)
|
||||||
|
membership.Active = bool.Parse(dict["Active"].ToString());
|
||||||
|
|
||||||
|
if (dict.ContainsKey("ActiveRole") && dict["ActiveRole"] != null)
|
||||||
|
membership.ActiveRole = UUID.Parse(dict["ActiveRole"].ToString());
|
||||||
|
|
||||||
|
if (dict.ContainsKey("AllowPublish") && dict["AllowPublish"] != null)
|
||||||
|
membership.AllowPublish = bool.Parse(dict["AllowPublish"].ToString());
|
||||||
|
|
||||||
|
if (dict.ContainsKey("Charter") && dict["Charter"] != null)
|
||||||
|
membership.Charter = dict["Charter"].ToString();
|
||||||
|
else
|
||||||
|
membership.Charter = string.Empty;
|
||||||
|
|
||||||
|
if (dict.ContainsKey("Contribution") && dict["Contribution"] != null)
|
||||||
|
membership.Contribution = Int32.Parse(dict["Contribution"].ToString());
|
||||||
|
|
||||||
|
if (dict.ContainsKey("FounderID") && dict["FounderID"] != null)
|
||||||
|
membership.FounderID = UUID.Parse(dict["FounderID"].ToString());
|
||||||
|
|
||||||
|
if (dict.ContainsKey("GroupID") && dict["GroupID"] != null)
|
||||||
|
membership.GroupID = UUID.Parse(dict["GroupID"].ToString());
|
||||||
|
|
||||||
|
if (dict.ContainsKey("GroupName") && dict["GroupName"] != null)
|
||||||
|
membership.GroupName = dict["GroupName"].ToString();
|
||||||
|
else
|
||||||
|
membership.GroupName = string.Empty;
|
||||||
|
|
||||||
|
if (dict.ContainsKey("GroupPicture") && dict["GroupPicture"] != null)
|
||||||
|
membership.GroupPicture = UUID.Parse(dict["GroupPicture"].ToString());
|
||||||
|
|
||||||
|
if (dict.ContainsKey("GroupPowers") && dict["GroupPowers"] != null)
|
||||||
|
membership.GroupPowers = UInt64.Parse(dict["GroupPowers"].ToString());
|
||||||
|
|
||||||
|
if (dict.ContainsKey("GroupTitle") && dict["GroupTitle"] != null)
|
||||||
|
membership.GroupTitle = dict["GroupTitle"].ToString();
|
||||||
|
else
|
||||||
|
membership.GroupTitle = string.Empty;
|
||||||
|
|
||||||
|
if (dict.ContainsKey("ListInProfile") && dict["ListInProfile"] != null)
|
||||||
|
membership.ListInProfile = bool.Parse(dict["ListInProfile"].ToString());
|
||||||
|
|
||||||
|
if (dict.ContainsKey("MaturePublish") && dict["MaturePublish"] != null)
|
||||||
|
membership.MaturePublish = bool.Parse(dict["MaturePublish"].ToString());
|
||||||
|
|
||||||
|
if (dict.ContainsKey("MembershipFee") && dict["MembershipFee"] != null)
|
||||||
|
membership.MembershipFee = Int32.Parse(dict["MembershipFee"].ToString());
|
||||||
|
|
||||||
|
if (dict.ContainsKey("OpenEnrollment") && dict["OpenEnrollment"] != null)
|
||||||
|
membership.OpenEnrollment = bool.Parse(dict["OpenEnrollment"].ToString());
|
||||||
|
|
||||||
|
if (dict.ContainsKey("ShowInList") && dict["ShowInList"] != null)
|
||||||
|
membership.ShowInList = bool.Parse(dict["ShowInList"].ToString());
|
||||||
|
|
||||||
|
return membership;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Dictionary<string, object> GroupMembersData(ExtendedGroupMembersData member)
|
||||||
|
{
|
||||||
|
Dictionary<string, object> dict = new Dictionary<string, object>();
|
||||||
|
|
||||||
|
dict["AcceptNotices"] = member.AcceptNotices.ToString();
|
||||||
|
dict["AccessToken"] = Sanitize(member.AccessToken);
|
||||||
|
dict["AgentID"] = Sanitize(member.AgentID);
|
||||||
|
dict["AgentPowers"] = member.AgentPowers.ToString();
|
||||||
|
dict["Contribution"] = member.Contribution.ToString();
|
||||||
|
dict["IsOwner"] = member.IsOwner.ToString();
|
||||||
|
dict["ListInProfile"] = member.ListInProfile.ToString();
|
||||||
|
dict["OnlineStatus"] = Sanitize(member.OnlineStatus);
|
||||||
|
dict["Title"] = Sanitize(member.Title);
|
||||||
|
|
||||||
|
return dict;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ExtendedGroupMembersData GroupMembersData(Dictionary<string, object> dict)
|
||||||
|
{
|
||||||
|
ExtendedGroupMembersData member = new ExtendedGroupMembersData();
|
||||||
|
|
||||||
|
if (dict == null)
|
||||||
|
return member;
|
||||||
|
|
||||||
|
if (dict.ContainsKey("AcceptNotices") && dict["AcceptNotices"] != null)
|
||||||
|
member.AcceptNotices = bool.Parse(dict["AcceptNotices"].ToString());
|
||||||
|
|
||||||
|
if (dict.ContainsKey("AccessToken") && dict["AccessToken"] != null)
|
||||||
|
member.AccessToken = Sanitize(dict["AccessToken"].ToString());
|
||||||
|
else
|
||||||
|
member.AccessToken = string.Empty;
|
||||||
|
|
||||||
|
if (dict.ContainsKey("AgentID") && dict["AgentID"] != null)
|
||||||
|
member.AgentID = Sanitize(dict["AgentID"].ToString());
|
||||||
|
else
|
||||||
|
member.AgentID = UUID.Zero.ToString();
|
||||||
|
|
||||||
|
if (dict.ContainsKey("AgentPowers") && dict["AgentPowers"] != null)
|
||||||
|
member.AgentPowers = UInt64.Parse(dict["AgentPowers"].ToString());
|
||||||
|
|
||||||
|
if (dict.ContainsKey("Contribution") && dict["Contribution"] != null)
|
||||||
|
member.Contribution = Int32.Parse(dict["Contribution"].ToString());
|
||||||
|
|
||||||
|
if (dict.ContainsKey("IsOwner") && dict["IsOwner"] != null)
|
||||||
|
member.IsOwner = bool.Parse(dict["IsOwner"].ToString());
|
||||||
|
|
||||||
|
if (dict.ContainsKey("ListInProfile") && dict["ListInProfile"] != null)
|
||||||
|
member.ListInProfile = bool.Parse(dict["ListInProfile"].ToString());
|
||||||
|
|
||||||
|
if (dict.ContainsKey("OnlineStatus") && dict["OnlineStatus"] != null)
|
||||||
|
member.OnlineStatus = Sanitize(dict["OnlineStatus"].ToString());
|
||||||
|
else
|
||||||
|
member.OnlineStatus = string.Empty;
|
||||||
|
|
||||||
|
if (dict.ContainsKey("Title") && dict["Title"] != null)
|
||||||
|
member.Title = Sanitize(dict["Title"].ToString());
|
||||||
|
else
|
||||||
|
member.Title = string.Empty;
|
||||||
|
|
||||||
|
return member;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Dictionary<string, object> GroupRolesData(GroupRolesData role)
|
||||||
|
{
|
||||||
|
Dictionary<string, object> dict = new Dictionary<string, object>();
|
||||||
|
|
||||||
|
dict["Description"] = Sanitize(role.Description);
|
||||||
|
dict["Members"] = role.Members.ToString();
|
||||||
|
dict["Name"] = Sanitize(role.Name);
|
||||||
|
dict["Powers"] = role.Powers.ToString();
|
||||||
|
dict["RoleID"] = role.RoleID.ToString();
|
||||||
|
dict["Title"] = Sanitize(role.Title);
|
||||||
|
|
||||||
|
return dict;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static GroupRolesData GroupRolesData(Dictionary<string, object> dict)
|
||||||
|
{
|
||||||
|
GroupRolesData role = new GroupRolesData();
|
||||||
|
|
||||||
|
if (dict == null)
|
||||||
|
return role;
|
||||||
|
|
||||||
|
if (dict.ContainsKey("Description") && dict["Description"] != null)
|
||||||
|
role.Description = Sanitize(dict["Description"].ToString());
|
||||||
|
else
|
||||||
|
role.Description = string.Empty;
|
||||||
|
|
||||||
|
if (dict.ContainsKey("Members") && dict["Members"] != null)
|
||||||
|
role.Members = Int32.Parse(dict["Members"].ToString());
|
||||||
|
|
||||||
|
if (dict.ContainsKey("Name") && dict["Name"] != null)
|
||||||
|
role.Name = Sanitize(dict["Name"].ToString());
|
||||||
|
else
|
||||||
|
role.Name = string.Empty;
|
||||||
|
|
||||||
|
if (dict.ContainsKey("Powers") && dict["Powers"] != null)
|
||||||
|
role.Powers = UInt64.Parse(dict["Powers"].ToString());
|
||||||
|
|
||||||
|
if (dict.ContainsKey("Title") && dict["Title"] != null)
|
||||||
|
role.Title = Sanitize(dict["Title"].ToString());
|
||||||
|
else
|
||||||
|
role.Title = string.Empty;
|
||||||
|
|
||||||
|
if (dict.ContainsKey("RoleID") && dict["RoleID"] != null)
|
||||||
|
role.RoleID = UUID.Parse(dict["RoleID"].ToString());
|
||||||
|
|
||||||
|
return role;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Dictionary<string, object> GroupRoleMembersData(ExtendedGroupRoleMembersData rmember)
|
||||||
|
{
|
||||||
|
Dictionary<string, object> dict = new Dictionary<string, object>();
|
||||||
|
|
||||||
|
dict["RoleID"] = rmember.RoleID.ToString();
|
||||||
|
dict["MemberID"] = rmember.MemberID;
|
||||||
|
return dict;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ExtendedGroupRoleMembersData GroupRoleMembersData(Dictionary<string, object> dict)
|
||||||
|
{
|
||||||
|
ExtendedGroupRoleMembersData rmember = new ExtendedGroupRoleMembersData();
|
||||||
|
|
||||||
|
if (dict.ContainsKey("RoleID") && dict["RoleID"] != null)
|
||||||
|
rmember.RoleID = new UUID(dict["RoleID"].ToString());
|
||||||
|
|
||||||
|
if (dict.ContainsKey("MemberID") && dict["MemberID"] != null)
|
||||||
|
rmember.MemberID = dict["MemberID"].ToString();
|
||||||
|
|
||||||
|
return rmember;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Dictionary<string, object> GroupInviteInfo(GroupInviteInfo invite)
|
||||||
|
{
|
||||||
|
Dictionary<string, object> dict = new Dictionary<string, object>();
|
||||||
|
|
||||||
|
dict["InviteID"] = invite.InviteID.ToString();
|
||||||
|
dict["GroupID"] = invite.GroupID.ToString();
|
||||||
|
dict["RoleID"] = invite.RoleID.ToString();
|
||||||
|
dict["AgentID"] = invite.AgentID;
|
||||||
|
|
||||||
|
return dict;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static GroupInviteInfo GroupInviteInfo(Dictionary<string, object> dict)
|
||||||
|
{
|
||||||
|
if (dict == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
GroupInviteInfo invite = new GroupInviteInfo();
|
||||||
|
|
||||||
|
invite.InviteID = new UUID(dict["InviteID"].ToString());
|
||||||
|
invite.GroupID = new UUID(dict["GroupID"].ToString());
|
||||||
|
invite.RoleID = new UUID(dict["RoleID"].ToString());
|
||||||
|
invite.AgentID = Sanitize(dict["AgentID"].ToString());
|
||||||
|
|
||||||
|
return invite;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Dictionary<string, object> GroupNoticeData(ExtendedGroupNoticeData notice)
|
||||||
|
{
|
||||||
|
Dictionary<string, object> dict = new Dictionary<string, object>();
|
||||||
|
|
||||||
|
dict["NoticeID"] = notice.NoticeID.ToString();
|
||||||
|
dict["Timestamp"] = notice.Timestamp.ToString();
|
||||||
|
dict["FromName"] = Sanitize(notice.FromName);
|
||||||
|
dict["Subject"] = Sanitize(notice.Subject);
|
||||||
|
dict["HasAttachment"] = notice.HasAttachment.ToString();
|
||||||
|
dict["AttachmentItemID"] = notice.AttachmentItemID.ToString();
|
||||||
|
dict["AttachmentName"] = Sanitize(notice.AttachmentName);
|
||||||
|
dict["AttachmentType"] = notice.AttachmentType.ToString();
|
||||||
|
dict["AttachmentOwnerID"] = Sanitize(notice.AttachmentOwnerID);
|
||||||
|
|
||||||
|
return dict;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ExtendedGroupNoticeData GroupNoticeData(Dictionary<string, object> dict)
|
||||||
|
{
|
||||||
|
ExtendedGroupNoticeData notice = new ExtendedGroupNoticeData();
|
||||||
|
|
||||||
|
if (dict == null)
|
||||||
|
return notice;
|
||||||
|
|
||||||
|
notice.NoticeID = new UUID(dict["NoticeID"].ToString());
|
||||||
|
notice.Timestamp = UInt32.Parse(dict["Timestamp"].ToString());
|
||||||
|
notice.FromName = Sanitize(dict["FromName"].ToString());
|
||||||
|
notice.Subject = Sanitize(dict["Subject"].ToString());
|
||||||
|
notice.HasAttachment = bool.Parse(dict["HasAttachment"].ToString());
|
||||||
|
notice.AttachmentItemID = new UUID(dict["AttachmentItemID"].ToString());
|
||||||
|
notice.AttachmentName = dict["AttachmentName"].ToString();
|
||||||
|
notice.AttachmentType = byte.Parse(dict["AttachmentType"].ToString());
|
||||||
|
notice.AttachmentOwnerID = dict["AttachmentOwnerID"].ToString();
|
||||||
|
|
||||||
|
return notice;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Dictionary<string, object> GroupNoticeInfo(GroupNoticeInfo notice)
|
||||||
|
{
|
||||||
|
Dictionary<string, object> dict = GroupNoticeData(notice.noticeData);
|
||||||
|
|
||||||
|
dict["GroupID"] = notice.GroupID.ToString();
|
||||||
|
dict["Message"] = Sanitize(notice.Message);
|
||||||
|
|
||||||
|
return dict;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static GroupNoticeInfo GroupNoticeInfo(Dictionary<string, object> dict)
|
||||||
|
{
|
||||||
|
GroupNoticeInfo notice = new GroupNoticeInfo();
|
||||||
|
|
||||||
|
notice.noticeData = GroupNoticeData(dict);
|
||||||
|
notice.GroupID = new UUID(dict["GroupID"].ToString());
|
||||||
|
notice.Message = Sanitize(dict["Message"].ToString());
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,841 @@
|
||||||
|
/*
|
||||||
|
* 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.Reflection;
|
||||||
|
using log4net;
|
||||||
|
using Mono.Addins;
|
||||||
|
using Nini.Config;
|
||||||
|
using OpenMetaverse;
|
||||||
|
using OpenMetaverse.StructuredData;
|
||||||
|
using OpenSim.Framework;
|
||||||
|
using OpenSim.Region.Framework.Interfaces;
|
||||||
|
using OpenSim.Region.Framework.Scenes;
|
||||||
|
using OpenSim.Services.Interfaces;
|
||||||
|
using PresenceInfo = OpenSim.Services.Interfaces.PresenceInfo;
|
||||||
|
using GridRegion = OpenSim.Services.Interfaces.GridRegion;
|
||||||
|
|
||||||
|
namespace OpenSim.Groups
|
||||||
|
{
|
||||||
|
[Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "GroupsMessagingModule")]
|
||||||
|
public class GroupsMessagingModule : ISharedRegionModule, IGroupsMessagingModule
|
||||||
|
{
|
||||||
|
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
|
|
||||||
|
private List<Scene> m_sceneList = new List<Scene>();
|
||||||
|
private IPresenceService m_presenceService;
|
||||||
|
|
||||||
|
private IMessageTransferModule m_msgTransferModule = null;
|
||||||
|
private IUserManagement m_UserManagement = null;
|
||||||
|
private IGroupsServicesConnector m_groupData = null;
|
||||||
|
|
||||||
|
// Config Options
|
||||||
|
private bool m_groupMessagingEnabled;
|
||||||
|
private bool m_debugEnabled;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// If enabled, module only tries to send group IMs to online users by querying cached presence information.
|
||||||
|
/// </summary>
|
||||||
|
private bool m_messageOnlineAgentsOnly;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Cache for online users.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Group ID is key, presence information for online members is value.
|
||||||
|
/// Will only be non-null if m_messageOnlineAgentsOnly = true
|
||||||
|
/// We cache here so that group messages don't constantly have to re-request the online user list to avoid
|
||||||
|
/// attempted expensive sending of messages to offline users.
|
||||||
|
/// The tradeoff is that a user that comes online will not receive messages consistently from all other users
|
||||||
|
/// until caches have updated.
|
||||||
|
/// Therefore, we set the cache expiry to just 20 seconds.
|
||||||
|
/// </remarks>
|
||||||
|
private ExpiringCache<UUID, PresenceInfo[]> m_usersOnlineCache;
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
public void Initialise(IConfigSource config)
|
||||||
|
{
|
||||||
|
IConfig groupsConfig = config.Configs["Groups"];
|
||||||
|
|
||||||
|
if (groupsConfig == null)
|
||||||
|
// Do not run this module by default.
|
||||||
|
return;
|
||||||
|
|
||||||
|
// if groups aren't enabled, we're not needed.
|
||||||
|
// if we're not specified as the connector to use, then we're not wanted
|
||||||
|
if ((groupsConfig.GetBoolean("Enabled", false) == false)
|
||||||
|
|| (groupsConfig.GetString("MessagingModule", "") != Name))
|
||||||
|
{
|
||||||
|
m_groupMessagingEnabled = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_groupMessagingEnabled = groupsConfig.GetBoolean("MessagingEnabled", true);
|
||||||
|
|
||||||
|
if (!m_groupMessagingEnabled)
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_messageOnlineAgentsOnly = groupsConfig.GetBoolean("MessageOnlineUsersOnly", false);
|
||||||
|
|
||||||
|
if (m_messageOnlineAgentsOnly)
|
||||||
|
{
|
||||||
|
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_log.InfoFormat(
|
||||||
|
"[Groups.Messaging]: GroupsMessagingModule enabled with MessageOnlineOnly = {0}, DebugEnabled = {1}",
|
||||||
|
m_messageOnlineAgentsOnly, m_debugEnabled);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddRegion(Scene scene)
|
||||||
|
{
|
||||||
|
if (!m_groupMessagingEnabled)
|
||||||
|
return;
|
||||||
|
|
||||||
|
scene.RegisterModuleInterface<IGroupsMessagingModule>(this);
|
||||||
|
m_sceneList.Add(scene);
|
||||||
|
|
||||||
|
scene.EventManager.OnNewClient += OnNewClient;
|
||||||
|
scene.EventManager.OnMakeRootAgent += OnMakeRootAgent;
|
||||||
|
scene.EventManager.OnMakeChildAgent += OnMakeChildAgent;
|
||||||
|
scene.EventManager.OnIncomingInstantMessage += OnGridInstantMessage;
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
if (!m_groupMessagingEnabled)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (m_debugEnabled) m_log.DebugFormat("[Groups.Messaging]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
|
||||||
|
|
||||||
|
m_groupData = scene.RequestModuleInterface<IGroupsServicesConnector>();
|
||||||
|
|
||||||
|
// No groups module, no groups messaging
|
||||||
|
if (m_groupData == null)
|
||||||
|
{
|
||||||
|
m_log.Error("[Groups.Messaging]: Could not get IGroupsServicesConnector, GroupsMessagingModule is now disabled.");
|
||||||
|
RemoveRegion(scene);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_msgTransferModule = scene.RequestModuleInterface<IMessageTransferModule>();
|
||||||
|
|
||||||
|
// No message transfer module, no groups messaging
|
||||||
|
if (m_msgTransferModule == null)
|
||||||
|
{
|
||||||
|
m_log.Error("[Groups.Messaging]: Could not get MessageTransferModule");
|
||||||
|
RemoveRegion(scene);
|
||||||
|
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)
|
||||||
|
m_presenceService = scene.PresenceService;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RemoveRegion(Scene scene)
|
||||||
|
{
|
||||||
|
if (!m_groupMessagingEnabled)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (m_debugEnabled) m_log.DebugFormat("[Groups.Messaging]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
|
||||||
|
|
||||||
|
m_sceneList.Remove(scene);
|
||||||
|
scene.EventManager.OnNewClient -= OnNewClient;
|
||||||
|
scene.EventManager.OnIncomingInstantMessage -= OnGridInstantMessage;
|
||||||
|
scene.EventManager.OnClientLogin -= OnClientLogin;
|
||||||
|
scene.UnregisterModuleInterface<IGroupsMessagingModule>(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Close()
|
||||||
|
{
|
||||||
|
if (!m_groupMessagingEnabled)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (m_debugEnabled) m_log.Debug("[Groups.Messaging]: Shutting down GroupsMessagingModule module.");
|
||||||
|
|
||||||
|
m_sceneList.Clear();
|
||||||
|
|
||||||
|
m_groupData = null;
|
||||||
|
m_msgTransferModule = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Type ReplaceableInterface
|
||||||
|
{
|
||||||
|
get { return null; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Name
|
||||||
|
{
|
||||||
|
get { return "Groups Messaging Module V2"; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public void PostInitialise()
|
||||||
|
{
|
||||||
|
// NoOp
|
||||||
|
}
|
||||||
|
|
||||||
|
#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>
|
||||||
|
/// Not really needed, but does confirm that the group exists.
|
||||||
|
/// </summary>
|
||||||
|
public bool StartGroupChatSession(UUID agentID, UUID groupID)
|
||||||
|
{
|
||||||
|
if (m_debugEnabled)
|
||||||
|
m_log.DebugFormat("[Groups.Messaging]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
|
||||||
|
|
||||||
|
GroupRecord groupInfo = m_groupData.GetGroupRecord(agentID.ToString(), groupID, null);
|
||||||
|
|
||||||
|
if (groupInfo != null)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SendMessageToGroup(GridInstantMessage im, UUID groupID)
|
||||||
|
{
|
||||||
|
SendMessageToGroup(im, groupID, UUID.Zero, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
PresenceInfo[] onlineAgents = null;
|
||||||
|
|
||||||
|
// In V2 we always only send to online members.
|
||||||
|
// 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);
|
||||||
|
m_usersOnlineCache.Add(groupID, onlineAgents, m_usersOnlineCacheExpirySeconds);
|
||||||
|
}
|
||||||
|
|
||||||
|
HashSet<string> onlineAgentsUuidSet = new HashSet<string>();
|
||||||
|
Array.ForEach<PresenceInfo>(onlineAgents, pi => onlineAgentsUuidSet.Add(pi.UserID));
|
||||||
|
|
||||||
|
groupMembers = groupMembers.Where(gmd => onlineAgentsUuidSet.Contains(gmd.AgentID.ToString())).ToList();
|
||||||
|
|
||||||
|
// if (m_debugEnabled)
|
||||||
|
// m_log.DebugFormat(
|
||||||
|
// "[Groups.Messaging]: SendMessageToGroup called for group {0} with {1} visible members, {2} online",
|
||||||
|
// groupID, groupMembersCount, groupMembers.Count());
|
||||||
|
|
||||||
|
im.imSessionID = groupID.Guid;
|
||||||
|
im.fromGroup = true;
|
||||||
|
IClientAPI thisClient = GetActiveClient(fromAgentID);
|
||||||
|
if (thisClient != null)
|
||||||
|
{
|
||||||
|
im.RegionID = thisClient.Scene.RegionInfo.RegionID.Guid;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((im.binaryBucket == null) || (im.binaryBucket.Length == 0) || ((im.binaryBucket.Length == 1 && im.binaryBucket[0] == 0)))
|
||||||
|
{
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
if (member.AgentID.Guid == im.fromAgentID)
|
||||||
|
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
|
||||||
|
if (m_debugEnabled)
|
||||||
|
m_log.DebugFormat("[Groups.Messaging]: {0} has dropped session, not delivering to them", member.AgentID);
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
im.toAgentID = member.AgentID.Guid;
|
||||||
|
|
||||||
|
IClientAPI client = GetActiveClient(member.AgentID);
|
||||||
|
if (client == null)
|
||||||
|
{
|
||||||
|
// 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);
|
||||||
|
|
||||||
|
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
|
||||||
|
{
|
||||||
|
// Deliver locally, directly
|
||||||
|
if (m_debugEnabled) m_log.DebugFormat("[Groups.Messaging]: Passing to ProcessMessageFromGroupSession to deliver to {0} locally", client.Name);
|
||||||
|
|
||||||
|
ProcessMessageFromGroupSession(im);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_debugEnabled)
|
||||||
|
m_log.DebugFormat(
|
||||||
|
"[Groups.Messaging]: SendMessageToGroup for group {0} with {1} visible members, {2} online took {3}ms",
|
||||||
|
groupID, groupMembersCount, groupMembers.Count(), Environment.TickCount - requestStartTick);
|
||||||
|
}
|
||||||
|
|
||||||
|
#region SimGridEventHandlers
|
||||||
|
|
||||||
|
void OnClientLogin(IClientAPI client)
|
||||||
|
{
|
||||||
|
if (m_debugEnabled) m_log.DebugFormat("[Groups.Messaging]: OnInstantMessage registered for {0}", client.Name);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnNewClient(IClientAPI client)
|
||||||
|
{
|
||||||
|
if (m_debugEnabled) m_log.DebugFormat("[Groups.Messaging]: OnInstantMessage registered for {0}", client.Name);
|
||||||
|
|
||||||
|
ResetAgentGroupChatSessions(client.AgentId.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
void OnMakeRootAgent(ScenePresence sp)
|
||||||
|
{
|
||||||
|
sp.ControllingClient.OnInstantMessage += OnInstantMessage;
|
||||||
|
}
|
||||||
|
|
||||||
|
void OnMakeChildAgent(ScenePresence sp)
|
||||||
|
{
|
||||||
|
sp.ControllingClient.OnInstantMessage -= OnInstantMessage;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void OnGridInstantMessage(GridInstantMessage msg)
|
||||||
|
{
|
||||||
|
// The instant message module will only deliver messages of dialog types:
|
||||||
|
// MessageFromAgent, StartTyping, StopTyping, MessageFromObject
|
||||||
|
//
|
||||||
|
// Any other message type will not be delivered to a client by the
|
||||||
|
// Instant Message Module
|
||||||
|
|
||||||
|
UUID regionID = new UUID(msg.RegionID);
|
||||||
|
if (m_debugEnabled)
|
||||||
|
{
|
||||||
|
m_log.DebugFormat("[Groups.Messaging]: {0} called, IM from region {1}",
|
||||||
|
System.Reflection.MethodBase.GetCurrentMethod().Name, regionID);
|
||||||
|
|
||||||
|
DebugGridInstantMessage(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Incoming message from a group
|
||||||
|
if ((msg.fromGroup == true) && (msg.dialog == (byte)InstantMessageDialog.SessionSend))
|
||||||
|
{
|
||||||
|
// We have to redistribute the message across all members of the group who are here
|
||||||
|
// 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ProcessMessageFromGroupSession(GridInstantMessage msg)
|
||||||
|
{
|
||||||
|
if (m_debugEnabled) m_log.DebugFormat("[Groups.Messaging]: Session message from {0} going to agent {1}", msg.fromAgentName, msg.toAgentID);
|
||||||
|
|
||||||
|
UUID AgentID = new UUID(msg.fromAgentID);
|
||||||
|
UUID GroupID = new UUID(msg.imSessionID);
|
||||||
|
UUID toAgentID = new UUID(msg.toAgentID);
|
||||||
|
|
||||||
|
switch (msg.dialog)
|
||||||
|
{
|
||||||
|
case (byte)InstantMessageDialog.SessionAdd:
|
||||||
|
AgentInvitedToGroupChatSession(AgentID.ToString(), GroupID);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case (byte)InstantMessageDialog.SessionDrop:
|
||||||
|
AgentDroppedFromGroupChatSession(AgentID.ToString(), GroupID);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case (byte)InstantMessageDialog.SessionSend:
|
||||||
|
// 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);
|
||||||
|
|
||||||
|
if (!hasAgentDroppedGroupChatSession(toAgentID.ToString(), GroupID))
|
||||||
|
{
|
||||||
|
if (!hasAgentBeenInvitedToGroupChatSession(toAgentID.ToString(), GroupID))
|
||||||
|
// This actually sends the message too, so no need to resend it
|
||||||
|
// with client.SendInstantMessage
|
||||||
|
AddAgentToSession(toAgentID, GroupID, msg);
|
||||||
|
else
|
||||||
|
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;
|
||||||
|
|
||||||
|
default:
|
||||||
|
m_log.WarnFormat("[Groups.Messaging]: I don't know how to proccess a {0} message.", ((InstantMessageDialog)msg.dialog).ToString());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
|
||||||
|
#region ClientEvents
|
||||||
|
private void OnInstantMessage(IClientAPI remoteClient, GridInstantMessage im)
|
||||||
|
{
|
||||||
|
if (m_debugEnabled)
|
||||||
|
{
|
||||||
|
m_log.DebugFormat("[Groups.Messaging]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
|
||||||
|
|
||||||
|
DebugGridInstantMessage(im);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start group IM session
|
||||||
|
if ((im.dialog == (byte)InstantMessageDialog.SessionGroupStart))
|
||||||
|
{
|
||||||
|
if (m_debugEnabled) m_log.InfoFormat("[Groups.Messaging]: imSessionID({0}) toAgentID({1})", im.imSessionID, im.toAgentID);
|
||||||
|
|
||||||
|
UUID GroupID = new UUID(im.imSessionID);
|
||||||
|
UUID AgentID = new UUID(im.fromAgentID);
|
||||||
|
|
||||||
|
GroupRecord groupInfo = m_groupData.GetGroupRecord(UUID.Zero.ToString(), GroupID, null);
|
||||||
|
|
||||||
|
if (groupInfo != null)
|
||||||
|
{
|
||||||
|
AgentInvitedToGroupChatSession(AgentID.ToString(), GroupID);
|
||||||
|
|
||||||
|
ChatterBoxSessionStartReplyViaCaps(remoteClient, groupInfo.GroupName, GroupID);
|
||||||
|
|
||||||
|
IEventQueue queue = remoteClient.Scene.RequestModuleInterface<IEventQueue>();
|
||||||
|
if (queue != null)
|
||||||
|
{
|
||||||
|
var update = new GroupChatListAgentUpdateData(AgentID);
|
||||||
|
var updates = new List<GroupChatListAgentUpdateData> { update };
|
||||||
|
queue.ChatterBoxSessionAgentListUpdates(GroupID, remoteClient.AgentId, updates);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send a message from locally connected client to a group
|
||||||
|
if ((im.dialog == (byte)InstantMessageDialog.SessionSend))
|
||||||
|
{
|
||||||
|
UUID GroupID = new UUID(im.imSessionID);
|
||||||
|
UUID AgentID = new UUID(im.fromAgentID);
|
||||||
|
|
||||||
|
if (m_debugEnabled)
|
||||||
|
m_log.DebugFormat("[Groups.Messaging]: Send message to session for group {0} with session ID {1}", GroupID, im.imSessionID.ToString());
|
||||||
|
|
||||||
|
//If this agent is sending a message, then they want to be in the session
|
||||||
|
AgentInvitedToGroupChatSession(AgentID.ToString(), GroupID);
|
||||||
|
|
||||||
|
SendMessageToGroup(im, GroupID);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
void ChatterBoxSessionStartReplyViaCaps(IClientAPI remoteClient, string groupName, UUID groupID)
|
||||||
|
{
|
||||||
|
if (m_debugEnabled) m_log.DebugFormat("[Groups.Messaging]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
|
||||||
|
|
||||||
|
OSDMap moderatedMap = new OSDMap(4);
|
||||||
|
moderatedMap.Add("voice", OSD.FromBoolean(false));
|
||||||
|
|
||||||
|
OSDMap sessionMap = new OSDMap(4);
|
||||||
|
sessionMap.Add("moderated_mode", moderatedMap);
|
||||||
|
sessionMap.Add("session_name", OSD.FromString(groupName));
|
||||||
|
sessionMap.Add("type", OSD.FromInteger(0));
|
||||||
|
sessionMap.Add("voice_enabled", OSD.FromBoolean(false));
|
||||||
|
|
||||||
|
OSDMap bodyMap = new OSDMap(4);
|
||||||
|
bodyMap.Add("session_id", OSD.FromUUID(groupID));
|
||||||
|
bodyMap.Add("temp_session_id", OSD.FromUUID(groupID));
|
||||||
|
bodyMap.Add("success", OSD.FromBoolean(true));
|
||||||
|
bodyMap.Add("session_info", sessionMap);
|
||||||
|
|
||||||
|
IEventQueue queue = remoteClient.Scene.RequestModuleInterface<IEventQueue>();
|
||||||
|
queue?.Enqueue(queue.BuildEvent("ChatterBoxSessionStartReply", bodyMap), remoteClient.AgentId);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void DebugGridInstantMessage(GridInstantMessage im)
|
||||||
|
{
|
||||||
|
// Don't log any normal IMs (privacy!)
|
||||||
|
if (m_debugEnabled && im.dialog != (byte)InstantMessageDialog.MessageFromAgent)
|
||||||
|
{
|
||||||
|
m_log.WarnFormat("[Groups.Messaging]: IM: fromGroup({0})", im.fromGroup ? "True" : "False");
|
||||||
|
m_log.WarnFormat("[Groups.Messaging]: IM: Dialog({0})", ((InstantMessageDialog)im.dialog).ToString());
|
||||||
|
m_log.WarnFormat("[Groups.Messaging]: IM: fromAgentID({0})", im.fromAgentID.ToString());
|
||||||
|
m_log.WarnFormat("[Groups.Messaging]: IM: fromAgentName({0})", im.fromAgentName.ToString());
|
||||||
|
m_log.WarnFormat("[Groups.Messaging]: IM: imSessionID({0})", im.imSessionID.ToString());
|
||||||
|
m_log.WarnFormat("[Groups.Messaging]: IM: message({0})", im.message.ToString());
|
||||||
|
m_log.WarnFormat("[Groups.Messaging]: IM: offline({0})", im.offline.ToString());
|
||||||
|
m_log.WarnFormat("[Groups.Messaging]: IM: toAgentID({0})", im.toAgentID.ToString());
|
||||||
|
m_log.WarnFormat("[Groups.Messaging]: IM: binaryBucket({0})", OpenMetaverse.Utils.BytesToHexString(im.binaryBucket, "BinaryBucket"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Client Tools
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Try to find an active IClientAPI reference for agentID giving preference to root connections
|
||||||
|
/// </summary>
|
||||||
|
private IClientAPI GetActiveClient(UUID agentID)
|
||||||
|
{
|
||||||
|
if (m_debugEnabled) m_log.WarnFormat("[Groups.Messaging]: Looking for local client {0}", agentID);
|
||||||
|
|
||||||
|
IClientAPI child = null;
|
||||||
|
|
||||||
|
// Try root avatar first
|
||||||
|
foreach (Scene scene in m_sceneList)
|
||||||
|
{
|
||||||
|
ScenePresence sp = scene.GetScenePresence(agentID);
|
||||||
|
if (sp != null)
|
||||||
|
{
|
||||||
|
if (!sp.IsChildAgent)
|
||||||
|
{
|
||||||
|
if (m_debugEnabled) m_log.DebugFormat("[Groups.Messaging]: Found root agent for client : {0}", sp.ControllingClient.Name);
|
||||||
|
return sp.ControllingClient;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (m_debugEnabled) m_log.DebugFormat("[Groups.Messaging]: Found child agent for client : {0}", sp.ControllingClient.Name);
|
||||||
|
child = sp.ControllingClient;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we didn't find a root, then just return whichever child we found, or null if none
|
||||||
|
if (child == null)
|
||||||
|
{
|
||||||
|
if (m_debugEnabled) m_log.WarnFormat("[Groups.Messaging]: Could not find local client for agent : {0}", agentID);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (m_debugEnabled) m_log.WarnFormat("[Groups.Messaging]: Returning child agent for client : {0}", child.Name);
|
||||||
|
}
|
||||||
|
return child;
|
||||||
|
}
|
||||||
|
|
||||||
|
#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
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,289 @@
|
||||||
|
/*
|
||||||
|
* 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.Reflection;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
using OpenSim.Framework;
|
||||||
|
using OpenSim.Server.Base;
|
||||||
|
|
||||||
|
using OpenMetaverse;
|
||||||
|
using log4net;
|
||||||
|
|
||||||
|
namespace OpenSim.Groups
|
||||||
|
{
|
||||||
|
public class GroupsServiceHGConnector
|
||||||
|
{
|
||||||
|
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
|
|
||||||
|
private string m_ServerURI;
|
||||||
|
private object m_Lock = new object();
|
||||||
|
|
||||||
|
public GroupsServiceHGConnector(string url)
|
||||||
|
{
|
||||||
|
m_ServerURI = url;
|
||||||
|
if (!m_ServerURI.EndsWith("/"))
|
||||||
|
m_ServerURI += "/";
|
||||||
|
|
||||||
|
m_log.DebugFormat("[Groups.HGConnector]: Groups server at {0}", m_ServerURI);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool CreateProxy(string RequestingAgentID, string AgentID, string accessToken, UUID groupID, string url, string name, out string reason)
|
||||||
|
{
|
||||||
|
reason = string.Empty;
|
||||||
|
|
||||||
|
Dictionary<string, object> sendData = new Dictionary<string,object>();
|
||||||
|
sendData["RequestingAgentID"] = RequestingAgentID;
|
||||||
|
sendData["AgentID"] = AgentID.ToString();
|
||||||
|
sendData["AccessToken"] = accessToken;
|
||||||
|
sendData["GroupID"] = groupID.ToString();
|
||||||
|
sendData["Location"] = url;
|
||||||
|
sendData["Name"] = name;
|
||||||
|
Dictionary<string, object> ret = MakeRequest("POSTGROUP", sendData);
|
||||||
|
|
||||||
|
if (ret == null)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!ret.ContainsKey("RESULT"))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (ret["RESULT"].ToString().ToLower() != "true")
|
||||||
|
{
|
||||||
|
reason = ret["REASON"].ToString();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RemoveAgentFromGroup(string AgentID, UUID GroupID, string token)
|
||||||
|
{
|
||||||
|
Dictionary<string, object> sendData = new Dictionary<string, object>();
|
||||||
|
sendData["AgentID"] = AgentID;
|
||||||
|
sendData["GroupID"] = GroupID.ToString();
|
||||||
|
sendData["AccessToken"] = GroupsDataUtils.Sanitize(token);
|
||||||
|
MakeRequest("REMOVEAGENTFROMGROUP", sendData);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ExtendedGroupRecord GetGroupRecord(string RequestingAgentID, UUID GroupID, string GroupName, string token)
|
||||||
|
{
|
||||||
|
if (GroupID == UUID.Zero && (GroupName == null || (GroupName != null && GroupName == string.Empty)))
|
||||||
|
return null;
|
||||||
|
|
||||||
|
Dictionary<string, object> sendData = new Dictionary<string, object>();
|
||||||
|
if (GroupID != UUID.Zero)
|
||||||
|
sendData["GroupID"] = GroupID.ToString();
|
||||||
|
if (!string.IsNullOrEmpty(GroupName))
|
||||||
|
sendData["Name"] = GroupsDataUtils.Sanitize(GroupName);
|
||||||
|
|
||||||
|
sendData["RequestingAgentID"] = RequestingAgentID;
|
||||||
|
sendData["AccessToken"] = GroupsDataUtils.Sanitize(token);
|
||||||
|
|
||||||
|
Dictionary<string, object> ret = MakeRequest("GETGROUP", sendData);
|
||||||
|
|
||||||
|
if (ret == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
if (!ret.ContainsKey("RESULT"))
|
||||||
|
return null;
|
||||||
|
|
||||||
|
if (ret["RESULT"].ToString() == "NULL")
|
||||||
|
return null;
|
||||||
|
|
||||||
|
return GroupsDataUtils.GroupRecord((Dictionary<string, object>)ret["RESULT"]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<ExtendedGroupMembersData> GetGroupMembers(string RequestingAgentID, UUID GroupID, string token)
|
||||||
|
{
|
||||||
|
List<ExtendedGroupMembersData> members = new List<ExtendedGroupMembersData>();
|
||||||
|
|
||||||
|
Dictionary<string, object> sendData = new Dictionary<string, object>();
|
||||||
|
sendData["GroupID"] = GroupID.ToString();
|
||||||
|
sendData["RequestingAgentID"] = RequestingAgentID;
|
||||||
|
sendData["AccessToken"] = GroupsDataUtils.Sanitize(token);
|
||||||
|
Dictionary<string, object> ret = MakeRequest("GETGROUPMEMBERS", sendData);
|
||||||
|
|
||||||
|
if (ret == null)
|
||||||
|
return members;
|
||||||
|
|
||||||
|
if (!ret.ContainsKey("RESULT"))
|
||||||
|
return members;
|
||||||
|
|
||||||
|
if (ret["RESULT"].ToString() == "NULL")
|
||||||
|
return members;
|
||||||
|
foreach (object v in ((Dictionary<string, object>)ret["RESULT"]).Values)
|
||||||
|
{
|
||||||
|
ExtendedGroupMembersData m = GroupsDataUtils.GroupMembersData((Dictionary<string, object>)v);
|
||||||
|
members.Add(m);
|
||||||
|
}
|
||||||
|
|
||||||
|
return members;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<GroupRolesData> GetGroupRoles(string RequestingAgentID, UUID GroupID, string token)
|
||||||
|
{
|
||||||
|
List<GroupRolesData> roles = new List<GroupRolesData>();
|
||||||
|
|
||||||
|
Dictionary<string, object> sendData = new Dictionary<string, object>();
|
||||||
|
sendData["GroupID"] = GroupID.ToString();
|
||||||
|
sendData["RequestingAgentID"] = RequestingAgentID;
|
||||||
|
sendData["AccessToken"] = GroupsDataUtils.Sanitize(token);
|
||||||
|
Dictionary<string, object> ret = MakeRequest("GETGROUPROLES", sendData);
|
||||||
|
|
||||||
|
if (ret == null)
|
||||||
|
return roles;
|
||||||
|
|
||||||
|
if (!ret.ContainsKey("RESULT"))
|
||||||
|
return roles;
|
||||||
|
|
||||||
|
if (ret["RESULT"].ToString() == "NULL")
|
||||||
|
return roles;
|
||||||
|
foreach (object v in ((Dictionary<string, object>)ret["RESULT"]).Values)
|
||||||
|
{
|
||||||
|
GroupRolesData m = GroupsDataUtils.GroupRolesData((Dictionary<string, object>)v);
|
||||||
|
roles.Add(m);
|
||||||
|
}
|
||||||
|
|
||||||
|
return roles;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<ExtendedGroupRoleMembersData> GetGroupRoleMembers(string RequestingAgentID, UUID GroupID, string token)
|
||||||
|
{
|
||||||
|
List<ExtendedGroupRoleMembersData> rmembers = new List<ExtendedGroupRoleMembersData>();
|
||||||
|
|
||||||
|
Dictionary<string, object> sendData = new Dictionary<string, object>();
|
||||||
|
sendData["GroupID"] = GroupID.ToString();
|
||||||
|
sendData["RequestingAgentID"] = RequestingAgentID;
|
||||||
|
sendData["AccessToken"] = GroupsDataUtils.Sanitize(token);
|
||||||
|
Dictionary<string, object> ret = MakeRequest("GETROLEMEMBERS", sendData);
|
||||||
|
|
||||||
|
if (ret == null)
|
||||||
|
return rmembers;
|
||||||
|
|
||||||
|
if (!ret.ContainsKey("RESULT"))
|
||||||
|
return rmembers;
|
||||||
|
|
||||||
|
if (ret["RESULT"].ToString() == "NULL")
|
||||||
|
return rmembers;
|
||||||
|
|
||||||
|
foreach (object v in ((Dictionary<string, object>)ret["RESULT"]).Values)
|
||||||
|
{
|
||||||
|
ExtendedGroupRoleMembersData m = GroupsDataUtils.GroupRoleMembersData((Dictionary<string, object>)v);
|
||||||
|
rmembers.Add(m);
|
||||||
|
}
|
||||||
|
|
||||||
|
return rmembers;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool AddNotice(string RequestingAgentID, UUID groupID, UUID noticeID, string fromName, string subject, string message,
|
||||||
|
bool hasAttachment, byte attType, string attName, UUID attItemID, string attOwnerID)
|
||||||
|
{
|
||||||
|
Dictionary<string, object> sendData = new Dictionary<string, object>();
|
||||||
|
sendData["GroupID"] = groupID.ToString();
|
||||||
|
sendData["NoticeID"] = noticeID.ToString();
|
||||||
|
sendData["FromName"] = GroupsDataUtils.Sanitize(fromName);
|
||||||
|
sendData["Subject"] = GroupsDataUtils.Sanitize(subject);
|
||||||
|
sendData["Message"] = GroupsDataUtils.Sanitize(message);
|
||||||
|
sendData["HasAttachment"] = hasAttachment.ToString();
|
||||||
|
if (hasAttachment)
|
||||||
|
{
|
||||||
|
sendData["AttachmentType"] = attType.ToString();
|
||||||
|
sendData["AttachmentName"] = attName.ToString();
|
||||||
|
sendData["AttachmentItemID"] = attItemID.ToString();
|
||||||
|
sendData["AttachmentOwnerID"] = attOwnerID;
|
||||||
|
}
|
||||||
|
sendData["RequestingAgentID"] = RequestingAgentID;
|
||||||
|
|
||||||
|
Dictionary<string, object> ret = MakeRequest("ADDNOTICE", sendData);
|
||||||
|
|
||||||
|
if (ret == null)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!ret.ContainsKey("RESULT"))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (ret["RESULT"].ToString().ToLower() != "true")
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool VerifyNotice(UUID noticeID, UUID groupID)
|
||||||
|
{
|
||||||
|
Dictionary<string, object> sendData = new Dictionary<string, object>();
|
||||||
|
sendData["NoticeID"] = noticeID.ToString();
|
||||||
|
sendData["GroupID"] = groupID.ToString();
|
||||||
|
Dictionary<string, object> ret = MakeRequest("VERIFYNOTICE", sendData);
|
||||||
|
|
||||||
|
if (ret == null)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!ret.ContainsKey("RESULT"))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (ret["RESULT"].ToString().ToLower() != "true")
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
|
||||||
|
#region Make Request
|
||||||
|
|
||||||
|
private Dictionary<string, object> MakeRequest(string method, Dictionary<string, object> sendData)
|
||||||
|
{
|
||||||
|
sendData["METHOD"] = method;
|
||||||
|
|
||||||
|
string reply = string.Empty;
|
||||||
|
lock (m_Lock)
|
||||||
|
reply = SynchronousRestFormsRequester.MakeRequest("POST",
|
||||||
|
m_ServerURI + "hg-groups",
|
||||||
|
ServerUtils.BuildQueryString(sendData));
|
||||||
|
|
||||||
|
//m_log.DebugFormat("[XXX]: reply was {0}", reply);
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(reply))
|
||||||
|
return null;
|
||||||
|
|
||||||
|
Dictionary<string, object> replyData = ServerUtils.ParseXmlResponse(
|
||||||
|
reply);
|
||||||
|
|
||||||
|
return replyData;
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,695 @@
|
||||||
|
/*
|
||||||
|
* 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.Reflection;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
using OpenSim.Framework;
|
||||||
|
using OpenSim.Framework.Monitoring;
|
||||||
|
using OpenSim.Framework.Servers;
|
||||||
|
using OpenSim.Region.Framework.Scenes;
|
||||||
|
using OpenSim.Region.Framework.Interfaces;
|
||||||
|
using OpenSim.Services.Interfaces;
|
||||||
|
|
||||||
|
using OpenMetaverse;
|
||||||
|
using Mono.Addins;
|
||||||
|
using log4net;
|
||||||
|
using Nini.Config;
|
||||||
|
|
||||||
|
namespace OpenSim.Groups
|
||||||
|
{
|
||||||
|
[Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "GroupsServiceHGConnectorModule")]
|
||||||
|
public class GroupsServiceHGConnectorModule : ISharedRegionModule, IGroupsServicesConnector
|
||||||
|
{
|
||||||
|
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
|
|
||||||
|
private bool m_Enabled = false;
|
||||||
|
private IGroupsServicesConnector m_LocalGroupsConnector;
|
||||||
|
private string m_LocalGroupsServiceLocation;
|
||||||
|
private IUserManagement m_UserManagement;
|
||||||
|
private IOfflineIMService m_OfflineIM;
|
||||||
|
private IMessageTransferModule m_Messaging;
|
||||||
|
private List<Scene> m_Scenes;
|
||||||
|
private ForeignImporter m_ForeignImporter;
|
||||||
|
private string m_ServiceLocation;
|
||||||
|
private IConfigSource m_Config;
|
||||||
|
|
||||||
|
private Dictionary<string, GroupsServiceHGConnector> m_NetworkConnectors = new Dictionary<string, GroupsServiceHGConnector>();
|
||||||
|
private RemoteConnectorCacheWrapper m_CacheWrapper; // for caching info of external group services
|
||||||
|
|
||||||
|
#region ISharedRegionModule
|
||||||
|
|
||||||
|
public void Initialise(IConfigSource config)
|
||||||
|
{
|
||||||
|
IConfig groupsConfig = config.Configs["Groups"];
|
||||||
|
if (groupsConfig == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if ((groupsConfig.GetBoolean("Enabled", false) == false)
|
||||||
|
|| (groupsConfig.GetString("ServicesConnectorModule", string.Empty) != Name))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_Config = config;
|
||||||
|
m_ServiceLocation = groupsConfig.GetString("LocalService", "local"); // local or remote
|
||||||
|
m_LocalGroupsServiceLocation = groupsConfig.GetString("GroupsExternalURI", "http://127.0.0.1");
|
||||||
|
m_Scenes = new List<Scene>();
|
||||||
|
|
||||||
|
m_Enabled = true;
|
||||||
|
|
||||||
|
m_log.DebugFormat("[Groups]: Initializing {0} with LocalService {1}", this.Name, m_ServiceLocation);
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Name
|
||||||
|
{
|
||||||
|
get { return "Groups HG Service Connector"; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public Type ReplaceableInterface
|
||||||
|
{
|
||||||
|
get { return null; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddRegion(Scene scene)
|
||||||
|
{
|
||||||
|
if (!m_Enabled)
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_log.DebugFormat("[Groups]: Registering {0} with {1}", this.Name, scene.RegionInfo.RegionName);
|
||||||
|
scene.RegisterModuleInterface<IGroupsServicesConnector>(this);
|
||||||
|
m_Scenes.Add(scene);
|
||||||
|
|
||||||
|
scene.EventManager.OnNewClient += OnNewClient;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RemoveRegion(Scene scene)
|
||||||
|
{
|
||||||
|
if (!m_Enabled)
|
||||||
|
return;
|
||||||
|
|
||||||
|
scene.UnregisterModuleInterface<IGroupsServicesConnector>(this);
|
||||||
|
m_Scenes.Remove(scene);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RegionLoaded(Scene scene)
|
||||||
|
{
|
||||||
|
if (!m_Enabled)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (m_UserManagement == null)
|
||||||
|
{
|
||||||
|
m_UserManagement = scene.RequestModuleInterface<IUserManagement>();
|
||||||
|
m_OfflineIM = scene.RequestModuleInterface<IOfflineIMService>();
|
||||||
|
m_Messaging = scene.RequestModuleInterface<IMessageTransferModule>();
|
||||||
|
m_ForeignImporter = new ForeignImporter(m_UserManagement);
|
||||||
|
|
||||||
|
if (m_ServiceLocation.Equals("local"))
|
||||||
|
{
|
||||||
|
m_LocalGroupsConnector = new GroupsServiceLocalConnectorModule(m_Config, m_UserManagement);
|
||||||
|
// Also, if local, create the endpoint for the HGGroupsService
|
||||||
|
new HGGroupsServiceRobustConnector(m_Config, MainServer.Instance, string.Empty,
|
||||||
|
scene.RequestModuleInterface<IOfflineIMService>(), scene.RequestModuleInterface<IUserAccountService>());
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
m_LocalGroupsConnector = new GroupsServiceRemoteConnectorModule(m_Config, m_UserManagement);
|
||||||
|
|
||||||
|
m_CacheWrapper = new RemoteConnectorCacheWrapper(m_UserManagement);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void PostInitialise()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Close()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
private void OnNewClient(IClientAPI client)
|
||||||
|
{
|
||||||
|
client.OnCompleteMovementToRegion += OnCompleteMovementToRegion;
|
||||||
|
}
|
||||||
|
|
||||||
|
void OnCompleteMovementToRegion(IClientAPI client, bool arg2)
|
||||||
|
{
|
||||||
|
object sp = null;
|
||||||
|
if (client.Scene.TryGetScenePresence(client.AgentId, out sp))
|
||||||
|
{
|
||||||
|
if (sp is ScenePresence && ((ScenePresence)sp).PresenceType != PresenceType.Npc)
|
||||||
|
{
|
||||||
|
AgentCircuitData aCircuit = ((ScenePresence)sp).Scene.AuthenticateHandler.GetAgentCircuitData(client.AgentId);
|
||||||
|
if (aCircuit != null && (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaHGLogin) != 0 &&
|
||||||
|
m_OfflineIM != null && m_Messaging != null)
|
||||||
|
{
|
||||||
|
List<GridInstantMessage> ims = m_OfflineIM.GetMessages(aCircuit.AgentID);
|
||||||
|
if (ims != null && ims.Count > 0)
|
||||||
|
foreach (GridInstantMessage im in ims)
|
||||||
|
m_Messaging.SendInstantMessage(im, delegate(bool success) { });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#region IGroupsServicesConnector
|
||||||
|
|
||||||
|
public UUID CreateGroup(UUID RequestingAgentID, string name, string charter, bool showInList, UUID insigniaID, int membershipFee, bool openEnrollment,
|
||||||
|
bool allowPublish, bool maturePublish, UUID founderID, out string reason)
|
||||||
|
{
|
||||||
|
reason = string.Empty;
|
||||||
|
if (m_UserManagement.IsLocalGridUser(RequestingAgentID))
|
||||||
|
return m_LocalGroupsConnector.CreateGroup(RequestingAgentID, name, charter, showInList, insigniaID,
|
||||||
|
membershipFee, openEnrollment, allowPublish, maturePublish, founderID, out reason);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
reason = "Only local grid users are allowed to create a new group";
|
||||||
|
return UUID.Zero;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool UpdateGroup(string RequestingAgentID, UUID groupID, string charter, bool showInList, UUID insigniaID, int membershipFee,
|
||||||
|
bool openEnrollment, bool allowPublish, bool maturePublish, out string reason)
|
||||||
|
{
|
||||||
|
reason = string.Empty;
|
||||||
|
string url = string.Empty;
|
||||||
|
string name = string.Empty;
|
||||||
|
if (IsLocal(groupID, out url, out name))
|
||||||
|
return m_LocalGroupsConnector.UpdateGroup(AgentUUI(RequestingAgentID), groupID, charter, showInList, insigniaID, membershipFee,
|
||||||
|
openEnrollment, allowPublish, maturePublish, out reason);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
reason = "Changes to remote group not allowed. Please go to the group's original world.";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public ExtendedGroupRecord GetGroupRecord(string RequestingAgentID, UUID GroupID, string GroupName)
|
||||||
|
{
|
||||||
|
string url = string.Empty;
|
||||||
|
string name = string.Empty;
|
||||||
|
if (IsLocal(GroupID, out url, out name))
|
||||||
|
return m_LocalGroupsConnector.GetGroupRecord(AgentUUI(RequestingAgentID), GroupID, GroupName);
|
||||||
|
else if (url != string.Empty)
|
||||||
|
{
|
||||||
|
ExtendedGroupMembershipData membership = m_LocalGroupsConnector.GetAgentGroupMembership(RequestingAgentID, RequestingAgentID, GroupID);
|
||||||
|
string accessToken = string.Empty;
|
||||||
|
if (membership != null)
|
||||||
|
accessToken = membership.AccessToken;
|
||||||
|
else
|
||||||
|
return null;
|
||||||
|
|
||||||
|
GroupsServiceHGConnector c = GetConnector(url);
|
||||||
|
if (c != null)
|
||||||
|
{
|
||||||
|
ExtendedGroupRecord grec = m_CacheWrapper.GetGroupRecord(RequestingAgentID, GroupID, GroupName, delegate
|
||||||
|
{
|
||||||
|
return c.GetGroupRecord(AgentUUIForOutside(RequestingAgentID), GroupID, GroupName, accessToken);
|
||||||
|
});
|
||||||
|
|
||||||
|
if (grec != null)
|
||||||
|
ImportForeigner(grec.FounderUUI);
|
||||||
|
return grec;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<DirGroupsReplyData> FindGroups(string RequestingAgentIDstr, string search)
|
||||||
|
{
|
||||||
|
return m_LocalGroupsConnector.FindGroups(RequestingAgentIDstr, search);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<GroupMembersData> GetGroupMembers(string RequestingAgentID, UUID GroupID)
|
||||||
|
{
|
||||||
|
string url = string.Empty, gname = string.Empty;
|
||||||
|
if (IsLocal(GroupID, out url, out gname))
|
||||||
|
{
|
||||||
|
string agentID = AgentUUI(RequestingAgentID);
|
||||||
|
return m_LocalGroupsConnector.GetGroupMembers(agentID, GroupID);
|
||||||
|
}
|
||||||
|
else if (!string.IsNullOrEmpty(url))
|
||||||
|
{
|
||||||
|
ExtendedGroupMembershipData membership = m_LocalGroupsConnector.GetAgentGroupMembership(RequestingAgentID, RequestingAgentID, GroupID);
|
||||||
|
string accessToken = string.Empty;
|
||||||
|
if (membership != null)
|
||||||
|
accessToken = membership.AccessToken;
|
||||||
|
else
|
||||||
|
return null;
|
||||||
|
|
||||||
|
GroupsServiceHGConnector c = GetConnector(url);
|
||||||
|
if (c != null)
|
||||||
|
{
|
||||||
|
return m_CacheWrapper.GetGroupMembers(RequestingAgentID, GroupID, delegate
|
||||||
|
{
|
||||||
|
return c.GetGroupMembers(AgentUUIForOutside(RequestingAgentID), GroupID, accessToken);
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return new List<GroupMembersData>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool AddGroupRole(string RequestingAgentID, UUID groupID, UUID roleID, string name, string description, string title, ulong powers, out string reason)
|
||||||
|
{
|
||||||
|
reason = string.Empty;
|
||||||
|
string url = string.Empty, gname = string.Empty;
|
||||||
|
|
||||||
|
if (IsLocal(groupID, out url, out gname))
|
||||||
|
return m_LocalGroupsConnector.AddGroupRole(AgentUUI(RequestingAgentID), groupID, roleID, name, description, title, powers, out reason);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
reason = "Operation not allowed outside this group's origin world.";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool UpdateGroupRole(string RequestingAgentID, UUID groupID, UUID roleID, string name, string description, string title, ulong powers)
|
||||||
|
{
|
||||||
|
string url = string.Empty, gname = string.Empty;
|
||||||
|
|
||||||
|
if (IsLocal(groupID, out url, out gname))
|
||||||
|
return m_LocalGroupsConnector.UpdateGroupRole(AgentUUI(RequestingAgentID), groupID, roleID, name, description, title, powers);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RemoveGroupRole(string RequestingAgentID, UUID groupID, UUID roleID)
|
||||||
|
{
|
||||||
|
string url = string.Empty, gname = string.Empty;
|
||||||
|
|
||||||
|
if (IsLocal(groupID, out url, out gname))
|
||||||
|
m_LocalGroupsConnector.RemoveGroupRole(AgentUUI(RequestingAgentID), groupID, roleID);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<GroupRolesData> GetGroupRoles(string RequestingAgentID, UUID groupID)
|
||||||
|
{
|
||||||
|
string url = string.Empty, gname = string.Empty;
|
||||||
|
|
||||||
|
if (IsLocal(groupID, out url, out gname))
|
||||||
|
return m_LocalGroupsConnector.GetGroupRoles(AgentUUI(RequestingAgentID), groupID);
|
||||||
|
else if (!string.IsNullOrEmpty(url))
|
||||||
|
{
|
||||||
|
ExtendedGroupMembershipData membership = m_LocalGroupsConnector.GetAgentGroupMembership(RequestingAgentID, RequestingAgentID, groupID);
|
||||||
|
string accessToken = string.Empty;
|
||||||
|
if (membership != null)
|
||||||
|
accessToken = membership.AccessToken;
|
||||||
|
else
|
||||||
|
return null;
|
||||||
|
|
||||||
|
GroupsServiceHGConnector c = GetConnector(url);
|
||||||
|
if (c != null)
|
||||||
|
{
|
||||||
|
return m_CacheWrapper.GetGroupRoles(RequestingAgentID, groupID, delegate
|
||||||
|
{
|
||||||
|
return c.GetGroupRoles(AgentUUIForOutside(RequestingAgentID), groupID, accessToken);
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return new List<GroupRolesData>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<GroupRoleMembersData> GetGroupRoleMembers(string RequestingAgentID, UUID groupID)
|
||||||
|
{
|
||||||
|
string url = string.Empty, gname = string.Empty;
|
||||||
|
|
||||||
|
if (IsLocal(groupID, out url, out gname))
|
||||||
|
return m_LocalGroupsConnector.GetGroupRoleMembers(AgentUUI(RequestingAgentID), groupID);
|
||||||
|
else if (!string.IsNullOrEmpty(url))
|
||||||
|
{
|
||||||
|
ExtendedGroupMembershipData membership = m_LocalGroupsConnector.GetAgentGroupMembership(RequestingAgentID, RequestingAgentID, groupID);
|
||||||
|
string accessToken = string.Empty;
|
||||||
|
if (membership != null)
|
||||||
|
accessToken = membership.AccessToken;
|
||||||
|
else
|
||||||
|
return null;
|
||||||
|
|
||||||
|
GroupsServiceHGConnector c = GetConnector(url);
|
||||||
|
if (c != null)
|
||||||
|
{
|
||||||
|
return m_CacheWrapper.GetGroupRoleMembers(RequestingAgentID, groupID, delegate
|
||||||
|
{
|
||||||
|
return c.GetGroupRoleMembers(AgentUUIForOutside(RequestingAgentID), groupID, accessToken);
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return new List<GroupRoleMembersData>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool AddAgentToGroup(string RequestingAgentID, string AgentID, UUID GroupID, UUID RoleID, string token, out string reason)
|
||||||
|
{
|
||||||
|
string url = string.Empty;
|
||||||
|
string name = string.Empty;
|
||||||
|
reason = string.Empty;
|
||||||
|
|
||||||
|
UUID uid = new UUID(AgentID);
|
||||||
|
if (IsLocal(GroupID, out url, out name))
|
||||||
|
{
|
||||||
|
if (m_UserManagement.IsLocalGridUser(uid)) // local user
|
||||||
|
{
|
||||||
|
// normal case: local group, local user
|
||||||
|
return m_LocalGroupsConnector.AddAgentToGroup(AgentUUI(RequestingAgentID), AgentUUI(AgentID), GroupID, RoleID, token, out reason);
|
||||||
|
}
|
||||||
|
else // local group, foreign user
|
||||||
|
{
|
||||||
|
// the user is accepting the invitation, or joining, where the group resides
|
||||||
|
token = UUID.Random().ToString();
|
||||||
|
bool success = m_LocalGroupsConnector.AddAgentToGroup(AgentUUI(RequestingAgentID), AgentUUI(AgentID), GroupID, RoleID, token, out reason);
|
||||||
|
|
||||||
|
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");
|
||||||
|
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.";
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
GroupsServiceHGConnector c = GetConnector(url);
|
||||||
|
if (c != null)
|
||||||
|
c.CreateProxy(AgentUUI(RequestingAgentID), AgentID, token, GroupID, m_LocalGroupsServiceLocation, name, out reason);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (m_UserManagement.IsLocalGridUser(uid)) // local user
|
||||||
|
{
|
||||||
|
// foreign group, local user. She's been added already by the HG service.
|
||||||
|
// Let's just check
|
||||||
|
if (m_LocalGroupsConnector.GetAgentGroupMembership(AgentUUI(RequestingAgentID), AgentUUI(AgentID), GroupID) != null)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
reason = "Operation not allowed outside this group's origin world";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void RemoveAgentFromGroup(string RequestingAgentID, string AgentID, UUID GroupID)
|
||||||
|
{
|
||||||
|
string url = string.Empty, name = string.Empty;
|
||||||
|
if (!IsLocal(GroupID, out url, out name) && url != string.Empty)
|
||||||
|
{
|
||||||
|
ExtendedGroupMembershipData membership = m_LocalGroupsConnector.GetAgentGroupMembership(AgentUUI(RequestingAgentID), AgentUUI(AgentID), GroupID);
|
||||||
|
if (membership != null)
|
||||||
|
{
|
||||||
|
GroupsServiceHGConnector c = GetConnector(url);
|
||||||
|
if (c != null)
|
||||||
|
c.RemoveAgentFromGroup(AgentUUIForOutside(AgentID), GroupID, membership.AccessToken);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// remove from local service
|
||||||
|
m_LocalGroupsConnector.RemoveAgentFromGroup(AgentUUI(RequestingAgentID), AgentUUI(AgentID), GroupID);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool AddAgentToGroupInvite(string RequestingAgentID, UUID inviteID, UUID groupID, UUID roleID, string agentID)
|
||||||
|
{
|
||||||
|
string url = string.Empty, gname = string.Empty;
|
||||||
|
|
||||||
|
if (IsLocal(groupID, out url, out gname))
|
||||||
|
return m_LocalGroupsConnector.AddAgentToGroupInvite(AgentUUI(RequestingAgentID), inviteID, groupID, roleID, AgentUUI(agentID));
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public GroupInviteInfo GetAgentToGroupInvite(string RequestingAgentID, UUID inviteID)
|
||||||
|
{
|
||||||
|
return m_LocalGroupsConnector.GetAgentToGroupInvite(AgentUUI(RequestingAgentID), inviteID); ;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RemoveAgentToGroupInvite(string RequestingAgentID, UUID inviteID)
|
||||||
|
{
|
||||||
|
m_LocalGroupsConnector.RemoveAgentToGroupInvite(AgentUUI(RequestingAgentID), inviteID);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddAgentToGroupRole(string RequestingAgentID, string AgentID, UUID GroupID, UUID RoleID)
|
||||||
|
{
|
||||||
|
string url = string.Empty, gname = string.Empty;
|
||||||
|
|
||||||
|
if (IsLocal(GroupID, out url, out gname))
|
||||||
|
m_LocalGroupsConnector.AddAgentToGroupRole(AgentUUI(RequestingAgentID), AgentUUI(AgentID), GroupID, RoleID);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RemoveAgentFromGroupRole(string RequestingAgentID, string AgentID, UUID GroupID, UUID RoleID)
|
||||||
|
{
|
||||||
|
string url = string.Empty, gname = string.Empty;
|
||||||
|
|
||||||
|
if (IsLocal(GroupID, out url, out gname))
|
||||||
|
m_LocalGroupsConnector.RemoveAgentFromGroupRole(AgentUUI(RequestingAgentID), AgentUUI(AgentID), GroupID, RoleID);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<GroupRolesData> GetAgentGroupRoles(string RequestingAgentID, string AgentID, UUID GroupID)
|
||||||
|
{
|
||||||
|
string url = string.Empty, gname = string.Empty;
|
||||||
|
|
||||||
|
if (IsLocal(GroupID, out url, out gname))
|
||||||
|
return m_LocalGroupsConnector.GetAgentGroupRoles(AgentUUI(RequestingAgentID), AgentUUI(AgentID), GroupID);
|
||||||
|
else
|
||||||
|
return new List<GroupRolesData>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetAgentActiveGroup(string RequestingAgentID, string AgentID, UUID GroupID)
|
||||||
|
{
|
||||||
|
string url = string.Empty, gname = string.Empty;
|
||||||
|
|
||||||
|
if (IsLocal(GroupID, out url, out gname))
|
||||||
|
m_LocalGroupsConnector.SetAgentActiveGroup(AgentUUI(RequestingAgentID), AgentUUI(AgentID), GroupID);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ExtendedGroupMembershipData GetAgentActiveMembership(string RequestingAgentID, string AgentID)
|
||||||
|
{
|
||||||
|
return m_LocalGroupsConnector.GetAgentActiveMembership(AgentUUI(RequestingAgentID), AgentUUI(AgentID));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetAgentActiveGroupRole(string RequestingAgentID, string AgentID, UUID GroupID, UUID RoleID)
|
||||||
|
{
|
||||||
|
string url = string.Empty, gname = string.Empty;
|
||||||
|
|
||||||
|
if (IsLocal(GroupID, out url, out gname))
|
||||||
|
m_LocalGroupsConnector.SetAgentActiveGroupRole(AgentUUI(RequestingAgentID), AgentUUI(AgentID), GroupID, RoleID);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void UpdateMembership(string RequestingAgentID, string AgentID, UUID GroupID, bool AcceptNotices, bool ListInProfile)
|
||||||
|
{
|
||||||
|
m_LocalGroupsConnector.UpdateMembership(AgentUUI(RequestingAgentID), AgentUUI(AgentID), GroupID, AcceptNotices, ListInProfile);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ExtendedGroupMembershipData GetAgentGroupMembership(string RequestingAgentID, string AgentID, UUID GroupID)
|
||||||
|
{
|
||||||
|
string url = string.Empty, gname = string.Empty;
|
||||||
|
|
||||||
|
if (IsLocal(GroupID, out url, out gname))
|
||||||
|
return m_LocalGroupsConnector.GetAgentGroupMembership(AgentUUI(RequestingAgentID), AgentUUI(AgentID), GroupID);
|
||||||
|
else
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<GroupMembershipData> GetAgentGroupMemberships(string RequestingAgentID, string AgentID)
|
||||||
|
{
|
||||||
|
return m_LocalGroupsConnector.GetAgentGroupMemberships(AgentUUI(RequestingAgentID), AgentUUI(AgentID));
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
string url = string.Empty, gname = string.Empty;
|
||||||
|
|
||||||
|
if (IsLocal(groupID, out url, out gname))
|
||||||
|
{
|
||||||
|
if (m_LocalGroupsConnector.AddGroupNotice(AgentUUI(RequestingAgentID), groupID, noticeID, fromName, subject, message,
|
||||||
|
hasAttachment, attType, attName, attItemID, AgentUUI(attOwnerID)))
|
||||||
|
{
|
||||||
|
// then send the notice to every grid for which there are members in this group
|
||||||
|
List<GroupMembersData> members = m_LocalGroupsConnector.GetGroupMembers(AgentUUI(RequestingAgentID), groupID);
|
||||||
|
List<string> urls = new List<string>();
|
||||||
|
foreach (GroupMembersData m in members)
|
||||||
|
{
|
||||||
|
if (!m_UserManagement.IsLocalGridUser(m.AgentID))
|
||||||
|
{
|
||||||
|
string gURL = m_UserManagement.GetUserServerURL(m.AgentID, "GroupsServerURI");
|
||||||
|
if (!urls.Contains(gURL))
|
||||||
|
urls.Add(gURL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// so we have the list of urls to send the notice to
|
||||||
|
// this may take a long time...
|
||||||
|
WorkManager.RunInThread(delegate
|
||||||
|
{
|
||||||
|
foreach (string u in urls)
|
||||||
|
{
|
||||||
|
GroupsServiceHGConnector c = GetConnector(u);
|
||||||
|
if (c != null)
|
||||||
|
{
|
||||||
|
c.AddNotice(AgentUUIForOutside(RequestingAgentID), groupID, noticeID, fromName, subject, message,
|
||||||
|
hasAttachment, attType, attName, attItemID, AgentUUIForOutside(attOwnerID));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, null, string.Format("AddGroupNotice (agent {0}, group {1})", RequestingAgentID, groupID));
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public GroupNoticeInfo GetGroupNotice(string RequestingAgentID, UUID noticeID)
|
||||||
|
{
|
||||||
|
GroupNoticeInfo notice = m_LocalGroupsConnector.GetGroupNotice(AgentUUI(RequestingAgentID), noticeID);
|
||||||
|
|
||||||
|
if (notice != null && notice.noticeData.HasAttachment && notice.noticeData.AttachmentOwnerID != null)
|
||||||
|
ImportForeigner(notice.noticeData.AttachmentOwnerID);
|
||||||
|
|
||||||
|
return notice;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<ExtendedGroupNoticeData> GetGroupNotices(string RequestingAgentID, UUID GroupID)
|
||||||
|
{
|
||||||
|
return m_LocalGroupsConnector.GetGroupNotices(AgentUUI(RequestingAgentID), GroupID);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region hypergrid groups
|
||||||
|
|
||||||
|
private string AgentUUI(string AgentIDStr)
|
||||||
|
{
|
||||||
|
UUID AgentID = UUID.Zero;
|
||||||
|
if (!UUID.TryParse(AgentIDStr, out AgentID) || AgentID == UUID.Zero)
|
||||||
|
return UUID.Zero.ToString();
|
||||||
|
|
||||||
|
if (m_UserManagement.IsLocalGridUser(AgentID))
|
||||||
|
return AgentID.ToString();
|
||||||
|
|
||||||
|
AgentCircuitData agent = null;
|
||||||
|
foreach (Scene scene in m_Scenes)
|
||||||
|
{
|
||||||
|
agent = scene.AuthenticateHandler.GetAgentCircuitData(AgentID);
|
||||||
|
if (agent != null)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (agent != null)
|
||||||
|
return Util.ProduceUserUniversalIdentifier(agent);
|
||||||
|
|
||||||
|
// we don't know anything about this foreign user
|
||||||
|
// try asking the user management module, which may know more
|
||||||
|
return m_UserManagement.GetUserUUI(AgentID);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private string AgentUUIForOutside(string AgentIDStr)
|
||||||
|
{
|
||||||
|
UUID AgentID = UUID.Zero;
|
||||||
|
if (!UUID.TryParse(AgentIDStr, out AgentID) || AgentID == UUID.Zero)
|
||||||
|
return UUID.Zero.ToString();
|
||||||
|
|
||||||
|
AgentCircuitData agent = null;
|
||||||
|
foreach (Scene scene in m_Scenes)
|
||||||
|
{
|
||||||
|
agent = scene.AuthenticateHandler.GetAgentCircuitData(AgentID);
|
||||||
|
if (agent != null)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (agent == null) // oops
|
||||||
|
return AgentID.ToString();
|
||||||
|
|
||||||
|
return Util.ProduceUserUniversalIdentifier(agent);
|
||||||
|
}
|
||||||
|
|
||||||
|
private UUID ImportForeigner(string uID)
|
||||||
|
{
|
||||||
|
UUID userID = UUID.Zero;
|
||||||
|
string url = string.Empty, first = string.Empty, last = string.Empty, tmp = string.Empty;
|
||||||
|
if (Util.ParseUniversalUserIdentifier(uID, out userID, out url, out first, out last, out tmp))
|
||||||
|
m_UserManagement.AddUser(userID, first, last, url);
|
||||||
|
|
||||||
|
return userID;
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool IsLocal(UUID groupID, out string serviceLocation, out string name)
|
||||||
|
{
|
||||||
|
serviceLocation = string.Empty;
|
||||||
|
name = string.Empty;
|
||||||
|
if (groupID.Equals(UUID.Zero))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
ExtendedGroupRecord group = m_LocalGroupsConnector.GetGroupRecord(UUID.Zero.ToString(), groupID, string.Empty);
|
||||||
|
if (group == null)
|
||||||
|
{
|
||||||
|
//m_log.DebugFormat("[XXX]: IsLocal? group {0} not found -- no.", groupID);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
serviceLocation = group.ServiceLocation;
|
||||||
|
name = group.GroupName;
|
||||||
|
bool isLocal = (group.ServiceLocation == string.Empty);
|
||||||
|
//m_log.DebugFormat("[XXX]: IsLocal? {0}", isLocal);
|
||||||
|
return isLocal;
|
||||||
|
}
|
||||||
|
|
||||||
|
private GroupsServiceHGConnector GetConnector(string url)
|
||||||
|
{
|
||||||
|
lock (m_NetworkConnectors)
|
||||||
|
{
|
||||||
|
if (m_NetworkConnectors.ContainsKey(url))
|
||||||
|
return m_NetworkConnectors[url];
|
||||||
|
|
||||||
|
GroupsServiceHGConnector c = new GroupsServiceHGConnector(url);
|
||||||
|
m_NetworkConnectors[url] = c;
|
||||||
|
}
|
||||||
|
|
||||||
|
return m_NetworkConnectors[url];
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,445 @@
|
||||||
|
/*
|
||||||
|
* 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.Reflection;
|
||||||
|
using System.Text;
|
||||||
|
using System.Xml;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using Nini.Config;
|
||||||
|
using OpenSim.Framework;
|
||||||
|
using OpenSim.Server.Base;
|
||||||
|
using OpenSim.Services.Interfaces;
|
||||||
|
using OpenSim.Framework.Servers.HttpServer;
|
||||||
|
using OpenSim.Server.Handlers.Base;
|
||||||
|
using log4net;
|
||||||
|
using OpenMetaverse;
|
||||||
|
|
||||||
|
namespace OpenSim.Groups
|
||||||
|
{
|
||||||
|
public class HGGroupsServiceRobustConnector : ServiceConnector
|
||||||
|
{
|
||||||
|
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
|
|
||||||
|
private HGGroupsService m_GroupsService;
|
||||||
|
private string m_ConfigName = "Groups";
|
||||||
|
|
||||||
|
// Called by Robust shell
|
||||||
|
public HGGroupsServiceRobustConnector(IConfigSource config, IHttpServer server, string configName) :
|
||||||
|
this(config, server, configName, null, null)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// Called by the sim-bound module
|
||||||
|
public HGGroupsServiceRobustConnector(IConfigSource config, IHttpServer server, string configName, IOfflineIMService im, IUserAccountService users) :
|
||||||
|
base(config, server, configName)
|
||||||
|
{
|
||||||
|
if (configName != String.Empty)
|
||||||
|
m_ConfigName = configName;
|
||||||
|
|
||||||
|
m_log.DebugFormat("[Groups.RobustHGConnector]: Starting with config name {0}", m_ConfigName);
|
||||||
|
|
||||||
|
string homeURI = Util.GetConfigVarFromSections<string>(config, "HomeURI",
|
||||||
|
new string[] { "Startup", "Hypergrid", m_ConfigName}, string.Empty);
|
||||||
|
if (homeURI == string.Empty)
|
||||||
|
throw new Exception(String.Format("[Groups.RobustHGConnector]: please provide the HomeURI [Startup] or in section {0}", m_ConfigName));
|
||||||
|
|
||||||
|
IConfig cnf = config.Configs[m_ConfigName];
|
||||||
|
if (cnf == null)
|
||||||
|
throw new Exception(String.Format("[Groups.RobustHGConnector]: {0} section does not exist", m_ConfigName));
|
||||||
|
|
||||||
|
if (im == null)
|
||||||
|
{
|
||||||
|
string imDll = cnf.GetString("OfflineIMService", string.Empty);
|
||||||
|
if (imDll == string.Empty)
|
||||||
|
throw new Exception(String.Format("[Groups.RobustHGConnector]: please provide OfflineIMService in section {0}", m_ConfigName));
|
||||||
|
|
||||||
|
Object[] args = new Object[] { config };
|
||||||
|
im = ServerUtils.LoadPlugin<IOfflineIMService>(imDll, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (users == null)
|
||||||
|
{
|
||||||
|
string usersDll = cnf.GetString("UserAccountService", string.Empty);
|
||||||
|
if (usersDll == string.Empty)
|
||||||
|
throw new Exception(String.Format("[Groups.RobustHGConnector]: please provide UserAccountService in section {0}", m_ConfigName));
|
||||||
|
|
||||||
|
Object[] args = new Object[] { config };
|
||||||
|
users = ServerUtils.LoadPlugin<IUserAccountService>(usersDll, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_GroupsService = new HGGroupsService(config, im, users, homeURI);
|
||||||
|
|
||||||
|
server.AddStreamHandler(new HGGroupsServicePostHandler(m_GroupsService));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public class HGGroupsServicePostHandler : BaseStreamHandler
|
||||||
|
{
|
||||||
|
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
|
|
||||||
|
private HGGroupsService m_GroupsService;
|
||||||
|
|
||||||
|
public HGGroupsServicePostHandler(HGGroupsService service) :
|
||||||
|
base("POST", "/hg-groups")
|
||||||
|
{
|
||||||
|
m_GroupsService = service;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override byte[] ProcessRequest(string path, Stream requestData,
|
||||||
|
IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
|
||||||
|
{
|
||||||
|
string body;
|
||||||
|
using(StreamReader sr = new StreamReader(requestData))
|
||||||
|
body = sr.ReadToEnd();
|
||||||
|
|
||||||
|
body = body.Trim();
|
||||||
|
|
||||||
|
//m_log.DebugFormat("[XXX]: query String: {0}", body);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Dictionary<string, object> request =
|
||||||
|
ServerUtils.ParseQueryString(body);
|
||||||
|
|
||||||
|
if (!request.ContainsKey("METHOD"))
|
||||||
|
return FailureResult();
|
||||||
|
|
||||||
|
string method = request["METHOD"].ToString();
|
||||||
|
request.Remove("METHOD");
|
||||||
|
|
||||||
|
m_log.DebugFormat("[Groups.RobustHGConnector]: {0}", method);
|
||||||
|
switch (method)
|
||||||
|
{
|
||||||
|
case "POSTGROUP":
|
||||||
|
return HandleAddGroupProxy(request);
|
||||||
|
case "REMOVEAGENTFROMGROUP":
|
||||||
|
return HandleRemoveAgentFromGroup(request);
|
||||||
|
case "GETGROUP":
|
||||||
|
return HandleGetGroup(request);
|
||||||
|
case "ADDNOTICE":
|
||||||
|
return HandleAddNotice(request);
|
||||||
|
case "VERIFYNOTICE":
|
||||||
|
return HandleVerifyNotice(request);
|
||||||
|
case "GETGROUPMEMBERS":
|
||||||
|
return HandleGetGroupMembers(request);
|
||||||
|
case "GETGROUPROLES":
|
||||||
|
return HandleGetGroupRoles(request);
|
||||||
|
case "GETROLEMEMBERS":
|
||||||
|
return HandleGetRoleMembers(request);
|
||||||
|
|
||||||
|
}
|
||||||
|
m_log.DebugFormat("[Groups.RobustHGConnector]: unknown method request: {0}", method);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
m_log.Error(string.Format("[Groups.RobustHGConnector]: Exception {0} ", e.Message), e);
|
||||||
|
}
|
||||||
|
|
||||||
|
return FailureResult();
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] HandleAddGroupProxy(Dictionary<string, object> request)
|
||||||
|
{
|
||||||
|
Dictionary<string, object> result = new Dictionary<string, object>();
|
||||||
|
|
||||||
|
if (!request.ContainsKey("RequestingAgentID") || !request.ContainsKey("GroupID")
|
||||||
|
|| !request.ContainsKey("AgentID")
|
||||||
|
|| !request.ContainsKey("AccessToken") || !request.ContainsKey("Location"))
|
||||||
|
NullResult(result, "Bad network data");
|
||||||
|
|
||||||
|
else
|
||||||
|
{
|
||||||
|
string RequestingAgentID = request["RequestingAgentID"].ToString();
|
||||||
|
string agentID = request["AgentID"].ToString();
|
||||||
|
UUID groupID = new UUID(request["GroupID"].ToString());
|
||||||
|
string accessToken = request["AccessToken"].ToString();
|
||||||
|
string location = request["Location"].ToString();
|
||||||
|
string name = string.Empty;
|
||||||
|
if (request.ContainsKey("Name"))
|
||||||
|
name = request["Name"].ToString();
|
||||||
|
|
||||||
|
string reason = string.Empty;
|
||||||
|
bool success = m_GroupsService.CreateGroupProxy(RequestingAgentID, agentID, accessToken, groupID, location, name, out reason);
|
||||||
|
result["REASON"] = reason;
|
||||||
|
result["RESULT"] = success.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
string xmlString = ServerUtils.BuildXmlResponse(result);
|
||||||
|
|
||||||
|
//m_log.DebugFormat("[XXX]: resp string: {0}", xmlString);
|
||||||
|
return Util.UTF8NoBomEncoding.GetBytes(xmlString);
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] HandleRemoveAgentFromGroup(Dictionary<string, object> request)
|
||||||
|
{
|
||||||
|
Dictionary<string, object> result = new Dictionary<string, object>();
|
||||||
|
|
||||||
|
if (!request.ContainsKey("AccessToken") || !request.ContainsKey("AgentID") ||
|
||||||
|
!request.ContainsKey("GroupID"))
|
||||||
|
NullResult(result, "Bad network data");
|
||||||
|
else
|
||||||
|
{
|
||||||
|
UUID groupID = new UUID(request["GroupID"].ToString());
|
||||||
|
string agentID = request["AgentID"].ToString();
|
||||||
|
string token = request["AccessToken"].ToString();
|
||||||
|
|
||||||
|
if (!m_GroupsService.RemoveAgentFromGroup(agentID, agentID, groupID, token))
|
||||||
|
NullResult(result, "Internal error");
|
||||||
|
else
|
||||||
|
result["RESULT"] = "true";
|
||||||
|
}
|
||||||
|
|
||||||
|
//m_log.DebugFormat("[XXX]: resp string: {0}", xmlString);
|
||||||
|
return Util.UTF8NoBomEncoding.GetBytes(ServerUtils.BuildXmlResponse(result));
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] HandleGetGroup(Dictionary<string, object> request)
|
||||||
|
{
|
||||||
|
Dictionary<string, object> result = new Dictionary<string, object>();
|
||||||
|
|
||||||
|
if (!request.ContainsKey("RequestingAgentID") || !request.ContainsKey("AccessToken"))
|
||||||
|
NullResult(result, "Bad network data");
|
||||||
|
else
|
||||||
|
{
|
||||||
|
string RequestingAgentID = request["RequestingAgentID"].ToString();
|
||||||
|
string token = request["AccessToken"].ToString();
|
||||||
|
|
||||||
|
UUID groupID = UUID.Zero;
|
||||||
|
string groupName = string.Empty;
|
||||||
|
|
||||||
|
if (request.ContainsKey("GroupID"))
|
||||||
|
groupID = new UUID(request["GroupID"].ToString());
|
||||||
|
if (request.ContainsKey("Name"))
|
||||||
|
groupName = request["Name"].ToString();
|
||||||
|
|
||||||
|
ExtendedGroupRecord grec = m_GroupsService.GetGroupRecord(RequestingAgentID, groupID, groupName, token);
|
||||||
|
if (grec == null)
|
||||||
|
NullResult(result, "Group not found");
|
||||||
|
else
|
||||||
|
result["RESULT"] = GroupsDataUtils.GroupRecord(grec);
|
||||||
|
}
|
||||||
|
|
||||||
|
string xmlString = ServerUtils.BuildXmlResponse(result);
|
||||||
|
|
||||||
|
//m_log.DebugFormat("[XXX]: resp string: {0}", xmlString);
|
||||||
|
return Util.UTF8NoBomEncoding.GetBytes(xmlString);
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] HandleGetGroupMembers(Dictionary<string, object> request)
|
||||||
|
{
|
||||||
|
Dictionary<string, object> result = new Dictionary<string, object>();
|
||||||
|
|
||||||
|
if (!request.ContainsKey("RequestingAgentID") || !request.ContainsKey("GroupID") || !request.ContainsKey("AccessToken"))
|
||||||
|
NullResult(result, "Bad network data");
|
||||||
|
else
|
||||||
|
{
|
||||||
|
UUID groupID = new UUID(request["GroupID"].ToString());
|
||||||
|
string requestingAgentID = request["RequestingAgentID"].ToString();
|
||||||
|
string token = request["AccessToken"].ToString();
|
||||||
|
|
||||||
|
List<ExtendedGroupMembersData> members = m_GroupsService.GetGroupMembers(requestingAgentID, groupID, token);
|
||||||
|
if (members == null || (members != null && members.Count == 0))
|
||||||
|
{
|
||||||
|
NullResult(result, "No members");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Dictionary<string, object> dict = new Dictionary<string, object>();
|
||||||
|
int i = 0;
|
||||||
|
foreach (ExtendedGroupMembersData m in members)
|
||||||
|
{
|
||||||
|
dict["m-" + i++] = GroupsDataUtils.GroupMembersData(m);
|
||||||
|
}
|
||||||
|
|
||||||
|
result["RESULT"] = dict;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
string xmlString = ServerUtils.BuildXmlResponse(result);
|
||||||
|
|
||||||
|
//m_log.DebugFormat("[XXX]: resp string: {0}", xmlString);
|
||||||
|
return Util.UTF8NoBomEncoding.GetBytes(xmlString);
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] HandleGetGroupRoles(Dictionary<string, object> request)
|
||||||
|
{
|
||||||
|
Dictionary<string, object> result = new Dictionary<string, object>();
|
||||||
|
|
||||||
|
if (!request.ContainsKey("RequestingAgentID") || !request.ContainsKey("GroupID") || !request.ContainsKey("AccessToken"))
|
||||||
|
NullResult(result, "Bad network data");
|
||||||
|
else
|
||||||
|
{
|
||||||
|
UUID groupID = new UUID(request["GroupID"].ToString());
|
||||||
|
string requestingAgentID = request["RequestingAgentID"].ToString();
|
||||||
|
string token = request["AccessToken"].ToString();
|
||||||
|
|
||||||
|
List<GroupRolesData> roles = m_GroupsService.GetGroupRoles(requestingAgentID, groupID, token);
|
||||||
|
if (roles == null || (roles != null && roles.Count == 0))
|
||||||
|
{
|
||||||
|
NullResult(result, "No members");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Dictionary<string, object> dict = new Dictionary<string, object>();
|
||||||
|
int i = 0;
|
||||||
|
foreach (GroupRolesData r in roles)
|
||||||
|
dict["r-" + i++] = GroupsDataUtils.GroupRolesData(r);
|
||||||
|
|
||||||
|
result["RESULT"] = dict;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
string xmlString = ServerUtils.BuildXmlResponse(result);
|
||||||
|
|
||||||
|
//m_log.DebugFormat("[XXX]: resp string: {0}", xmlString);
|
||||||
|
return Util.UTF8NoBomEncoding.GetBytes(xmlString);
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] HandleGetRoleMembers(Dictionary<string, object> request)
|
||||||
|
{
|
||||||
|
Dictionary<string, object> result = new Dictionary<string, object>();
|
||||||
|
|
||||||
|
if (!request.ContainsKey("RequestingAgentID") || !request.ContainsKey("GroupID") || !request.ContainsKey("AccessToken"))
|
||||||
|
NullResult(result, "Bad network data");
|
||||||
|
else
|
||||||
|
{
|
||||||
|
UUID groupID = new UUID(request["GroupID"].ToString());
|
||||||
|
string requestingAgentID = request["RequestingAgentID"].ToString();
|
||||||
|
string token = request["AccessToken"].ToString();
|
||||||
|
|
||||||
|
List<ExtendedGroupRoleMembersData> rmembers = m_GroupsService.GetGroupRoleMembers(requestingAgentID, groupID, token);
|
||||||
|
if (rmembers == null || (rmembers != null && rmembers.Count == 0))
|
||||||
|
{
|
||||||
|
NullResult(result, "No members");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Dictionary<string, object> dict = new Dictionary<string, object>();
|
||||||
|
int i = 0;
|
||||||
|
foreach (ExtendedGroupRoleMembersData rm in rmembers)
|
||||||
|
dict["rm-" + i++] = GroupsDataUtils.GroupRoleMembersData(rm);
|
||||||
|
|
||||||
|
result["RESULT"] = dict;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
string xmlString = ServerUtils.BuildXmlResponse(result);
|
||||||
|
|
||||||
|
//m_log.DebugFormat("[XXX]: resp string: {0}", xmlString);
|
||||||
|
return Util.UTF8NoBomEncoding.GetBytes(xmlString);
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] HandleAddNotice(Dictionary<string, object> request)
|
||||||
|
{
|
||||||
|
Dictionary<string, object> result = new Dictionary<string, object>();
|
||||||
|
|
||||||
|
if (!request.ContainsKey("RequestingAgentID") || !request.ContainsKey("GroupID") || !request.ContainsKey("NoticeID") ||
|
||||||
|
!request.ContainsKey("FromName") || !request.ContainsKey("Subject") || !request.ContainsKey("Message") ||
|
||||||
|
!request.ContainsKey("HasAttachment"))
|
||||||
|
NullResult(result, "Bad network data");
|
||||||
|
|
||||||
|
else
|
||||||
|
{
|
||||||
|
|
||||||
|
bool hasAtt = bool.Parse(request["HasAttachment"].ToString());
|
||||||
|
byte attType = 0;
|
||||||
|
string attName = string.Empty;
|
||||||
|
string attOwner = string.Empty;
|
||||||
|
UUID attItem = UUID.Zero;
|
||||||
|
if (request.ContainsKey("AttachmentType"))
|
||||||
|
attType = byte.Parse(request["AttachmentType"].ToString());
|
||||||
|
if (request.ContainsKey("AttachmentName"))
|
||||||
|
attName = request["AttachmentType"].ToString();
|
||||||
|
if (request.ContainsKey("AttachmentItemID"))
|
||||||
|
attItem = new UUID(request["AttachmentItemID"].ToString());
|
||||||
|
if (request.ContainsKey("AttachmentOwnerID"))
|
||||||
|
attOwner = request["AttachmentOwnerID"].ToString();
|
||||||
|
|
||||||
|
bool success = m_GroupsService.AddNotice(request["RequestingAgentID"].ToString(), new UUID(request["GroupID"].ToString()),
|
||||||
|
new UUID(request["NoticeID"].ToString()), request["FromName"].ToString(), request["Subject"].ToString(),
|
||||||
|
request["Message"].ToString(), hasAtt, attType, attName, attItem, attOwner);
|
||||||
|
|
||||||
|
result["RESULT"] = success.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
string xmlString = ServerUtils.BuildXmlResponse(result);
|
||||||
|
|
||||||
|
//m_log.DebugFormat("[XXX]: resp string: {0}", xmlString);
|
||||||
|
return Util.UTF8NoBomEncoding.GetBytes(xmlString);
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] HandleVerifyNotice(Dictionary<string, object> request)
|
||||||
|
{
|
||||||
|
Dictionary<string, object> result = new Dictionary<string, object>();
|
||||||
|
|
||||||
|
if (!request.ContainsKey("NoticeID") || !request.ContainsKey("GroupID"))
|
||||||
|
NullResult(result, "Bad network data");
|
||||||
|
|
||||||
|
else
|
||||||
|
{
|
||||||
|
UUID noticeID = new UUID(request["NoticeID"].ToString());
|
||||||
|
UUID groupID = new UUID(request["GroupID"].ToString());
|
||||||
|
|
||||||
|
bool success = m_GroupsService.VerifyNotice(noticeID, groupID);
|
||||||
|
//m_log.DebugFormat("[XXX]: VerifyNotice returned {0}", success);
|
||||||
|
result["RESULT"] = success.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
string xmlString = ServerUtils.BuildXmlResponse(result);
|
||||||
|
|
||||||
|
//m_log.DebugFormat("[XXX]: resp string: {0}", xmlString);
|
||||||
|
return Util.UTF8NoBomEncoding.GetBytes(xmlString);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
|
||||||
|
#region Helpers
|
||||||
|
|
||||||
|
private void NullResult(Dictionary<string, object> result, string reason)
|
||||||
|
{
|
||||||
|
result["RESULT"] = "NULL";
|
||||||
|
result["REASON"] = reason;
|
||||||
|
}
|
||||||
|
|
||||||
|
private byte[] FailureResult()
|
||||||
|
{
|
||||||
|
Dictionary<string, object> result = new Dictionary<string, object>();
|
||||||
|
NullResult(result, "Unknown method");
|
||||||
|
string xmlString = ServerUtils.BuildXmlResponse(result);
|
||||||
|
return Util.UTF8NoBomEncoding.GetBytes(xmlString);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,112 @@
|
||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
using OpenSim.Framework;
|
||||||
|
|
||||||
|
namespace OpenSim.Groups
|
||||||
|
{
|
||||||
|
public interface IGroupsServicesConnector
|
||||||
|
{
|
||||||
|
UUID CreateGroup(UUID RequestingAgentID, string name, string charter, bool showInList, UUID insigniaID, int membershipFee,
|
||||||
|
bool openEnrollment, bool allowPublish, bool maturePublish, UUID founderID, out string reason);
|
||||||
|
bool UpdateGroup(string RequestingAgentID, UUID groupID, string charter, bool showInList, UUID insigniaID, int membershipFee,
|
||||||
|
bool openEnrollment, bool allowPublish, bool maturePublish, out string reason);
|
||||||
|
ExtendedGroupRecord GetGroupRecord(string RequestingAgentID, UUID GroupID, string GroupName);
|
||||||
|
List<DirGroupsReplyData> FindGroups(string RequestingAgentIDstr, string search);
|
||||||
|
List<GroupMembersData> GetGroupMembers(string RequestingAgentID, UUID GroupID);
|
||||||
|
|
||||||
|
bool AddGroupRole(string RequestingAgentID, UUID groupID, UUID roleID, string name, string description, string title, ulong powers, out string reason);
|
||||||
|
bool UpdateGroupRole(string RequestingAgentID, UUID groupID, UUID roleID, string name, string description, string title, ulong powers);
|
||||||
|
void RemoveGroupRole(string RequestingAgentID, UUID groupID, UUID roleID);
|
||||||
|
List<GroupRolesData> GetGroupRoles(string RequestingAgentID, UUID GroupID);
|
||||||
|
List<GroupRoleMembersData> GetGroupRoleMembers(string RequestingAgentID, UUID GroupID);
|
||||||
|
|
||||||
|
bool AddAgentToGroup(string RequestingAgentID, string AgentID, UUID GroupID, UUID RoleID, string token, out string reason);
|
||||||
|
void RemoveAgentFromGroup(string RequestingAgentID, string AgentID, UUID GroupID);
|
||||||
|
|
||||||
|
bool AddAgentToGroupInvite(string RequestingAgentID, UUID inviteID, UUID groupID, UUID roleID, string agentID);
|
||||||
|
GroupInviteInfo GetAgentToGroupInvite(string RequestingAgentID, UUID inviteID);
|
||||||
|
void RemoveAgentToGroupInvite(string RequestingAgentID, UUID inviteID);
|
||||||
|
|
||||||
|
void AddAgentToGroupRole(string RequestingAgentID, string AgentID, UUID GroupID, UUID RoleID);
|
||||||
|
void RemoveAgentFromGroupRole(string RequestingAgentID, string AgentID, UUID GroupID, UUID RoleID);
|
||||||
|
List<GroupRolesData> GetAgentGroupRoles(string RequestingAgentID, string AgentID, UUID GroupID);
|
||||||
|
|
||||||
|
void SetAgentActiveGroup(string RequestingAgentID, string AgentID, UUID GroupID);
|
||||||
|
ExtendedGroupMembershipData GetAgentActiveMembership(string RequestingAgentID, string AgentID);
|
||||||
|
|
||||||
|
void SetAgentActiveGroupRole(string RequestingAgentID, string AgentID, UUID GroupID, UUID RoleID);
|
||||||
|
void UpdateMembership(string RequestingAgentID, string AgentID, UUID GroupID, bool AcceptNotices, bool ListInProfile);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get information about a specific group to which the user belongs.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="RequestingAgentID">The agent requesting the information.</param>
|
||||||
|
/// <param name="AgentID">The agent requested.</param>
|
||||||
|
/// <param name="GroupID">The group requested.</param>
|
||||||
|
/// <returns>
|
||||||
|
/// If the user is a member of the group then the data structure is returned. If not, then null is returned.
|
||||||
|
/// </returns>
|
||||||
|
ExtendedGroupMembershipData GetAgentGroupMembership(string RequestingAgentID, string AgentID, UUID GroupID);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get information about the groups to which a user belongs.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="RequestingAgentID">The agent requesting the information.</param>
|
||||||
|
/// <param name="AgentID">The agent requested.</param>
|
||||||
|
/// <returns>
|
||||||
|
/// Information about the groups to which the user belongs. If the user belongs to no groups then an empty
|
||||||
|
/// list is returned.
|
||||||
|
/// </returns>
|
||||||
|
List<GroupMembershipData> GetAgentGroupMemberships(string RequestingAgentID, string AgentID);
|
||||||
|
|
||||||
|
bool AddGroupNotice(string RequestingAgentID, UUID groupID, UUID noticeID, string fromName, string subject, string message,
|
||||||
|
bool hasAttachment, byte attType, string attName, UUID attItemID, string attOwnerID);
|
||||||
|
GroupNoticeInfo GetGroupNotice(string RequestingAgentID, UUID noticeID);
|
||||||
|
List<ExtendedGroupNoticeData> GetGroupNotices(string RequestingAgentID, UUID GroupID);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public class GroupInviteInfo
|
||||||
|
{
|
||||||
|
public UUID GroupID = UUID.Zero;
|
||||||
|
public UUID RoleID = UUID.Zero;
|
||||||
|
public string AgentID = string.Empty;
|
||||||
|
public UUID InviteID = UUID.Zero;
|
||||||
|
}
|
||||||
|
|
||||||
|
public class GroupNoticeInfo
|
||||||
|
{
|
||||||
|
public ExtendedGroupNoticeData noticeData = new ExtendedGroupNoticeData();
|
||||||
|
public UUID GroupID = UUID.Zero;
|
||||||
|
public string Message = string.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,326 @@
|
||||||
|
/*
|
||||||
|
* 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.Reflection;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
using OpenSim.Framework;
|
||||||
|
using OpenSim.Region.Framework.Scenes;
|
||||||
|
using OpenSim.Region.Framework.Interfaces;
|
||||||
|
using OpenSim.Services.Interfaces;
|
||||||
|
|
||||||
|
using OpenMetaverse;
|
||||||
|
using Mono.Addins;
|
||||||
|
using log4net;
|
||||||
|
using Nini.Config;
|
||||||
|
|
||||||
|
namespace OpenSim.Groups
|
||||||
|
{
|
||||||
|
[Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "GroupsServiceLocalConnectorModule")]
|
||||||
|
public class GroupsServiceLocalConnectorModule : ISharedRegionModule, IGroupsServicesConnector
|
||||||
|
{
|
||||||
|
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
|
|
||||||
|
private bool m_Enabled = false;
|
||||||
|
private GroupsService m_GroupsService;
|
||||||
|
private IUserManagement m_UserManagement;
|
||||||
|
private List<Scene> m_Scenes;
|
||||||
|
private ForeignImporter m_ForeignImporter;
|
||||||
|
|
||||||
|
#region constructors
|
||||||
|
public GroupsServiceLocalConnectorModule()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public GroupsServiceLocalConnectorModule(IConfigSource config, IUserManagement uman)
|
||||||
|
{
|
||||||
|
Init(config);
|
||||||
|
m_UserManagement = uman;
|
||||||
|
m_ForeignImporter = new ForeignImporter(uman);
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
private void Init(IConfigSource config)
|
||||||
|
{
|
||||||
|
m_GroupsService = new GroupsService(config);
|
||||||
|
m_Scenes = new List<Scene>();
|
||||||
|
}
|
||||||
|
|
||||||
|
#region ISharedRegionModule
|
||||||
|
|
||||||
|
public void Initialise(IConfigSource config)
|
||||||
|
{
|
||||||
|
IConfig groupsConfig = config.Configs["Groups"];
|
||||||
|
if (groupsConfig == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if ((groupsConfig.GetBoolean("Enabled", false) == false)
|
||||||
|
|| (groupsConfig.GetString("ServicesConnectorModule", string.Empty) != Name))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Init(config);
|
||||||
|
m_Enabled = true;
|
||||||
|
|
||||||
|
m_log.DebugFormat("[Groups]: Initializing {0}", this.Name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Name
|
||||||
|
{
|
||||||
|
get { return "Groups Local Service Connector"; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public Type ReplaceableInterface
|
||||||
|
{
|
||||||
|
get { return null; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddRegion(Scene scene)
|
||||||
|
{
|
||||||
|
if (!m_Enabled)
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_log.DebugFormat("[Groups]: Registering {0} with {1}", this.Name, scene.RegionInfo.RegionName);
|
||||||
|
scene.RegisterModuleInterface<IGroupsServicesConnector>(this);
|
||||||
|
m_Scenes.Add(scene);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RemoveRegion(Scene scene)
|
||||||
|
{
|
||||||
|
if (!m_Enabled)
|
||||||
|
return;
|
||||||
|
|
||||||
|
scene.UnregisterModuleInterface<IGroupsServicesConnector>(this);
|
||||||
|
m_Scenes.Remove(scene);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RegionLoaded(Scene scene)
|
||||||
|
{
|
||||||
|
if (!m_Enabled)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (m_UserManagement == null)
|
||||||
|
{
|
||||||
|
m_UserManagement = scene.RequestModuleInterface<IUserManagement>();
|
||||||
|
m_ForeignImporter = new ForeignImporter(m_UserManagement);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void PostInitialise()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Close()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region IGroupsServicesConnector
|
||||||
|
|
||||||
|
public UUID CreateGroup(UUID RequestingAgentID, string name, string charter, bool showInList, UUID insigniaID, int membershipFee, bool openEnrollment,
|
||||||
|
bool allowPublish, bool maturePublish, UUID founderID, out string reason)
|
||||||
|
{
|
||||||
|
m_log.DebugFormat("[Groups]: Creating group {0}", name);
|
||||||
|
reason = string.Empty;
|
||||||
|
return m_GroupsService.CreateGroup(RequestingAgentID.ToString(), name, charter, showInList, insigniaID,
|
||||||
|
membershipFee, openEnrollment, allowPublish, maturePublish, founderID, out reason);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool UpdateGroup(string RequestingAgentID, UUID groupID, string charter, bool showInList, UUID insigniaID, int membershipFee,
|
||||||
|
bool openEnrollment, bool allowPublish, bool maturePublish, out string reason)
|
||||||
|
{
|
||||||
|
reason = string.Empty;
|
||||||
|
m_GroupsService.UpdateGroup(RequestingAgentID, groupID, charter, showInList, insigniaID, membershipFee, openEnrollment, allowPublish, maturePublish);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ExtendedGroupRecord GetGroupRecord(string RequestingAgentID, UUID GroupID, string GroupName)
|
||||||
|
{
|
||||||
|
if (GroupID != UUID.Zero)
|
||||||
|
return m_GroupsService.GetGroupRecord(RequestingAgentID, GroupID);
|
||||||
|
else if (GroupName != null)
|
||||||
|
return m_GroupsService.GetGroupRecord(RequestingAgentID, GroupName);
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<DirGroupsReplyData> FindGroups(string RequestingAgentIDstr, string search)
|
||||||
|
{
|
||||||
|
return m_GroupsService.FindGroups(RequestingAgentIDstr, search);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<GroupMembersData> GetGroupMembers(string RequestingAgentID, UUID GroupID)
|
||||||
|
{
|
||||||
|
List<ExtendedGroupMembersData> _members = m_GroupsService.GetGroupMembers(RequestingAgentID, GroupID);
|
||||||
|
if (_members != null && _members.Count > 0)
|
||||||
|
{
|
||||||
|
List<GroupMembersData> members = _members.ConvertAll<GroupMembersData>(new Converter<ExtendedGroupMembersData, GroupMembersData>(m_ForeignImporter.ConvertGroupMembersData));
|
||||||
|
return members;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new List<GroupMembersData>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool AddGroupRole(string RequestingAgentID, UUID groupID, UUID roleID, string name, string description, string title, ulong powers, out string reason)
|
||||||
|
{
|
||||||
|
return m_GroupsService.AddGroupRole(RequestingAgentID, groupID, roleID, name, description, title, powers, out reason);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool UpdateGroupRole(string RequestingAgentID, UUID groupID, UUID roleID, string name, string description, string title, ulong powers)
|
||||||
|
{
|
||||||
|
return m_GroupsService.UpdateGroupRole(RequestingAgentID, groupID, roleID, name, description, title, powers);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RemoveGroupRole(string RequestingAgentID, UUID groupID, UUID roleID)
|
||||||
|
{
|
||||||
|
m_GroupsService.RemoveGroupRole(RequestingAgentID, groupID, roleID);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<GroupRolesData> GetGroupRoles(string RequestingAgentID, UUID GroupID)
|
||||||
|
{
|
||||||
|
return m_GroupsService.GetGroupRoles(RequestingAgentID, GroupID);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<GroupRoleMembersData> GetGroupRoleMembers(string RequestingAgentID, UUID GroupID)
|
||||||
|
{
|
||||||
|
List<ExtendedGroupRoleMembersData> _rm = m_GroupsService.GetGroupRoleMembers(RequestingAgentID, GroupID);
|
||||||
|
if (_rm != null && _rm.Count > 0)
|
||||||
|
{
|
||||||
|
List<GroupRoleMembersData> rm = _rm.ConvertAll<GroupRoleMembersData>(new Converter<ExtendedGroupRoleMembersData, GroupRoleMembersData>(m_ForeignImporter.ConvertGroupRoleMembersData));
|
||||||
|
return rm;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new List<GroupRoleMembersData>();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool AddAgentToGroup(string RequestingAgentID, string AgentID, UUID GroupID, UUID RoleID, string token, out string reason)
|
||||||
|
{
|
||||||
|
return m_GroupsService.AddAgentToGroup(RequestingAgentID, AgentID, GroupID, RoleID, token, out reason);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RemoveAgentFromGroup(string RequestingAgentID, string AgentID, UUID GroupID)
|
||||||
|
{
|
||||||
|
m_GroupsService.RemoveAgentFromGroup(RequestingAgentID, AgentID, GroupID);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool AddAgentToGroupInvite(string RequestingAgentID, UUID inviteID, UUID groupID, UUID roleID, string agentID)
|
||||||
|
{
|
||||||
|
return m_GroupsService.AddAgentToGroupInvite(RequestingAgentID, inviteID, groupID, roleID, agentID);
|
||||||
|
}
|
||||||
|
|
||||||
|
public GroupInviteInfo GetAgentToGroupInvite(string RequestingAgentID, UUID inviteID)
|
||||||
|
{
|
||||||
|
return m_GroupsService.GetAgentToGroupInvite(RequestingAgentID, inviteID); ;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RemoveAgentToGroupInvite(string RequestingAgentID, UUID inviteID)
|
||||||
|
{
|
||||||
|
m_GroupsService.RemoveAgentToGroupInvite(RequestingAgentID, inviteID);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddAgentToGroupRole(string RequestingAgentID, string AgentID, UUID GroupID, UUID RoleID)
|
||||||
|
{
|
||||||
|
m_GroupsService.AddAgentToGroupRole(RequestingAgentID, AgentID, GroupID, RoleID);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RemoveAgentFromGroupRole(string RequestingAgentID, string AgentID, UUID GroupID, UUID RoleID)
|
||||||
|
{
|
||||||
|
m_GroupsService.RemoveAgentFromGroupRole(RequestingAgentID, AgentID, GroupID, RoleID);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<GroupRolesData> GetAgentGroupRoles(string RequestingAgentID, string AgentID, UUID GroupID)
|
||||||
|
{
|
||||||
|
return m_GroupsService.GetAgentGroupRoles(RequestingAgentID, AgentID, GroupID);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetAgentActiveGroup(string RequestingAgentID, string AgentID, UUID GroupID)
|
||||||
|
{
|
||||||
|
m_GroupsService.SetAgentActiveGroup(RequestingAgentID, AgentID, GroupID);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ExtendedGroupMembershipData GetAgentActiveMembership(string RequestingAgentID, string AgentID)
|
||||||
|
{
|
||||||
|
return m_GroupsService.GetAgentActiveMembership(RequestingAgentID, AgentID);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetAgentActiveGroupRole(string RequestingAgentID, string AgentID, UUID GroupID, UUID RoleID)
|
||||||
|
{
|
||||||
|
m_GroupsService.SetAgentActiveGroupRole(RequestingAgentID, AgentID, GroupID, RoleID);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void UpdateMembership(string RequestingAgentID, string AgentID, UUID GroupID, bool AcceptNotices, bool ListInProfile)
|
||||||
|
{
|
||||||
|
m_GroupsService.UpdateMembership(RequestingAgentID, AgentID, GroupID, AcceptNotices, ListInProfile);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ExtendedGroupMembershipData GetAgentGroupMembership(string RequestingAgentID, string AgentID, UUID GroupID)
|
||||||
|
{
|
||||||
|
return m_GroupsService.GetAgentGroupMembership(RequestingAgentID, AgentID, GroupID); ;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<GroupMembershipData> GetAgentGroupMemberships(string RequestingAgentID, string AgentID)
|
||||||
|
{
|
||||||
|
return m_GroupsService.GetAgentGroupMemberships(RequestingAgentID, AgentID);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool AddGroupNotice(string RequestingAgentID, UUID groupID, UUID noticeID, string fromName, string subject, string message,
|
||||||
|
bool hasAttachment, byte attType, string attName, UUID attItemID, string attOwnerID)
|
||||||
|
{
|
||||||
|
return m_GroupsService.AddGroupNotice(RequestingAgentID, groupID, noticeID, fromName, subject, message,
|
||||||
|
hasAttachment, attType, attName, attItemID, attOwnerID);
|
||||||
|
}
|
||||||
|
|
||||||
|
public GroupNoticeInfo GetGroupNotice(string RequestingAgentID, UUID noticeID)
|
||||||
|
{
|
||||||
|
GroupNoticeInfo notice = m_GroupsService.GetGroupNotice(RequestingAgentID, noticeID);
|
||||||
|
|
||||||
|
//if (notice != null && notice.noticeData.HasAttachment && notice.noticeData.AttachmentOwnerID != null)
|
||||||
|
//{
|
||||||
|
// UUID userID = UUID.Zero;
|
||||||
|
// string url = string.Empty, first = string.Empty, last = string.Empty, tmp = string.Empty;
|
||||||
|
// Util.ParseUniversalUserIdentifier(notice.noticeData.AttachmentOwnerID, out userID, out url, out first, out last, out tmp);
|
||||||
|
// if (url != string.Empty)
|
||||||
|
// m_UserManagement.AddUser(userID, first, last, url);
|
||||||
|
//}
|
||||||
|
|
||||||
|
return notice;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<ExtendedGroupNoticeData> GetGroupNotices(string RequestingAgentID, UUID GroupID)
|
||||||
|
{
|
||||||
|
return m_GroupsService.GetGroupNotices(RequestingAgentID, GroupID);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,36 @@
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using Mono.Addins;
|
||||||
|
|
||||||
|
// General Information about an assembly is controlled through the following
|
||||||
|
// set of attributes. Change these attribute values to modify the information
|
||||||
|
// associated with an assembly.
|
||||||
|
[assembly: AssemblyTitle("OpenSim.Addons.Groups")]
|
||||||
|
[assembly: AssemblyDescription("")]
|
||||||
|
[assembly: AssemblyConfiguration("")]
|
||||||
|
[assembly: AssemblyCompany("http://opensimulator.org")]
|
||||||
|
[assembly: AssemblyProduct("OpenSim.Addons.Groups")]
|
||||||
|
[assembly: AssemblyCopyright("Copyright (c) OpenSimulator.org Developers")]
|
||||||
|
[assembly: AssemblyTrademark("")]
|
||||||
|
[assembly: AssemblyCulture("")]
|
||||||
|
|
||||||
|
// Setting ComVisible to false makes the types in this assembly not visible
|
||||||
|
// to COM components. If you need to access a type in this assembly from
|
||||||
|
// COM, set the ComVisible attribute to true on that type.
|
||||||
|
[assembly: ComVisible(false)]
|
||||||
|
|
||||||
|
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||||
|
[assembly: Guid("313d4865-d179-4735-9b5a-fe74885878b2")]
|
||||||
|
|
||||||
|
// Version information for an assembly consists of the following four values:
|
||||||
|
//
|
||||||
|
// Major Version
|
||||||
|
// Minor Version
|
||||||
|
// Build Number
|
||||||
|
// Revision
|
||||||
|
//
|
||||||
|
[assembly: AssemblyVersion(OpenSim.VersionInfo.AssemblyVersionNumber)]
|
||||||
|
|
||||||
|
[assembly: Addin("OpenSim.Groups", OpenSim.VersionInfo.VersionNumber)]
|
||||||
|
[assembly: AddinDependency("OpenSim.Region.Framework", OpenSim.VersionInfo.VersionNumber)]
|
|
@ -0,0 +1,696 @@
|
||||||
|
/*
|
||||||
|
* 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.Reflection;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
using OpenSim.Framework;
|
||||||
|
using OpenSim.Framework.ServiceAuth;
|
||||||
|
using OpenSim.Server.Base;
|
||||||
|
|
||||||
|
using OpenMetaverse;
|
||||||
|
using log4net;
|
||||||
|
using Nini.Config;
|
||||||
|
|
||||||
|
namespace OpenSim.Groups
|
||||||
|
{
|
||||||
|
public class GroupsServiceRemoteConnector
|
||||||
|
{
|
||||||
|
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
|
|
||||||
|
private string m_ServerURI;
|
||||||
|
private IServiceAuth m_Auth;
|
||||||
|
private object m_Lock = new object();
|
||||||
|
|
||||||
|
public GroupsServiceRemoteConnector(IConfigSource 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_ServerURI = url;
|
||||||
|
if (!m_ServerURI.EndsWith("/"))
|
||||||
|
m_ServerURI += "/";
|
||||||
|
|
||||||
|
/// This is from BaseServiceConnector
|
||||||
|
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,
|
||||||
|
bool allowPublish, bool maturePublish, UUID founderID, out string reason)
|
||||||
|
{
|
||||||
|
reason = string.Empty;
|
||||||
|
|
||||||
|
ExtendedGroupRecord rec = new ExtendedGroupRecord();
|
||||||
|
rec.AllowPublish = allowPublish;
|
||||||
|
rec.Charter = charter;
|
||||||
|
rec.FounderID = founderID;
|
||||||
|
rec.GroupName = name;
|
||||||
|
rec.GroupPicture = insigniaID;
|
||||||
|
rec.MaturePublish = maturePublish;
|
||||||
|
rec.MembershipFee = membershipFee;
|
||||||
|
rec.OpenEnrollment = openEnrollment;
|
||||||
|
rec.ShowInList = showInList;
|
||||||
|
|
||||||
|
Dictionary<string, object> sendData = GroupsDataUtils.GroupRecord(rec);
|
||||||
|
sendData["RequestingAgentID"] = RequestingAgentID;
|
||||||
|
sendData["OP"] = "ADD";
|
||||||
|
Dictionary<string, object> ret = MakeRequest("PUTGROUP", sendData);
|
||||||
|
|
||||||
|
if (ret == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
if (ret["RESULT"].ToString() == "NULL")
|
||||||
|
{
|
||||||
|
reason = ret["REASON"].ToString();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return GroupsDataUtils.GroupRecord((Dictionary<string, object>)ret["RESULT"]);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public ExtendedGroupRecord UpdateGroup(string RequestingAgentID, UUID groupID, string charter, bool showInList, UUID insigniaID, int membershipFee, bool openEnrollment, bool allowPublish, bool maturePublish)
|
||||||
|
{
|
||||||
|
ExtendedGroupRecord rec = new ExtendedGroupRecord();
|
||||||
|
rec.AllowPublish = allowPublish;
|
||||||
|
rec.Charter = charter;
|
||||||
|
rec.GroupPicture = insigniaID;
|
||||||
|
rec.MaturePublish = maturePublish;
|
||||||
|
rec.GroupID = groupID;
|
||||||
|
rec.MembershipFee = membershipFee;
|
||||||
|
rec.OpenEnrollment = openEnrollment;
|
||||||
|
rec.ShowInList = showInList;
|
||||||
|
|
||||||
|
Dictionary<string, object> sendData = GroupsDataUtils.GroupRecord(rec);
|
||||||
|
sendData["RequestingAgentID"] = RequestingAgentID;
|
||||||
|
sendData["OP"] = "UPDATE";
|
||||||
|
Dictionary<string, object> ret = MakeRequest("PUTGROUP", sendData);
|
||||||
|
|
||||||
|
if (ret == null || (ret != null && (!ret.ContainsKey("RESULT") || ret["RESULT"].ToString() == "NULL")))
|
||||||
|
return null;
|
||||||
|
|
||||||
|
return GroupsDataUtils.GroupRecord((Dictionary<string, object>)ret["RESULT"]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ExtendedGroupRecord GetGroupRecord(string RequestingAgentID, UUID GroupID, string GroupName)
|
||||||
|
{
|
||||||
|
if (GroupID == UUID.Zero && (GroupName == null || (GroupName != null && GroupName == string.Empty)))
|
||||||
|
return null;
|
||||||
|
|
||||||
|
Dictionary<string, object> sendData = new Dictionary<string, object>();
|
||||||
|
if (GroupID != UUID.Zero)
|
||||||
|
sendData["GroupID"] = GroupID.ToString();
|
||||||
|
if (!string.IsNullOrEmpty(GroupName))
|
||||||
|
sendData["Name"] = GroupsDataUtils.Sanitize(GroupName);
|
||||||
|
|
||||||
|
sendData["RequestingAgentID"] = RequestingAgentID;
|
||||||
|
|
||||||
|
Dictionary<string, object> ret = MakeRequest("GETGROUP", sendData);
|
||||||
|
|
||||||
|
if (ret == null || (ret != null && (!ret.ContainsKey("RESULT") || ret["RESULT"].ToString() == "NULL")))
|
||||||
|
return null;
|
||||||
|
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
reason = string.Empty;
|
||||||
|
|
||||||
|
Dictionary<string, object> sendData = new Dictionary<string,object>();
|
||||||
|
sendData["AgentID"] = AgentID;
|
||||||
|
sendData["GroupID"] = GroupID.ToString();
|
||||||
|
sendData["RoleID"] = RoleID.ToString();
|
||||||
|
sendData["RequestingAgentID"] = RequestingAgentID;
|
||||||
|
sendData["AccessToken"] = token;
|
||||||
|
Dictionary<string, object> ret = MakeRequest("ADDAGENTTOGROUP", sendData);
|
||||||
|
|
||||||
|
if (ret == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
if (!ret.ContainsKey("RESULT"))
|
||||||
|
return null;
|
||||||
|
|
||||||
|
if (ret["RESULT"].ToString() == "NULL")
|
||||||
|
{
|
||||||
|
reason = ret["REASON"].ToString();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return GroupsDataUtils.GroupMembershipData((Dictionary<string, object>)ret["RESULT"]);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RemoveAgentFromGroup(string RequestingAgentID, string AgentID, UUID GroupID)
|
||||||
|
{
|
||||||
|
Dictionary<string, object> sendData = new Dictionary<string, object>();
|
||||||
|
sendData["AgentID"] = AgentID;
|
||||||
|
sendData["GroupID"] = GroupID.ToString();
|
||||||
|
sendData["RequestingAgentID"] = RequestingAgentID;
|
||||||
|
MakeRequest("REMOVEAGENTFROMGROUP", sendData);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ExtendedGroupMembershipData GetMembership(string RequestingAgentID, string AgentID, UUID GroupID)
|
||||||
|
{
|
||||||
|
Dictionary<string, object> sendData = new Dictionary<string, object>();
|
||||||
|
sendData["AgentID"] = AgentID;
|
||||||
|
if (GroupID != UUID.Zero)
|
||||||
|
sendData["GroupID"] = GroupID.ToString();
|
||||||
|
sendData["RequestingAgentID"] = RequestingAgentID;
|
||||||
|
Dictionary<string, object> ret = MakeRequest("GETMEMBERSHIP", sendData);
|
||||||
|
|
||||||
|
if (ret == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
if (!ret.ContainsKey("RESULT"))
|
||||||
|
return null;
|
||||||
|
|
||||||
|
if (ret["RESULT"].ToString() == "NULL")
|
||||||
|
return null;
|
||||||
|
|
||||||
|
return GroupsDataUtils.GroupMembershipData((Dictionary<string, object>)ret["RESULT"]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<GroupMembershipData> GetMemberships(string RequestingAgentID, string AgentID)
|
||||||
|
{
|
||||||
|
List<GroupMembershipData> memberships = new List<GroupMembershipData>();
|
||||||
|
|
||||||
|
Dictionary<string, object> sendData = new Dictionary<string, object>();
|
||||||
|
sendData["AgentID"] = AgentID;
|
||||||
|
sendData["ALL"] = "true";
|
||||||
|
sendData["RequestingAgentID"] = RequestingAgentID;
|
||||||
|
Dictionary<string, object> ret = MakeRequest("GETMEMBERSHIP", sendData);
|
||||||
|
|
||||||
|
if (ret == null)
|
||||||
|
return memberships;
|
||||||
|
|
||||||
|
if (!ret.ContainsKey("RESULT"))
|
||||||
|
return memberships;
|
||||||
|
|
||||||
|
if (ret["RESULT"].ToString() == "NULL")
|
||||||
|
return memberships;
|
||||||
|
|
||||||
|
foreach (object v in ((Dictionary<string, object>)ret["RESULT"]).Values)
|
||||||
|
{
|
||||||
|
GroupMembershipData m = GroupsDataUtils.GroupMembershipData((Dictionary<string, object>)v);
|
||||||
|
memberships.Add(m);
|
||||||
|
}
|
||||||
|
|
||||||
|
return memberships;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<ExtendedGroupMembersData> GetGroupMembers(string RequestingAgentID, UUID GroupID)
|
||||||
|
{
|
||||||
|
List<ExtendedGroupMembersData> members = new List<ExtendedGroupMembersData>();
|
||||||
|
|
||||||
|
Dictionary<string, object> sendData = new Dictionary<string, object>();
|
||||||
|
sendData["GroupID"] = GroupID.ToString();
|
||||||
|
sendData["RequestingAgentID"] = RequestingAgentID;
|
||||||
|
|
||||||
|
Dictionary<string, object> ret = MakeRequest("GETGROUPMEMBERS", sendData);
|
||||||
|
|
||||||
|
if (ret == null)
|
||||||
|
return members;
|
||||||
|
|
||||||
|
if (!ret.ContainsKey("RESULT"))
|
||||||
|
return members;
|
||||||
|
|
||||||
|
if (ret["RESULT"].ToString() == "NULL")
|
||||||
|
return members;
|
||||||
|
|
||||||
|
foreach (object v in ((Dictionary<string, object>)ret["RESULT"]).Values)
|
||||||
|
{
|
||||||
|
ExtendedGroupMembersData m = GroupsDataUtils.GroupMembersData((Dictionary<string, object>)v);
|
||||||
|
members.Add(m);
|
||||||
|
}
|
||||||
|
|
||||||
|
return members;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool AddGroupRole(string RequestingAgentID, UUID groupID, UUID roleID, string name, string description, string title, ulong powers, out string reason)
|
||||||
|
{
|
||||||
|
reason = string.Empty;
|
||||||
|
|
||||||
|
Dictionary<string, object> sendData = new Dictionary<string, object>();
|
||||||
|
sendData["GroupID"] = groupID.ToString();
|
||||||
|
sendData["RoleID"] = roleID.ToString();
|
||||||
|
sendData["Name"] = GroupsDataUtils.Sanitize(name);
|
||||||
|
sendData["Description"] = GroupsDataUtils.Sanitize(description);
|
||||||
|
sendData["Title"] = GroupsDataUtils.Sanitize(title);
|
||||||
|
sendData["Powers"] = powers.ToString();
|
||||||
|
sendData["RequestingAgentID"] = RequestingAgentID;
|
||||||
|
sendData["OP"] = "ADD";
|
||||||
|
Dictionary<string, object> ret = MakeRequest("PUTROLE", sendData);
|
||||||
|
|
||||||
|
if (ret == null)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!ret.ContainsKey("RESULT"))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (ret["RESULT"].ToString().ToLower() != "true")
|
||||||
|
{
|
||||||
|
reason = ret["REASON"].ToString();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool UpdateGroupRole(string RequestingAgentID, UUID groupID, UUID roleID, string name, string description, string title, ulong powers)
|
||||||
|
{
|
||||||
|
Dictionary<string, object> sendData = new Dictionary<string, object>();
|
||||||
|
sendData["GroupID"] = groupID.ToString();
|
||||||
|
sendData["RoleID"] = roleID.ToString();
|
||||||
|
sendData["Name"] = GroupsDataUtils.Sanitize(name);
|
||||||
|
sendData["Description"] = GroupsDataUtils.Sanitize(description);
|
||||||
|
sendData["Title"] = GroupsDataUtils.Sanitize(title);
|
||||||
|
sendData["Powers"] = powers.ToString();
|
||||||
|
sendData["RequestingAgentID"] = RequestingAgentID;
|
||||||
|
sendData["OP"] = "UPDATE";
|
||||||
|
Dictionary<string, object> ret = MakeRequest("PUTROLE", sendData);
|
||||||
|
|
||||||
|
if (ret == null)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!ret.ContainsKey("RESULT"))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (ret["RESULT"].ToString().ToLower() != "true")
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RemoveGroupRole(string RequestingAgentID, UUID groupID, UUID roleID)
|
||||||
|
{
|
||||||
|
Dictionary<string, object> sendData = new Dictionary<string, object>();
|
||||||
|
sendData["GroupID"] = groupID.ToString();
|
||||||
|
sendData["RoleID"] = roleID.ToString();
|
||||||
|
sendData["RequestingAgentID"] = RequestingAgentID;
|
||||||
|
MakeRequest("REMOVEROLE", sendData);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<GroupRolesData> GetGroupRoles(string RequestingAgentID, UUID GroupID)
|
||||||
|
{
|
||||||
|
List<GroupRolesData> roles = new List<GroupRolesData>();
|
||||||
|
|
||||||
|
Dictionary<string, object> sendData = new Dictionary<string, object>();
|
||||||
|
sendData["GroupID"] = GroupID.ToString();
|
||||||
|
sendData["RequestingAgentID"] = RequestingAgentID;
|
||||||
|
Dictionary<string, object> ret = MakeRequest("GETGROUPROLES", sendData);
|
||||||
|
|
||||||
|
if (ret == null)
|
||||||
|
return roles;
|
||||||
|
|
||||||
|
if (!ret.ContainsKey("RESULT"))
|
||||||
|
return roles;
|
||||||
|
|
||||||
|
if (ret["RESULT"].ToString() == "NULL")
|
||||||
|
return roles;
|
||||||
|
|
||||||
|
foreach (object v in ((Dictionary<string, object>)ret["RESULT"]).Values)
|
||||||
|
{
|
||||||
|
GroupRolesData m = GroupsDataUtils.GroupRolesData((Dictionary<string, object>)v);
|
||||||
|
roles.Add(m);
|
||||||
|
}
|
||||||
|
|
||||||
|
return roles;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<ExtendedGroupRoleMembersData> GetGroupRoleMembers(string RequestingAgentID, UUID GroupID)
|
||||||
|
{
|
||||||
|
List<ExtendedGroupRoleMembersData> rmembers = new List<ExtendedGroupRoleMembersData>();
|
||||||
|
|
||||||
|
Dictionary<string, object> sendData = new Dictionary<string, object>();
|
||||||
|
sendData["GroupID"] = GroupID.ToString();
|
||||||
|
sendData["RequestingAgentID"] = RequestingAgentID;
|
||||||
|
Dictionary<string, object> ret = MakeRequest("GETROLEMEMBERS", sendData);
|
||||||
|
|
||||||
|
if (ret == null)
|
||||||
|
return rmembers;
|
||||||
|
|
||||||
|
if (!ret.ContainsKey("RESULT"))
|
||||||
|
return rmembers;
|
||||||
|
|
||||||
|
if (ret["RESULT"].ToString() == "NULL")
|
||||||
|
return rmembers;
|
||||||
|
|
||||||
|
foreach (object v in ((Dictionary<string, object>)ret["RESULT"]).Values)
|
||||||
|
{
|
||||||
|
ExtendedGroupRoleMembersData m = GroupsDataUtils.GroupRoleMembersData((Dictionary<string, object>)v);
|
||||||
|
rmembers.Add(m);
|
||||||
|
}
|
||||||
|
|
||||||
|
return rmembers;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool AddAgentToGroupRole(string RequestingAgentID, string AgentID, UUID GroupID, UUID RoleID)
|
||||||
|
{
|
||||||
|
Dictionary<string, object> sendData = new Dictionary<string, object>();
|
||||||
|
sendData["AgentID"] = AgentID.ToString();
|
||||||
|
sendData["GroupID"] = GroupID.ToString();
|
||||||
|
sendData["RoleID"] = RoleID.ToString();
|
||||||
|
sendData["RequestingAgentID"] = RequestingAgentID;
|
||||||
|
sendData["OP"] = "ADD";
|
||||||
|
|
||||||
|
Dictionary<string, object> ret = MakeRequest("AGENTROLE", sendData);
|
||||||
|
|
||||||
|
if (ret == null)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!ret.ContainsKey("RESULT"))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (ret["RESULT"].ToString().ToLower() != "true")
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool RemoveAgentFromGroupRole(string RequestingAgentID, string AgentID, UUID GroupID, UUID RoleID)
|
||||||
|
{
|
||||||
|
Dictionary<string, object> sendData = new Dictionary<string, object>();
|
||||||
|
sendData["AgentID"] = AgentID.ToString();
|
||||||
|
sendData["GroupID"] = GroupID.ToString();
|
||||||
|
sendData["RoleID"] = RoleID.ToString();
|
||||||
|
sendData["RequestingAgentID"] = RequestingAgentID;
|
||||||
|
sendData["OP"] = "DELETE";
|
||||||
|
|
||||||
|
Dictionary<string, object> ret = MakeRequest("AGENTROLE", sendData);
|
||||||
|
|
||||||
|
if (ret == null)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!ret.ContainsKey("RESULT"))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (ret["RESULT"].ToString().ToLower() != "true")
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<GroupRolesData> GetAgentGroupRoles(string RequestingAgentID, string AgentID, UUID GroupID)
|
||||||
|
{
|
||||||
|
List<GroupRolesData> roles = new List<GroupRolesData>();
|
||||||
|
|
||||||
|
Dictionary<string, object> sendData = new Dictionary<string, object>();
|
||||||
|
sendData["AgentID"] = AgentID.ToString();
|
||||||
|
sendData["GroupID"] = GroupID.ToString();
|
||||||
|
sendData["RequestingAgentID"] = RequestingAgentID;
|
||||||
|
Dictionary<string, object> ret = MakeRequest("GETAGENTROLES", sendData);
|
||||||
|
|
||||||
|
if (ret == null)
|
||||||
|
return roles;
|
||||||
|
|
||||||
|
if (!ret.ContainsKey("RESULT"))
|
||||||
|
return roles;
|
||||||
|
|
||||||
|
if (ret["RESULT"].ToString() == "NULL")
|
||||||
|
return roles;
|
||||||
|
|
||||||
|
foreach (object v in ((Dictionary<string, object>)ret["RESULT"]).Values)
|
||||||
|
{
|
||||||
|
GroupRolesData m = GroupsDataUtils.GroupRolesData((Dictionary<string, object>)v);
|
||||||
|
roles.Add(m);
|
||||||
|
}
|
||||||
|
|
||||||
|
return roles;
|
||||||
|
}
|
||||||
|
|
||||||
|
public GroupMembershipData SetAgentActiveGroup(string RequestingAgentID, string AgentID, UUID GroupID)
|
||||||
|
{
|
||||||
|
Dictionary<string, object> sendData = new Dictionary<string, object>();
|
||||||
|
sendData["AgentID"] = AgentID.ToString();
|
||||||
|
sendData["GroupID"] = GroupID.ToString();
|
||||||
|
sendData["RequestingAgentID"] = RequestingAgentID;
|
||||||
|
sendData["OP"] = "GROUP";
|
||||||
|
|
||||||
|
Dictionary<string, object> ret = MakeRequest("SETACTIVE", sendData);
|
||||||
|
|
||||||
|
if (ret == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
if (!ret.ContainsKey("RESULT"))
|
||||||
|
return null;
|
||||||
|
|
||||||
|
if (ret["RESULT"].ToString() == "NULL")
|
||||||
|
return null;
|
||||||
|
|
||||||
|
return GroupsDataUtils.GroupMembershipData((Dictionary<string, object>)ret["RESULT"]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetAgentActiveGroupRole(string RequestingAgentID, string AgentID, UUID GroupID, UUID RoleID)
|
||||||
|
{
|
||||||
|
Dictionary<string, object> sendData = new Dictionary<string, object>();
|
||||||
|
sendData["AgentID"] = AgentID.ToString();
|
||||||
|
sendData["GroupID"] = GroupID.ToString();
|
||||||
|
sendData["RoleID"] = RoleID.ToString();
|
||||||
|
sendData["RequestingAgentID"] = RequestingAgentID;
|
||||||
|
sendData["OP"] = "ROLE";
|
||||||
|
|
||||||
|
MakeRequest("SETACTIVE", sendData);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void UpdateMembership(string RequestingAgentID, string AgentID, UUID GroupID, bool AcceptNotices, bool ListInProfile)
|
||||||
|
{
|
||||||
|
Dictionary<string, object> sendData = new Dictionary<string, object>();
|
||||||
|
sendData["AgentID"] = AgentID.ToString();
|
||||||
|
sendData["GroupID"] = GroupID.ToString();
|
||||||
|
sendData["AcceptNotices"] = AcceptNotices.ToString();
|
||||||
|
sendData["ListInProfile"] = ListInProfile.ToString();
|
||||||
|
sendData["RequestingAgentID"] = RequestingAgentID;
|
||||||
|
MakeRequest("UPDATEMEMBERSHIP", sendData);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool AddAgentToGroupInvite(string RequestingAgentID, UUID inviteID, UUID groupID, UUID roleID, string agentID)
|
||||||
|
{
|
||||||
|
Dictionary<string, object> sendData = new Dictionary<string, object>();
|
||||||
|
sendData["InviteID"] = inviteID.ToString();
|
||||||
|
sendData["GroupID"] = groupID.ToString();
|
||||||
|
sendData["RoleID"] = roleID.ToString();
|
||||||
|
sendData["AgentID"] = agentID.ToString();
|
||||||
|
sendData["RequestingAgentID"] = RequestingAgentID;
|
||||||
|
sendData["OP"] = "ADD";
|
||||||
|
|
||||||
|
Dictionary<string, object> ret = MakeRequest("INVITE", sendData);
|
||||||
|
|
||||||
|
if (ret == null)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!ret.ContainsKey("RESULT"))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (ret["RESULT"].ToString().ToLower() != "true") // it may return "NULL"
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public GroupInviteInfo GetAgentToGroupInvite(string RequestingAgentID, UUID inviteID)
|
||||||
|
{
|
||||||
|
Dictionary<string, object> sendData = new Dictionary<string, object>();
|
||||||
|
sendData["InviteID"] = inviteID.ToString();
|
||||||
|
sendData["RequestingAgentID"] = RequestingAgentID;
|
||||||
|
sendData["OP"] = "GET";
|
||||||
|
|
||||||
|
Dictionary<string, object> ret = MakeRequest("INVITE", sendData);
|
||||||
|
|
||||||
|
if (ret == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
if (!ret.ContainsKey("RESULT"))
|
||||||
|
return null;
|
||||||
|
|
||||||
|
if (ret["RESULT"].ToString() == "NULL")
|
||||||
|
return null;
|
||||||
|
|
||||||
|
return GroupsDataUtils.GroupInviteInfo((Dictionary<string, object>)ret["RESULT"]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RemoveAgentToGroupInvite(string RequestingAgentID, UUID inviteID)
|
||||||
|
{
|
||||||
|
Dictionary<string, object> sendData = new Dictionary<string, object>();
|
||||||
|
sendData["InviteID"] = inviteID.ToString();
|
||||||
|
sendData["RequestingAgentID"] = RequestingAgentID;
|
||||||
|
sendData["OP"] = "DELETE";
|
||||||
|
|
||||||
|
MakeRequest("INVITE", sendData);
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
Dictionary<string, object> sendData = new Dictionary<string, object>();
|
||||||
|
sendData["GroupID"] = groupID.ToString();
|
||||||
|
sendData["NoticeID"] = noticeID.ToString();
|
||||||
|
sendData["FromName"] = GroupsDataUtils.Sanitize(fromName);
|
||||||
|
sendData["Subject"] = GroupsDataUtils.Sanitize(subject);
|
||||||
|
sendData["Message"] = GroupsDataUtils.Sanitize(message);
|
||||||
|
sendData["HasAttachment"] = hasAttachment.ToString();
|
||||||
|
if (hasAttachment)
|
||||||
|
{
|
||||||
|
sendData["AttachmentType"] = attType.ToString();
|
||||||
|
sendData["AttachmentName"] = attName.ToString();
|
||||||
|
sendData["AttachmentItemID"] = attItemID.ToString();
|
||||||
|
sendData["AttachmentOwnerID"] = attOwnerID;
|
||||||
|
}
|
||||||
|
sendData["RequestingAgentID"] = RequestingAgentID;
|
||||||
|
|
||||||
|
Dictionary<string, object> ret = MakeRequest("ADDNOTICE", sendData);
|
||||||
|
|
||||||
|
if (ret == null)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!ret.ContainsKey("RESULT"))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (ret["RESULT"].ToString().ToLower() != "true")
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public GroupNoticeInfo GetGroupNotice(string RequestingAgentID, UUID noticeID)
|
||||||
|
{
|
||||||
|
Dictionary<string, object> sendData = new Dictionary<string, object>();
|
||||||
|
sendData["NoticeID"] = noticeID.ToString();
|
||||||
|
sendData["RequestingAgentID"] = RequestingAgentID;
|
||||||
|
|
||||||
|
Dictionary<string, object> ret = MakeRequest("GETNOTICES", sendData);
|
||||||
|
|
||||||
|
if (ret == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
if (!ret.ContainsKey("RESULT"))
|
||||||
|
return null;
|
||||||
|
|
||||||
|
if (ret["RESULT"].ToString() == "NULL")
|
||||||
|
return null;
|
||||||
|
|
||||||
|
return GroupsDataUtils.GroupNoticeInfo((Dictionary<string, object>)ret["RESULT"]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<ExtendedGroupNoticeData> GetGroupNotices(string RequestingAgentID, UUID GroupID)
|
||||||
|
{
|
||||||
|
List<ExtendedGroupNoticeData> notices = new List<ExtendedGroupNoticeData>();
|
||||||
|
|
||||||
|
Dictionary<string, object> sendData = new Dictionary<string, object>();
|
||||||
|
sendData["GroupID"] = GroupID.ToString();
|
||||||
|
sendData["RequestingAgentID"] = RequestingAgentID;
|
||||||
|
Dictionary<string, object> ret = MakeRequest("GETNOTICES", sendData);
|
||||||
|
|
||||||
|
if (ret == null)
|
||||||
|
return notices;
|
||||||
|
|
||||||
|
if (!ret.ContainsKey("RESULT"))
|
||||||
|
return notices;
|
||||||
|
|
||||||
|
if (ret["RESULT"].ToString() == "NULL")
|
||||||
|
return notices;
|
||||||
|
|
||||||
|
foreach (object v in ((Dictionary<string, object>)ret["RESULT"]).Values)
|
||||||
|
{
|
||||||
|
ExtendedGroupNoticeData m = GroupsDataUtils.GroupNoticeData((Dictionary<string, object>)v);
|
||||||
|
notices.Add(m);
|
||||||
|
}
|
||||||
|
|
||||||
|
return notices;
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Make Request
|
||||||
|
|
||||||
|
private Dictionary<string, object> MakeRequest(string method, Dictionary<string, object> sendData)
|
||||||
|
{
|
||||||
|
sendData["METHOD"] = method;
|
||||||
|
|
||||||
|
string reply = string.Empty;
|
||||||
|
lock (m_Lock)
|
||||||
|
reply = SynchronousRestFormsRequester.MakeRequest("POST",
|
||||||
|
m_ServerURI + "groups",
|
||||||
|
ServerUtils.BuildQueryString(sendData),
|
||||||
|
m_Auth);
|
||||||
|
|
||||||
|
if (reply == string.Empty)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
Dictionary<string, object> replyData = ServerUtils.ParseXmlResponse(
|
||||||
|
reply);
|
||||||
|
|
||||||
|
return replyData;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,408 @@
|
||||||
|
/*
|
||||||
|
* 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.Reflection;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
using OpenSim.Framework;
|
||||||
|
using OpenSim.Region.Framework.Scenes;
|
||||||
|
using OpenSim.Region.Framework.Interfaces;
|
||||||
|
using OpenSim.Server.Base;
|
||||||
|
using OpenSim.Services.Interfaces;
|
||||||
|
|
||||||
|
using OpenMetaverse;
|
||||||
|
using Mono.Addins;
|
||||||
|
using log4net;
|
||||||
|
using Nini.Config;
|
||||||
|
|
||||||
|
namespace OpenSim.Groups
|
||||||
|
{
|
||||||
|
[Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "GroupsServiceRemoteConnectorModule")]
|
||||||
|
public class GroupsServiceRemoteConnectorModule : ISharedRegionModule, IGroupsServicesConnector
|
||||||
|
{
|
||||||
|
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
|
|
||||||
|
private bool m_Enabled = false;
|
||||||
|
private GroupsServiceRemoteConnector m_GroupsService;
|
||||||
|
private IUserManagement m_UserManagement;
|
||||||
|
private List<Scene> m_Scenes;
|
||||||
|
|
||||||
|
private RemoteConnectorCacheWrapper m_CacheWrapper;
|
||||||
|
|
||||||
|
#region constructors
|
||||||
|
public GroupsServiceRemoteConnectorModule()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public GroupsServiceRemoteConnectorModule(IConfigSource config, IUserManagement uman)
|
||||||
|
{
|
||||||
|
Init(config);
|
||||||
|
m_UserManagement = uman;
|
||||||
|
m_CacheWrapper = new RemoteConnectorCacheWrapper(m_UserManagement);
|
||||||
|
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
private void Init(IConfigSource config)
|
||||||
|
{
|
||||||
|
m_GroupsService = new GroupsServiceRemoteConnector(config);
|
||||||
|
m_Scenes = new List<Scene>();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#region ISharedRegionModule
|
||||||
|
|
||||||
|
public void Initialise(IConfigSource config)
|
||||||
|
{
|
||||||
|
IConfig groupsConfig = config.Configs["Groups"];
|
||||||
|
if (groupsConfig == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if ((groupsConfig.GetBoolean("Enabled", false) == false)
|
||||||
|
|| (groupsConfig.GetString("ServicesConnectorModule", string.Empty) != Name))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Init(config);
|
||||||
|
|
||||||
|
m_Enabled = true;
|
||||||
|
m_log.DebugFormat("[Groups.RemoteConnector]: Initializing {0}", this.Name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Name
|
||||||
|
{
|
||||||
|
get { return "Groups Remote Service Connector"; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public Type ReplaceableInterface
|
||||||
|
{
|
||||||
|
get { return null; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddRegion(Scene scene)
|
||||||
|
{
|
||||||
|
if (!m_Enabled)
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_log.DebugFormat("[Groups.RemoteConnector]: Registering {0} with {1}", this.Name, scene.RegionInfo.RegionName);
|
||||||
|
scene.RegisterModuleInterface<IGroupsServicesConnector>(this);
|
||||||
|
m_Scenes.Add(scene);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RemoveRegion(Scene scene)
|
||||||
|
{
|
||||||
|
if (!m_Enabled)
|
||||||
|
return;
|
||||||
|
|
||||||
|
scene.UnregisterModuleInterface<IGroupsServicesConnector>(this);
|
||||||
|
m_Scenes.Remove(scene);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RegionLoaded(Scene scene)
|
||||||
|
{
|
||||||
|
if (!m_Enabled)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (m_UserManagement == null)
|
||||||
|
{
|
||||||
|
m_UserManagement = scene.RequestModuleInterface<IUserManagement>();
|
||||||
|
m_CacheWrapper = new RemoteConnectorCacheWrapper(m_UserManagement);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void PostInitialise()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Close()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region IGroupsServicesConnector
|
||||||
|
|
||||||
|
public UUID CreateGroup(UUID RequestingAgentID, string name, string charter, bool showInList, UUID insigniaID, int membershipFee, bool openEnrollment,
|
||||||
|
bool allowPublish, bool maturePublish, UUID founderID, out string reason)
|
||||||
|
{
|
||||||
|
m_log.DebugFormat("[Groups.RemoteConnector]: Creating group {0}", name);
|
||||||
|
string r = string.Empty;
|
||||||
|
|
||||||
|
UUID groupID = m_CacheWrapper.CreateGroup(RequestingAgentID, delegate
|
||||||
|
{
|
||||||
|
return m_GroupsService.CreateGroup(RequestingAgentID.ToString(), name, charter, showInList, insigniaID,
|
||||||
|
membershipFee, openEnrollment, allowPublish, maturePublish, founderID, out r);
|
||||||
|
});
|
||||||
|
|
||||||
|
reason = r;
|
||||||
|
return groupID;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool UpdateGroup(string RequestingAgentID, UUID groupID, string charter, bool showInList, UUID insigniaID, int membershipFee,
|
||||||
|
bool openEnrollment, bool allowPublish, bool maturePublish, out string reason)
|
||||||
|
{
|
||||||
|
string r = string.Empty;
|
||||||
|
|
||||||
|
bool success = m_CacheWrapper.UpdateGroup(groupID, delegate
|
||||||
|
{
|
||||||
|
return m_GroupsService.UpdateGroup(RequestingAgentID, groupID, charter, showInList, insigniaID, membershipFee, openEnrollment, allowPublish, maturePublish);
|
||||||
|
});
|
||||||
|
|
||||||
|
reason = r;
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ExtendedGroupRecord GetGroupRecord(string RequestingAgentID, UUID GroupID, string GroupName)
|
||||||
|
{
|
||||||
|
if (GroupID == UUID.Zero && (GroupName == null || GroupName != null && GroupName == string.Empty))
|
||||||
|
return null;
|
||||||
|
|
||||||
|
return m_CacheWrapper.GetGroupRecord(RequestingAgentID,GroupID,GroupName, delegate
|
||||||
|
{
|
||||||
|
return m_GroupsService.GetGroupRecord(RequestingAgentID, GroupID, GroupName);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<DirGroupsReplyData> FindGroups(string RequestingAgentIDstr, string search)
|
||||||
|
{
|
||||||
|
// TODO!
|
||||||
|
return m_GroupsService.FindGroups(RequestingAgentIDstr, search);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool AddAgentToGroup(string RequestingAgentID, string AgentID, UUID GroupID, UUID RoleID, string token, out string reason)
|
||||||
|
{
|
||||||
|
string agentFullID = AgentID;
|
||||||
|
m_log.DebugFormat("[Groups.RemoteConnector]: Add agent {0} to group {1}", agentFullID, GroupID);
|
||||||
|
string r = string.Empty;
|
||||||
|
|
||||||
|
bool success = m_CacheWrapper.AddAgentToGroup(RequestingAgentID, AgentID, GroupID, delegate
|
||||||
|
{
|
||||||
|
return m_GroupsService.AddAgentToGroup(RequestingAgentID, agentFullID, GroupID, RoleID, token, out r);
|
||||||
|
});
|
||||||
|
|
||||||
|
reason = r;
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RemoveAgentFromGroup(string RequestingAgentID, string AgentID, UUID GroupID)
|
||||||
|
{
|
||||||
|
m_CacheWrapper.RemoveAgentFromGroup(RequestingAgentID, AgentID, GroupID, delegate
|
||||||
|
{
|
||||||
|
m_GroupsService.RemoveAgentFromGroup(RequestingAgentID, AgentID, GroupID);
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetAgentActiveGroup(string RequestingAgentID, string AgentID, UUID GroupID)
|
||||||
|
{
|
||||||
|
m_CacheWrapper.SetAgentActiveGroup(AgentID, delegate
|
||||||
|
{
|
||||||
|
return m_GroupsService.SetAgentActiveGroup(RequestingAgentID, AgentID, GroupID);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public ExtendedGroupMembershipData GetAgentActiveMembership(string RequestingAgentID, string AgentID)
|
||||||
|
{
|
||||||
|
return m_CacheWrapper.GetAgentActiveMembership(AgentID, delegate
|
||||||
|
{
|
||||||
|
return m_GroupsService.GetMembership(RequestingAgentID, AgentID, UUID.Zero);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public ExtendedGroupMembershipData GetAgentGroupMembership(string RequestingAgentID, string AgentID, UUID GroupID)
|
||||||
|
{
|
||||||
|
return m_CacheWrapper.GetAgentGroupMembership(AgentID, GroupID, delegate
|
||||||
|
{
|
||||||
|
return m_GroupsService.GetMembership(RequestingAgentID, AgentID, GroupID);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<GroupMembershipData> GetAgentGroupMemberships(string RequestingAgentID, string AgentID)
|
||||||
|
{
|
||||||
|
return m_CacheWrapper.GetAgentGroupMemberships(AgentID, delegate
|
||||||
|
{
|
||||||
|
return m_GroupsService.GetMemberships(RequestingAgentID, AgentID);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public List<GroupMembersData> GetGroupMembers(string RequestingAgentID, UUID GroupID)
|
||||||
|
{
|
||||||
|
return m_CacheWrapper.GetGroupMembers(RequestingAgentID, GroupID, delegate
|
||||||
|
{
|
||||||
|
return m_GroupsService.GetGroupMembers(RequestingAgentID, GroupID);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool AddGroupRole(string RequestingAgentID, UUID groupID, UUID roleID, string name, string description, string title, ulong powers, out string reason)
|
||||||
|
{
|
||||||
|
string r = string.Empty;
|
||||||
|
bool success = m_CacheWrapper.AddGroupRole(groupID, roleID, description, name, powers, title, delegate
|
||||||
|
{
|
||||||
|
return m_GroupsService.AddGroupRole(RequestingAgentID, groupID, roleID, name, description, title, powers, out r);
|
||||||
|
});
|
||||||
|
|
||||||
|
reason = r;
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool UpdateGroupRole(string RequestingAgentID, UUID groupID, UUID roleID, string name, string description, string title, ulong powers)
|
||||||
|
{
|
||||||
|
return m_CacheWrapper.UpdateGroupRole(groupID, roleID, name, description, title, powers, delegate
|
||||||
|
{
|
||||||
|
return m_GroupsService.UpdateGroupRole(RequestingAgentID, groupID, roleID, name, description, title, powers);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RemoveGroupRole(string RequestingAgentID, UUID groupID, UUID roleID)
|
||||||
|
{
|
||||||
|
m_CacheWrapper.RemoveGroupRole(RequestingAgentID, groupID, roleID, delegate
|
||||||
|
{
|
||||||
|
m_GroupsService.RemoveGroupRole(RequestingAgentID, groupID, roleID);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<GroupRolesData> GetGroupRoles(string RequestingAgentID, UUID GroupID)
|
||||||
|
{
|
||||||
|
return m_CacheWrapper.GetGroupRoles(RequestingAgentID, GroupID, delegate
|
||||||
|
{
|
||||||
|
return m_GroupsService.GetGroupRoles(RequestingAgentID, GroupID);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<GroupRoleMembersData> GetGroupRoleMembers(string RequestingAgentID, UUID GroupID)
|
||||||
|
{
|
||||||
|
return m_CacheWrapper.GetGroupRoleMembers(RequestingAgentID, GroupID, delegate
|
||||||
|
{
|
||||||
|
return m_GroupsService.GetGroupRoleMembers(RequestingAgentID, GroupID);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddAgentToGroupRole(string RequestingAgentID, string AgentID, UUID GroupID, UUID RoleID)
|
||||||
|
{
|
||||||
|
m_CacheWrapper.AddAgentToGroupRole(RequestingAgentID, AgentID, GroupID, RoleID, delegate
|
||||||
|
{
|
||||||
|
return m_GroupsService.AddAgentToGroupRole(RequestingAgentID, AgentID, GroupID, RoleID);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RemoveAgentFromGroupRole(string RequestingAgentID, string AgentID, UUID GroupID, UUID RoleID)
|
||||||
|
{
|
||||||
|
m_CacheWrapper.RemoveAgentFromGroupRole(RequestingAgentID, AgentID, GroupID, RoleID, delegate
|
||||||
|
{
|
||||||
|
return m_GroupsService.RemoveAgentFromGroupRole(RequestingAgentID, AgentID, GroupID, RoleID);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<GroupRolesData> GetAgentGroupRoles(string RequestingAgentID, string AgentID, UUID GroupID)
|
||||||
|
{
|
||||||
|
return m_CacheWrapper.GetAgentGroupRoles(RequestingAgentID, AgentID, GroupID, delegate
|
||||||
|
{
|
||||||
|
return m_GroupsService.GetAgentGroupRoles(RequestingAgentID, AgentID, GroupID); ;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetAgentActiveGroupRole(string RequestingAgentID, string AgentID, UUID GroupID, UUID RoleID)
|
||||||
|
{
|
||||||
|
m_CacheWrapper.SetAgentActiveGroupRole(AgentID, GroupID, delegate
|
||||||
|
{
|
||||||
|
m_GroupsService.SetAgentActiveGroupRole(RequestingAgentID, AgentID, GroupID, RoleID);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void UpdateMembership(string RequestingAgentID, string AgentID, UUID GroupID, bool AcceptNotices, bool ListInProfile)
|
||||||
|
{
|
||||||
|
m_CacheWrapper.UpdateMembership(AgentID, GroupID, AcceptNotices, ListInProfile, delegate
|
||||||
|
{
|
||||||
|
m_GroupsService.UpdateMembership(RequestingAgentID, AgentID, GroupID, AcceptNotices, ListInProfile);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool AddAgentToGroupInvite(string RequestingAgentID, UUID inviteID, UUID groupID, UUID roleID, string agentID)
|
||||||
|
{
|
||||||
|
return m_GroupsService.AddAgentToGroupInvite(RequestingAgentID, inviteID, groupID, roleID, agentID);
|
||||||
|
}
|
||||||
|
|
||||||
|
public GroupInviteInfo GetAgentToGroupInvite(string RequestingAgentID, UUID inviteID)
|
||||||
|
{
|
||||||
|
return m_GroupsService.GetAgentToGroupInvite(RequestingAgentID, inviteID);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RemoveAgentToGroupInvite(string RequestingAgentID, UUID inviteID)
|
||||||
|
{
|
||||||
|
m_GroupsService.RemoveAgentToGroupInvite(RequestingAgentID, inviteID);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool AddGroupNotice(string RequestingAgentID, UUID groupID, UUID noticeID, string fromName, string subject, string message,
|
||||||
|
bool hasAttachment, byte attType, string attName, UUID attItemID, string attOwnerID)
|
||||||
|
{
|
||||||
|
GroupNoticeInfo notice = new GroupNoticeInfo();
|
||||||
|
notice.GroupID = groupID;
|
||||||
|
notice.Message = message;
|
||||||
|
notice.noticeData = new ExtendedGroupNoticeData();
|
||||||
|
notice.noticeData.AttachmentItemID = attItemID;
|
||||||
|
notice.noticeData.AttachmentName = attName;
|
||||||
|
notice.noticeData.AttachmentOwnerID = attOwnerID.ToString();
|
||||||
|
notice.noticeData.AttachmentType = attType;
|
||||||
|
notice.noticeData.FromName = fromName;
|
||||||
|
notice.noticeData.HasAttachment = hasAttachment;
|
||||||
|
notice.noticeData.NoticeID = noticeID;
|
||||||
|
notice.noticeData.Subject = subject;
|
||||||
|
notice.noticeData.Timestamp = (uint)Util.UnixTimeSinceEpoch();
|
||||||
|
|
||||||
|
return m_CacheWrapper.AddGroupNotice(groupID, noticeID, notice, delegate
|
||||||
|
{
|
||||||
|
return m_GroupsService.AddGroupNotice(RequestingAgentID, groupID, noticeID, fromName, subject, message,
|
||||||
|
hasAttachment, attType, attName, attItemID, attOwnerID);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public GroupNoticeInfo GetGroupNotice(string RequestingAgentID, UUID noticeID)
|
||||||
|
{
|
||||||
|
return m_CacheWrapper.GetGroupNotice(noticeID, delegate
|
||||||
|
{
|
||||||
|
return m_GroupsService.GetGroupNotice(RequestingAgentID, noticeID);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<ExtendedGroupNoticeData> GetGroupNotices(string RequestingAgentID, UUID GroupID)
|
||||||
|
{
|
||||||
|
return m_CacheWrapper.GetGroupNotices(GroupID, delegate
|
||||||
|
{
|
||||||
|
return m_GroupsService.GetGroupNotices(RequestingAgentID, GroupID);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,817 @@
|
||||||
|
/*
|
||||||
|
* 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.Reflection;
|
||||||
|
using System.Text;
|
||||||
|
using System.Xml;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using Nini.Config;
|
||||||
|
using OpenSim.Framework;
|
||||||
|
using OpenSim.Server.Base;
|
||||||
|
using OpenSim.Services.Interfaces;
|
||||||
|
using OpenSim.Framework.Servers.HttpServer;
|
||||||
|
using OpenSim.Framework.ServiceAuth;
|
||||||
|
using OpenSim.Server.Handlers.Base;
|
||||||
|
using log4net;
|
||||||
|
using OpenMetaverse;
|
||||||
|
|
||||||
|
namespace OpenSim.Groups
|
||||||
|
{
|
||||||
|
public class GroupsServiceRobustConnector : ServiceConnector
|
||||||
|
{
|
||||||
|
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
|
|
||||||
|
private GroupsService m_GroupsService;
|
||||||
|
private string m_ConfigName = "Groups";
|
||||||
|
|
||||||
|
public GroupsServiceRobustConnector(IConfigSource config, IHttpServer server, string configName) :
|
||||||
|
base(config, server, configName)
|
||||||
|
{
|
||||||
|
string key = string.Empty;
|
||||||
|
if (configName != String.Empty)
|
||||||
|
m_ConfigName = 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);
|
||||||
|
|
||||||
|
IServiceAuth auth = ServiceAuth.Create(config, m_ConfigName);
|
||||||
|
|
||||||
|
server.AddStreamHandler(new GroupsServicePostHandler(m_GroupsService, auth));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class GroupsServicePostHandler : BaseStreamHandler
|
||||||
|
{
|
||||||
|
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
|
|
||||||
|
private GroupsService m_GroupsService;
|
||||||
|
|
||||||
|
public GroupsServicePostHandler(GroupsService service, IServiceAuth auth) :
|
||||||
|
base("POST", "/groups", auth)
|
||||||
|
{
|
||||||
|
m_GroupsService = service;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override byte[] ProcessRequest(string path, Stream requestData,
|
||||||
|
IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
|
||||||
|
{
|
||||||
|
string body;
|
||||||
|
using(StreamReader sr = new StreamReader(requestData))
|
||||||
|
body = sr.ReadToEnd();
|
||||||
|
|
||||||
|
body = body.Trim();
|
||||||
|
|
||||||
|
//m_log.DebugFormat("[XXX]: query String: {0}", body);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Dictionary<string, object> request =
|
||||||
|
ServerUtils.ParseQueryString(body);
|
||||||
|
|
||||||
|
if (!request.ContainsKey("METHOD"))
|
||||||
|
return FailureResult();
|
||||||
|
|
||||||
|
string method = request["METHOD"].ToString();
|
||||||
|
request.Remove("METHOD");
|
||||||
|
|
||||||
|
// m_log.DebugFormat("[Groups.Handler]: {0}", method);
|
||||||
|
switch (method)
|
||||||
|
{
|
||||||
|
case "PUTGROUP":
|
||||||
|
return HandleAddOrUpdateGroup(request);
|
||||||
|
case "GETGROUP":
|
||||||
|
return HandleGetGroup(request);
|
||||||
|
case "ADDAGENTTOGROUP":
|
||||||
|
return HandleAddAgentToGroup(request);
|
||||||
|
case "REMOVEAGENTFROMGROUP":
|
||||||
|
return HandleRemoveAgentFromGroup(request);
|
||||||
|
case "GETMEMBERSHIP":
|
||||||
|
return HandleGetMembership(request);
|
||||||
|
case "GETGROUPMEMBERS":
|
||||||
|
return HandleGetGroupMembers(request);
|
||||||
|
case "PUTROLE":
|
||||||
|
return HandlePutRole(request);
|
||||||
|
case "REMOVEROLE":
|
||||||
|
return HandleRemoveRole(request);
|
||||||
|
case "GETGROUPROLES":
|
||||||
|
return HandleGetGroupRoles(request);
|
||||||
|
case "GETROLEMEMBERS":
|
||||||
|
return HandleGetRoleMembers(request);
|
||||||
|
case "AGENTROLE":
|
||||||
|
return HandleAgentRole(request);
|
||||||
|
case "GETAGENTROLES":
|
||||||
|
return HandleGetAgentRoles(request);
|
||||||
|
case "SETACTIVE":
|
||||||
|
return HandleSetActive(request);
|
||||||
|
case "UPDATEMEMBERSHIP":
|
||||||
|
return HandleUpdateMembership(request);
|
||||||
|
case "INVITE":
|
||||||
|
return HandleInvite(request);
|
||||||
|
case "ADDNOTICE":
|
||||||
|
return HandleAddNotice(request);
|
||||||
|
case "GETNOTICES":
|
||||||
|
return HandleGetNotices(request);
|
||||||
|
case "FINDGROUPS":
|
||||||
|
return HandleFindGroups(request);
|
||||||
|
}
|
||||||
|
m_log.DebugFormat("[GROUPS HANDLER]: unknown method request: {0}", method);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
m_log.Error(string.Format("[GROUPS HANDLER]: Exception {0} ", e.Message), e);
|
||||||
|
}
|
||||||
|
|
||||||
|
return FailureResult();
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] HandleAddOrUpdateGroup(Dictionary<string, object> request)
|
||||||
|
{
|
||||||
|
Dictionary<string, object> result = new Dictionary<string, object>();
|
||||||
|
|
||||||
|
ExtendedGroupRecord grec = GroupsDataUtils.GroupRecord(request);
|
||||||
|
if (!request.ContainsKey("RequestingAgentID") || !request.ContainsKey("OP"))
|
||||||
|
NullResult(result, "Bad network data");
|
||||||
|
|
||||||
|
else
|
||||||
|
{
|
||||||
|
string RequestingAgentID = request["RequestingAgentID"].ToString();
|
||||||
|
string reason = string.Empty;
|
||||||
|
string op = request["OP"].ToString();
|
||||||
|
if (op == "ADD")
|
||||||
|
{
|
||||||
|
grec.GroupID = m_GroupsService.CreateGroup(RequestingAgentID, grec.GroupName, grec.Charter, grec.ShowInList, grec.GroupPicture, grec.MembershipFee,
|
||||||
|
grec.OpenEnrollment, grec.AllowPublish, grec.MaturePublish, grec.FounderID, out reason);
|
||||||
|
|
||||||
|
}
|
||||||
|
else if (op == "UPDATE")
|
||||||
|
{
|
||||||
|
m_GroupsService.UpdateGroup(RequestingAgentID, grec.GroupID, grec.Charter, grec.ShowInList, grec.GroupPicture, grec.MembershipFee,
|
||||||
|
grec.OpenEnrollment, grec.AllowPublish, grec.MaturePublish);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (grec.GroupID != UUID.Zero)
|
||||||
|
{
|
||||||
|
grec = m_GroupsService.GetGroupRecord(RequestingAgentID, grec.GroupID);
|
||||||
|
if (grec == null)
|
||||||
|
NullResult(result, "Internal Error");
|
||||||
|
else
|
||||||
|
result["RESULT"] = GroupsDataUtils.GroupRecord(grec);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
NullResult(result, reason);
|
||||||
|
}
|
||||||
|
|
||||||
|
string xmlString = ServerUtils.BuildXmlResponse(result);
|
||||||
|
|
||||||
|
//m_log.DebugFormat("[XXX]: resp string: {0}", xmlString);
|
||||||
|
return Util.UTF8NoBomEncoding.GetBytes(xmlString);
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] HandleGetGroup(Dictionary<string, object> request)
|
||||||
|
{
|
||||||
|
Dictionary<string, object> result = new Dictionary<string, object>();
|
||||||
|
|
||||||
|
if (!request.ContainsKey("RequestingAgentID"))
|
||||||
|
NullResult(result, "Bad network data");
|
||||||
|
else
|
||||||
|
{
|
||||||
|
string RequestingAgentID = request["RequestingAgentID"].ToString();
|
||||||
|
ExtendedGroupRecord grec = null;
|
||||||
|
if (request.ContainsKey("GroupID"))
|
||||||
|
{
|
||||||
|
UUID groupID = new UUID(request["GroupID"].ToString());
|
||||||
|
grec = m_GroupsService.GetGroupRecord(RequestingAgentID, groupID);
|
||||||
|
}
|
||||||
|
else if (request.ContainsKey("Name"))
|
||||||
|
{
|
||||||
|
string name = request["Name"].ToString();
|
||||||
|
grec = m_GroupsService.GetGroupRecord(RequestingAgentID, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (grec == null)
|
||||||
|
NullResult(result, "Group not found");
|
||||||
|
else
|
||||||
|
result["RESULT"] = GroupsDataUtils.GroupRecord(grec);
|
||||||
|
}
|
||||||
|
|
||||||
|
string xmlString = ServerUtils.BuildXmlResponse(result);
|
||||||
|
|
||||||
|
//m_log.DebugFormat("[XXX]: resp string: {0}", xmlString);
|
||||||
|
return Util.UTF8NoBomEncoding.GetBytes(xmlString);
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] HandleAddAgentToGroup(Dictionary<string, object> request)
|
||||||
|
{
|
||||||
|
Dictionary<string, object> result = new Dictionary<string, object>();
|
||||||
|
|
||||||
|
if (!request.ContainsKey("RequestingAgentID") || !request.ContainsKey("AgentID") ||
|
||||||
|
!request.ContainsKey("GroupID") || !request.ContainsKey("RoleID"))
|
||||||
|
NullResult(result, "Bad network data");
|
||||||
|
else
|
||||||
|
{
|
||||||
|
UUID groupID = new UUID(request["GroupID"].ToString());
|
||||||
|
UUID roleID = new UUID(request["RoleID"].ToString());
|
||||||
|
string agentID = request["AgentID"].ToString();
|
||||||
|
string requestingAgentID = request["RequestingAgentID"].ToString();
|
||||||
|
string token = string.Empty;
|
||||||
|
string reason = string.Empty;
|
||||||
|
|
||||||
|
if (request.ContainsKey("AccessToken"))
|
||||||
|
token = request["AccessToken"].ToString();
|
||||||
|
|
||||||
|
if (!m_GroupsService.AddAgentToGroup(requestingAgentID, agentID, groupID, roleID, token, out reason))
|
||||||
|
NullResult(result, reason);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
GroupMembershipData membership = m_GroupsService.GetAgentGroupMembership(requestingAgentID, agentID, groupID);
|
||||||
|
if (membership == null)
|
||||||
|
NullResult(result, "Internal error");
|
||||||
|
else
|
||||||
|
result["RESULT"] = GroupsDataUtils.GroupMembershipData((ExtendedGroupMembershipData)membership);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
string xmlString = ServerUtils.BuildXmlResponse(result);
|
||||||
|
|
||||||
|
//m_log.DebugFormat("[XXX]: resp string: {0}", xmlString);
|
||||||
|
return Util.UTF8NoBomEncoding.GetBytes(xmlString);
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] HandleRemoveAgentFromGroup(Dictionary<string, object> request)
|
||||||
|
{
|
||||||
|
Dictionary<string, object> result = new Dictionary<string, object>();
|
||||||
|
|
||||||
|
if (!request.ContainsKey("RequestingAgentID") || !request.ContainsKey("AgentID") || !request.ContainsKey("GroupID"))
|
||||||
|
NullResult(result, "Bad network data");
|
||||||
|
else
|
||||||
|
{
|
||||||
|
UUID groupID = new UUID(request["GroupID"].ToString());
|
||||||
|
string agentID = request["AgentID"].ToString();
|
||||||
|
string requestingAgentID = request["RequestingAgentID"].ToString();
|
||||||
|
|
||||||
|
if (!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);
|
||||||
|
return Util.UTF8NoBomEncoding.GetBytes(ServerUtils.BuildXmlResponse(result));
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] HandleGetMembership(Dictionary<string, object> request)
|
||||||
|
{
|
||||||
|
Dictionary<string, object> result = new Dictionary<string, object>();
|
||||||
|
|
||||||
|
if (!request.ContainsKey("RequestingAgentID") || !request.ContainsKey("AgentID"))
|
||||||
|
NullResult(result, "Bad network data");
|
||||||
|
else
|
||||||
|
{
|
||||||
|
string agentID = request["AgentID"].ToString();
|
||||||
|
UUID groupID = UUID.Zero;
|
||||||
|
if (request.ContainsKey("GroupID"))
|
||||||
|
groupID = new UUID(request["GroupID"].ToString());
|
||||||
|
string requestingAgentID = request["RequestingAgentID"].ToString();
|
||||||
|
bool all = request.ContainsKey("ALL");
|
||||||
|
|
||||||
|
if (!all)
|
||||||
|
{
|
||||||
|
ExtendedGroupMembershipData membership = null;
|
||||||
|
if (groupID == UUID.Zero)
|
||||||
|
{
|
||||||
|
membership = m_GroupsService.GetAgentActiveMembership(requestingAgentID, agentID);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
membership = m_GroupsService.GetAgentGroupMembership(requestingAgentID, agentID, groupID);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (membership == null)
|
||||||
|
NullResult(result, "No such membership");
|
||||||
|
else
|
||||||
|
result["RESULT"] = GroupsDataUtils.GroupMembershipData(membership);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
List<GroupMembershipData> memberships = m_GroupsService.GetAgentGroupMemberships(requestingAgentID, agentID);
|
||||||
|
if (memberships == null || (memberships != null && memberships.Count == 0))
|
||||||
|
{
|
||||||
|
NullResult(result, "No memberships");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Dictionary<string, object> dict = new Dictionary<string, object>();
|
||||||
|
int i = 0;
|
||||||
|
foreach (GroupMembershipData m in memberships)
|
||||||
|
dict["m-" + i++] = GroupsDataUtils.GroupMembershipData((ExtendedGroupMembershipData)m);
|
||||||
|
|
||||||
|
result["RESULT"] = dict;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
string xmlString = ServerUtils.BuildXmlResponse(result);
|
||||||
|
|
||||||
|
//m_log.DebugFormat("[XXX]: resp string: {0}", xmlString);
|
||||||
|
return Util.UTF8NoBomEncoding.GetBytes(xmlString);
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] HandleGetGroupMembers(Dictionary<string, object> request)
|
||||||
|
{
|
||||||
|
Dictionary<string, object> result = new Dictionary<string, object>();
|
||||||
|
|
||||||
|
if (!request.ContainsKey("RequestingAgentID") || !request.ContainsKey("GroupID"))
|
||||||
|
NullResult(result, "Bad network data");
|
||||||
|
else
|
||||||
|
{
|
||||||
|
UUID groupID = new UUID(request["GroupID"].ToString());
|
||||||
|
string requestingAgentID = request["RequestingAgentID"].ToString();
|
||||||
|
|
||||||
|
List<ExtendedGroupMembersData> members = m_GroupsService.GetGroupMembers(requestingAgentID, groupID);
|
||||||
|
if (members == null || (members != null && members.Count == 0))
|
||||||
|
{
|
||||||
|
NullResult(result, "No members");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Dictionary<string, object> dict = new Dictionary<string, object>();
|
||||||
|
int i = 0;
|
||||||
|
foreach (ExtendedGroupMembersData m in members)
|
||||||
|
{
|
||||||
|
dict["m-" + i++] = GroupsDataUtils.GroupMembersData(m);
|
||||||
|
}
|
||||||
|
|
||||||
|
result["RESULT"] = dict;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
string xmlString = ServerUtils.BuildXmlResponse(result);
|
||||||
|
|
||||||
|
//m_log.DebugFormat("[XXX]: resp string: {0}", xmlString);
|
||||||
|
return Util.UTF8NoBomEncoding.GetBytes(xmlString);
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] HandlePutRole(Dictionary<string, object> request)
|
||||||
|
{
|
||||||
|
Dictionary<string, object> result = new Dictionary<string, object>();
|
||||||
|
|
||||||
|
if (!request.ContainsKey("RequestingAgentID") || !request.ContainsKey("GroupID") || !request.ContainsKey("RoleID") ||
|
||||||
|
!request.ContainsKey("Name") || !request.ContainsKey("Description") || !request.ContainsKey("Title") ||
|
||||||
|
!request.ContainsKey("Powers") || !request.ContainsKey("OP"))
|
||||||
|
NullResult(result, "Bad network data");
|
||||||
|
|
||||||
|
else
|
||||||
|
{
|
||||||
|
string op = request["OP"].ToString();
|
||||||
|
string reason = string.Empty;
|
||||||
|
|
||||||
|
bool success = false;
|
||||||
|
if (op == "ADD")
|
||||||
|
success = m_GroupsService.AddGroupRole(request["RequestingAgentID"].ToString(), new UUID(request["GroupID"].ToString()),
|
||||||
|
new UUID(request["RoleID"].ToString()), request["Name"].ToString(), request["Description"].ToString(),
|
||||||
|
request["Title"].ToString(), UInt64.Parse(request["Powers"].ToString()), out reason);
|
||||||
|
|
||||||
|
else if (op == "UPDATE")
|
||||||
|
success = m_GroupsService.UpdateGroupRole(request["RequestingAgentID"].ToString(), new UUID(request["GroupID"].ToString()),
|
||||||
|
new UUID(request["RoleID"].ToString()), request["Name"].ToString(), request["Description"].ToString(),
|
||||||
|
request["Title"].ToString(), UInt64.Parse(request["Powers"].ToString()));
|
||||||
|
|
||||||
|
result["RESULT"] = success.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
string xmlString = ServerUtils.BuildXmlResponse(result);
|
||||||
|
|
||||||
|
//m_log.DebugFormat("[XXX]: resp string: {0}", xmlString);
|
||||||
|
return Util.UTF8NoBomEncoding.GetBytes(xmlString);
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] HandleRemoveRole(Dictionary<string, object> request)
|
||||||
|
{
|
||||||
|
Dictionary<string, object> result = new Dictionary<string, object>();
|
||||||
|
|
||||||
|
if (!request.ContainsKey("RequestingAgentID") || !request.ContainsKey("GroupID") || !request.ContainsKey("RoleID"))
|
||||||
|
NullResult(result, "Bad network data");
|
||||||
|
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_GroupsService.RemoveGroupRole(request["RequestingAgentID"].ToString(), new UUID(request["GroupID"].ToString()),
|
||||||
|
new UUID(request["RoleID"].ToString()));
|
||||||
|
result["RESULT"] = "true";
|
||||||
|
}
|
||||||
|
|
||||||
|
//m_log.DebugFormat("[XXX]: resp string: {0}", xmlString);
|
||||||
|
return Util.UTF8NoBomEncoding.GetBytes(ServerUtils.BuildXmlResponse(result));
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] HandleGetGroupRoles(Dictionary<string, object> request)
|
||||||
|
{
|
||||||
|
Dictionary<string, object> result = new Dictionary<string, object>();
|
||||||
|
|
||||||
|
if (!request.ContainsKey("RequestingAgentID") || !request.ContainsKey("GroupID"))
|
||||||
|
NullResult(result, "Bad network data");
|
||||||
|
else
|
||||||
|
{
|
||||||
|
UUID groupID = new UUID(request["GroupID"].ToString());
|
||||||
|
string requestingAgentID = request["RequestingAgentID"].ToString();
|
||||||
|
|
||||||
|
List<GroupRolesData> roles = m_GroupsService.GetGroupRoles(requestingAgentID, groupID);
|
||||||
|
if (roles == null || (roles != null && roles.Count == 0))
|
||||||
|
{
|
||||||
|
NullResult(result, "No members");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Dictionary<string, object> dict = new Dictionary<string, object>();
|
||||||
|
int i = 0;
|
||||||
|
foreach (GroupRolesData r in roles)
|
||||||
|
dict["r-" + i++] = GroupsDataUtils.GroupRolesData(r);
|
||||||
|
|
||||||
|
result["RESULT"] = dict;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
string xmlString = ServerUtils.BuildXmlResponse(result);
|
||||||
|
|
||||||
|
//m_log.DebugFormat("[XXX]: resp string: {0}", xmlString);
|
||||||
|
return Util.UTF8NoBomEncoding.GetBytes(xmlString);
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] HandleGetRoleMembers(Dictionary<string, object> request)
|
||||||
|
{
|
||||||
|
Dictionary<string, object> result = new Dictionary<string, object>();
|
||||||
|
|
||||||
|
if (!request.ContainsKey("RequestingAgentID") || !request.ContainsKey("GroupID"))
|
||||||
|
NullResult(result, "Bad network data");
|
||||||
|
else
|
||||||
|
{
|
||||||
|
UUID groupID = new UUID(request["GroupID"].ToString());
|
||||||
|
string requestingAgentID = request["RequestingAgentID"].ToString();
|
||||||
|
|
||||||
|
List<ExtendedGroupRoleMembersData> rmembers = m_GroupsService.GetGroupRoleMembers(requestingAgentID, groupID);
|
||||||
|
if (rmembers == null || (rmembers != null && rmembers.Count == 0))
|
||||||
|
{
|
||||||
|
NullResult(result, "No members");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Dictionary<string, object> dict = new Dictionary<string, object>();
|
||||||
|
int i = 0;
|
||||||
|
foreach (ExtendedGroupRoleMembersData rm in rmembers)
|
||||||
|
dict["rm-" + i++] = GroupsDataUtils.GroupRoleMembersData(rm);
|
||||||
|
|
||||||
|
result["RESULT"] = dict;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
string xmlString = ServerUtils.BuildXmlResponse(result);
|
||||||
|
|
||||||
|
//m_log.DebugFormat("[XXX]: resp string: {0}", xmlString);
|
||||||
|
return Util.UTF8NoBomEncoding.GetBytes(xmlString);
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] HandleAgentRole(Dictionary<string, object> request)
|
||||||
|
{
|
||||||
|
Dictionary<string, object> result = new Dictionary<string, object>();
|
||||||
|
|
||||||
|
if (!request.ContainsKey("RequestingAgentID") || !request.ContainsKey("GroupID") || !request.ContainsKey("RoleID") ||
|
||||||
|
!request.ContainsKey("AgentID") || !request.ContainsKey("OP"))
|
||||||
|
NullResult(result, "Bad network data");
|
||||||
|
|
||||||
|
else
|
||||||
|
{
|
||||||
|
string op = request["OP"].ToString();
|
||||||
|
|
||||||
|
bool success = false;
|
||||||
|
if (op == "ADD")
|
||||||
|
success = m_GroupsService.AddAgentToGroupRole(request["RequestingAgentID"].ToString(), request["AgentID"].ToString(),
|
||||||
|
new UUID(request["GroupID"].ToString()), new UUID(request["RoleID"].ToString()));
|
||||||
|
|
||||||
|
else if (op == "DELETE")
|
||||||
|
success = m_GroupsService.RemoveAgentFromGroupRole(request["RequestingAgentID"].ToString(), request["AgentID"].ToString(),
|
||||||
|
new UUID(request["GroupID"].ToString()), new UUID(request["RoleID"].ToString()));
|
||||||
|
|
||||||
|
result["RESULT"] = success.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
string xmlString = ServerUtils.BuildXmlResponse(result);
|
||||||
|
|
||||||
|
//m_log.DebugFormat("[XXX]: resp string: {0}", xmlString);
|
||||||
|
return Util.UTF8NoBomEncoding.GetBytes(xmlString);
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] HandleGetAgentRoles(Dictionary<string, object> request)
|
||||||
|
{
|
||||||
|
Dictionary<string, object> result = new Dictionary<string, object>();
|
||||||
|
|
||||||
|
if (!request.ContainsKey("RequestingAgentID") || !request.ContainsKey("GroupID") || !request.ContainsKey("AgentID"))
|
||||||
|
NullResult(result, "Bad network data");
|
||||||
|
else
|
||||||
|
{
|
||||||
|
UUID groupID = new UUID(request["GroupID"].ToString());
|
||||||
|
string agentID = request["AgentID"].ToString();
|
||||||
|
string requestingAgentID = request["RequestingAgentID"].ToString();
|
||||||
|
|
||||||
|
List<GroupRolesData> roles = m_GroupsService.GetAgentGroupRoles(requestingAgentID, agentID, groupID);
|
||||||
|
if (roles == null || (roles != null && roles.Count == 0))
|
||||||
|
{
|
||||||
|
NullResult(result, "No members");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Dictionary<string, object> dict = new Dictionary<string, object>();
|
||||||
|
int i = 0;
|
||||||
|
foreach (GroupRolesData r in roles)
|
||||||
|
dict["r-" + i++] = GroupsDataUtils.GroupRolesData(r);
|
||||||
|
|
||||||
|
result["RESULT"] = dict;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
string xmlString = ServerUtils.BuildXmlResponse(result);
|
||||||
|
|
||||||
|
//m_log.DebugFormat("[XXX]: resp string: {0}", xmlString);
|
||||||
|
return Util.UTF8NoBomEncoding.GetBytes(xmlString);
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] HandleSetActive(Dictionary<string, object> request)
|
||||||
|
{
|
||||||
|
Dictionary<string, object> result = new Dictionary<string, object>();
|
||||||
|
|
||||||
|
if (!request.ContainsKey("RequestingAgentID") || !request.ContainsKey("GroupID") ||
|
||||||
|
!request.ContainsKey("AgentID") || !request.ContainsKey("OP"))
|
||||||
|
{
|
||||||
|
NullResult(result, "Bad network data");
|
||||||
|
string xmlString = ServerUtils.BuildXmlResponse(result);
|
||||||
|
return Util.UTF8NoBomEncoding.GetBytes(xmlString);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
string op = request["OP"].ToString();
|
||||||
|
|
||||||
|
if (op == "GROUP")
|
||||||
|
{
|
||||||
|
ExtendedGroupMembershipData group = m_GroupsService.SetAgentActiveGroup(request["RequestingAgentID"].ToString(),
|
||||||
|
request["AgentID"].ToString(), new UUID(request["GroupID"].ToString()));
|
||||||
|
|
||||||
|
if (group == null)
|
||||||
|
NullResult(result, "Internal error");
|
||||||
|
else
|
||||||
|
result["RESULT"] = GroupsDataUtils.GroupMembershipData(group);
|
||||||
|
|
||||||
|
string xmlString = ServerUtils.BuildXmlResponse(result);
|
||||||
|
|
||||||
|
//m_log.DebugFormat("[XXX]: resp string: {0}", xmlString);
|
||||||
|
return Util.UTF8NoBomEncoding.GetBytes(xmlString);
|
||||||
|
|
||||||
|
}
|
||||||
|
else if (op == "ROLE" && request.ContainsKey("RoleID"))
|
||||||
|
{
|
||||||
|
m_GroupsService.SetAgentActiveGroupRole(request["RequestingAgentID"].ToString(), request["AgentID"].ToString(),
|
||||||
|
new UUID(request["GroupID"].ToString()), new UUID(request["RoleID"].ToString()));
|
||||||
|
result["RESULT"] = "true";
|
||||||
|
}
|
||||||
|
|
||||||
|
return Util.UTF8NoBomEncoding.GetBytes(ServerUtils.BuildXmlResponse(result));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] HandleUpdateMembership(Dictionary<string, object> request)
|
||||||
|
{
|
||||||
|
Dictionary<string, object> result = new Dictionary<string, object>();
|
||||||
|
|
||||||
|
if (!request.ContainsKey("RequestingAgentID") || !request.ContainsKey("AgentID") || !request.ContainsKey("GroupID") ||
|
||||||
|
!request.ContainsKey("AcceptNotices") || !request.ContainsKey("ListInProfile"))
|
||||||
|
NullResult(result, "Bad network data");
|
||||||
|
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_GroupsService.UpdateMembership(request["RequestingAgentID"].ToString(), request["AgentID"].ToString(), new UUID(request["GroupID"].ToString()),
|
||||||
|
bool.Parse(request["AcceptNotices"].ToString()), bool.Parse(request["ListInProfile"].ToString()));
|
||||||
|
|
||||||
|
result["RESULT"] = "true";
|
||||||
|
}
|
||||||
|
|
||||||
|
//m_log.DebugFormat("[XXX]: resp string: {0}", xmlString);
|
||||||
|
return Util.UTF8NoBomEncoding.GetBytes(ServerUtils.BuildXmlResponse(result));
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] HandleInvite(Dictionary<string, object> request)
|
||||||
|
{
|
||||||
|
Dictionary<string, object> result = new Dictionary<string, object>();
|
||||||
|
|
||||||
|
if (!request.ContainsKey("RequestingAgentID") || !request.ContainsKey("InviteID"))
|
||||||
|
{
|
||||||
|
NullResult(result, "Bad network data");
|
||||||
|
string xmlString = ServerUtils.BuildXmlResponse(result);
|
||||||
|
return Util.UTF8NoBomEncoding.GetBytes(xmlString);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
string op = request["OP"].ToString();
|
||||||
|
|
||||||
|
if (op == "ADD" && request.ContainsKey("GroupID") && request.ContainsKey("RoleID") && request.ContainsKey("AgentID"))
|
||||||
|
{
|
||||||
|
bool success = m_GroupsService.AddAgentToGroupInvite(request["RequestingAgentID"].ToString(),
|
||||||
|
new UUID(request["InviteID"].ToString()), new UUID(request["GroupID"].ToString()),
|
||||||
|
new UUID(request["RoleID"].ToString()), request["AgentID"].ToString());
|
||||||
|
|
||||||
|
result["RESULT"] = success.ToString();
|
||||||
|
return Util.UTF8NoBomEncoding.GetBytes(ServerUtils.BuildXmlResponse(result));
|
||||||
|
|
||||||
|
}
|
||||||
|
else if (op == "DELETE")
|
||||||
|
{
|
||||||
|
m_GroupsService.RemoveAgentToGroupInvite(request["RequestingAgentID"].ToString(), new UUID(request["InviteID"].ToString()));
|
||||||
|
result["RESULT"] = "true";
|
||||||
|
return Util.UTF8NoBomEncoding.GetBytes(ServerUtils.BuildXmlResponse(result));
|
||||||
|
}
|
||||||
|
else if (op == "GET")
|
||||||
|
{
|
||||||
|
GroupInviteInfo invite = m_GroupsService.GetAgentToGroupInvite(request["RequestingAgentID"].ToString(),
|
||||||
|
new UUID(request["InviteID"].ToString()));
|
||||||
|
|
||||||
|
if (invite != null)
|
||||||
|
result["RESULT"] = GroupsDataUtils.GroupInviteInfo(invite);
|
||||||
|
else
|
||||||
|
result["RESULT"] = "NULL";
|
||||||
|
|
||||||
|
return Util.UTF8NoBomEncoding.GetBytes(ServerUtils.BuildXmlResponse(result));
|
||||||
|
}
|
||||||
|
|
||||||
|
NullResult(result, "Bad OP in request");
|
||||||
|
return Util.UTF8NoBomEncoding.GetBytes(ServerUtils.BuildXmlResponse(result));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] HandleAddNotice(Dictionary<string, object> request)
|
||||||
|
{
|
||||||
|
Dictionary<string, object> result = new Dictionary<string, object>();
|
||||||
|
|
||||||
|
if (!request.ContainsKey("RequestingAgentID") || !request.ContainsKey("GroupID") || !request.ContainsKey("NoticeID") ||
|
||||||
|
!request.ContainsKey("FromName") || !request.ContainsKey("Subject") || !request.ContainsKey("Message") ||
|
||||||
|
!request.ContainsKey("HasAttachment"))
|
||||||
|
NullResult(result, "Bad network data");
|
||||||
|
|
||||||
|
else
|
||||||
|
{
|
||||||
|
|
||||||
|
bool hasAtt = bool.Parse(request["HasAttachment"].ToString());
|
||||||
|
byte attType = 0;
|
||||||
|
string attName = string.Empty;
|
||||||
|
string attOwner = string.Empty;
|
||||||
|
UUID attItem = UUID.Zero;
|
||||||
|
if (request.ContainsKey("AttachmentType"))
|
||||||
|
attType = byte.Parse(request["AttachmentType"].ToString());
|
||||||
|
if (request.ContainsKey("AttachmentName"))
|
||||||
|
attName = request["AttachmentName"].ToString();
|
||||||
|
if (request.ContainsKey("AttachmentItemID"))
|
||||||
|
attItem = new UUID(request["AttachmentItemID"].ToString());
|
||||||
|
if (request.ContainsKey("AttachmentOwnerID"))
|
||||||
|
attOwner = request["AttachmentOwnerID"].ToString();
|
||||||
|
|
||||||
|
bool success = m_GroupsService.AddGroupNotice(request["RequestingAgentID"].ToString(), new UUID(request["GroupID"].ToString()),
|
||||||
|
new UUID(request["NoticeID"].ToString()), request["FromName"].ToString(), request["Subject"].ToString(),
|
||||||
|
request["Message"].ToString(), hasAtt, attType, attName, attItem, attOwner);
|
||||||
|
|
||||||
|
result["RESULT"] = success.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
string xmlString = ServerUtils.BuildXmlResponse(result);
|
||||||
|
|
||||||
|
//m_log.DebugFormat("[XXX]: resp string: {0}", xmlString);
|
||||||
|
return Util.UTF8NoBomEncoding.GetBytes(xmlString);
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] HandleGetNotices(Dictionary<string, object> request)
|
||||||
|
{
|
||||||
|
Dictionary<string, object> result = new Dictionary<string, object>();
|
||||||
|
|
||||||
|
if (!request.ContainsKey("RequestingAgentID"))
|
||||||
|
NullResult(result, "Bad network data");
|
||||||
|
|
||||||
|
else if (request.ContainsKey("NoticeID")) // just one
|
||||||
|
{
|
||||||
|
GroupNoticeInfo notice = m_GroupsService.GetGroupNotice(request["RequestingAgentID"].ToString(), new UUID(request["NoticeID"].ToString()));
|
||||||
|
|
||||||
|
if (notice == null)
|
||||||
|
NullResult(result, "NO such notice");
|
||||||
|
else
|
||||||
|
result["RESULT"] = GroupsDataUtils.GroupNoticeInfo(notice);
|
||||||
|
|
||||||
|
}
|
||||||
|
else if (request.ContainsKey("GroupID")) // all notices for group
|
||||||
|
{
|
||||||
|
List<ExtendedGroupNoticeData> notices = m_GroupsService.GetGroupNotices(request["RequestingAgentID"].ToString(), new UUID(request["GroupID"].ToString()));
|
||||||
|
|
||||||
|
if (notices == null || (notices != null && notices.Count == 0))
|
||||||
|
NullResult(result, "No notices");
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Dictionary<string, object> dict = new Dictionary<string, object>();
|
||||||
|
int i = 0;
|
||||||
|
foreach (ExtendedGroupNoticeData n in notices)
|
||||||
|
dict["n-" + i++] = GroupsDataUtils.GroupNoticeData(n);
|
||||||
|
|
||||||
|
result["RESULT"] = dict;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
NullResult(result, "Bad OP in request");
|
||||||
|
|
||||||
|
string xmlString = ServerUtils.BuildXmlResponse(result);
|
||||||
|
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
|
||||||
|
|
||||||
|
private void NullResult(Dictionary<string, object> result, string reason)
|
||||||
|
{
|
||||||
|
result["RESULT"] = "NULL";
|
||||||
|
result["REASON"] = reason;
|
||||||
|
}
|
||||||
|
|
||||||
|
private byte[] FailureResult()
|
||||||
|
{
|
||||||
|
Dictionary<string, object> result = new Dictionary<string, object>();
|
||||||
|
NullResult(result, "Unknown method");
|
||||||
|
string xmlString = ServerUtils.BuildXmlResponse(result);
|
||||||
|
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
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,888 @@
|
||||||
|
/*
|
||||||
|
* 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.Reflection;
|
||||||
|
using System.Threading;
|
||||||
|
|
||||||
|
using OpenSim.Framework;
|
||||||
|
//using OpenSim.Region.Framework.Interfaces;
|
||||||
|
using OpenSim.Services.Interfaces;
|
||||||
|
|
||||||
|
using OpenMetaverse;
|
||||||
|
|
||||||
|
namespace OpenSim.Groups
|
||||||
|
{
|
||||||
|
public delegate ExtendedGroupRecord GroupRecordDelegate();
|
||||||
|
public delegate GroupMembershipData GroupMembershipDelegate();
|
||||||
|
public delegate List<GroupMembershipData> GroupMembershipListDelegate();
|
||||||
|
public delegate List<ExtendedGroupMembersData> GroupMembersListDelegate();
|
||||||
|
public delegate List<GroupRolesData> GroupRolesListDelegate();
|
||||||
|
public delegate List<ExtendedGroupRoleMembersData> RoleMembersListDelegate();
|
||||||
|
public delegate GroupNoticeInfo NoticeDelegate();
|
||||||
|
public delegate List<ExtendedGroupNoticeData> NoticeListDelegate();
|
||||||
|
public delegate void VoidDelegate();
|
||||||
|
public delegate bool BooleanDelegate();
|
||||||
|
|
||||||
|
public class RemoteConnectorCacheWrapper
|
||||||
|
{
|
||||||
|
private ForeignImporter m_ForeignImporter;
|
||||||
|
|
||||||
|
private Dictionary<string, bool> m_ActiveRequests = new Dictionary<string, bool>();
|
||||||
|
private const int GROUPS_CACHE_TIMEOUT = 1 * 60; // 1 minutes
|
||||||
|
|
||||||
|
// This all important cache cahces objects of different types:
|
||||||
|
// group-<GroupID> or group-<Name> => ExtendedGroupRecord
|
||||||
|
// active-<AgentID> => GroupMembershipData
|
||||||
|
// membership-<AgentID>-<GroupID> => GroupMembershipData
|
||||||
|
// memberships-<AgentID> => List<GroupMembershipData>
|
||||||
|
// members-<RequestingAgentID>-<GroupID> => List<ExtendedGroupMembersData>
|
||||||
|
// role-<RoleID> => GroupRolesData
|
||||||
|
// roles-<GroupID> => List<GroupRolesData> ; all roles in the group
|
||||||
|
// roles-<GroupID>-<AgentID> => List<GroupRolesData> ; roles that the agent has
|
||||||
|
// rolemembers-<RequestingAgentID>-<GroupID> => List<ExtendedGroupRoleMembersData>
|
||||||
|
// notice-<noticeID> => GroupNoticeInfo
|
||||||
|
// notices-<GroupID> => List<ExtendedGroupNoticeData>
|
||||||
|
private ExpiringCache<string, object> m_Cache = new ExpiringCache<string, object>();
|
||||||
|
|
||||||
|
public RemoteConnectorCacheWrapper(IUserManagement uman)
|
||||||
|
{
|
||||||
|
m_ForeignImporter = new ForeignImporter(uman);
|
||||||
|
}
|
||||||
|
|
||||||
|
public UUID CreateGroup(UUID RequestingAgentID, GroupRecordDelegate d)
|
||||||
|
{
|
||||||
|
//m_log.DebugFormat("[Groups.RemoteConnector]: Creating group {0}", name);
|
||||||
|
//reason = string.Empty;
|
||||||
|
|
||||||
|
//ExtendedGroupRecord group = m_GroupsService.CreateGroup(RequestingAgentID.ToString(), name, charter, showInList, insigniaID,
|
||||||
|
// membershipFee, openEnrollment, allowPublish, maturePublish, founderID, out reason);
|
||||||
|
ExtendedGroupRecord group = d();
|
||||||
|
|
||||||
|
if (group == null)
|
||||||
|
return UUID.Zero;
|
||||||
|
|
||||||
|
if (group.GroupID != UUID.Zero)
|
||||||
|
lock (m_Cache)
|
||||||
|
{
|
||||||
|
m_Cache.Add("group-" + group.GroupID.ToString(), group, GROUPS_CACHE_TIMEOUT);
|
||||||
|
if (m_Cache.Contains("memberships-" + RequestingAgentID.ToString()))
|
||||||
|
m_Cache.Remove("memberships-" + RequestingAgentID.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
return group.GroupID;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool UpdateGroup(UUID groupID, GroupRecordDelegate d)
|
||||||
|
{
|
||||||
|
//reason = string.Empty;
|
||||||
|
//ExtendedGroupRecord group = m_GroupsService.UpdateGroup(RequestingAgentID, groupID, charter, showInList, insigniaID, membershipFee, openEnrollment, allowPublish, maturePublish);
|
||||||
|
ExtendedGroupRecord group = d();
|
||||||
|
|
||||||
|
if (group != null && group.GroupID != UUID.Zero)
|
||||||
|
lock (m_Cache)
|
||||||
|
m_Cache.AddOrUpdate("group-" + group.GroupID.ToString(), group, GROUPS_CACHE_TIMEOUT);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ExtendedGroupRecord GetGroupRecord(string RequestingAgentID, UUID GroupID, string GroupName, GroupRecordDelegate d)
|
||||||
|
{
|
||||||
|
//if (GroupID == UUID.Zero && (GroupName == null || GroupName != null && GroupName == string.Empty))
|
||||||
|
// return null;
|
||||||
|
|
||||||
|
object group = null;
|
||||||
|
bool firstCall = false;
|
||||||
|
string cacheKey = "group-";
|
||||||
|
if (GroupID != UUID.Zero)
|
||||||
|
cacheKey += GroupID.ToString();
|
||||||
|
else
|
||||||
|
cacheKey += GroupName;
|
||||||
|
|
||||||
|
//m_log.DebugFormat("[XXX]: GetGroupRecord {0}", cacheKey);
|
||||||
|
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
lock (m_Cache)
|
||||||
|
{
|
||||||
|
if (m_Cache.TryGetValue(cacheKey, out group))
|
||||||
|
{
|
||||||
|
//m_log.DebugFormat("[XXX]: GetGroupRecord {0} cached!", cacheKey);
|
||||||
|
return (ExtendedGroupRecord)group;
|
||||||
|
}
|
||||||
|
|
||||||
|
// not cached
|
||||||
|
if (!m_ActiveRequests.ContainsKey(cacheKey))
|
||||||
|
{
|
||||||
|
m_ActiveRequests.Add(cacheKey, true);
|
||||||
|
firstCall = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (firstCall)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
//group = m_GroupsService.GetGroupRecord(RequestingAgentID, GroupID, GroupName);
|
||||||
|
group = d();
|
||||||
|
|
||||||
|
lock (m_Cache)
|
||||||
|
{
|
||||||
|
m_Cache.AddOrUpdate(cacheKey, group, GROUPS_CACHE_TIMEOUT);
|
||||||
|
return (ExtendedGroupRecord)group;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
m_ActiveRequests.Remove(cacheKey);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
Thread.Sleep(50);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool AddAgentToGroup(string RequestingAgentID, string AgentID, UUID GroupID, GroupMembershipDelegate d)
|
||||||
|
{
|
||||||
|
GroupMembershipData membership = d();
|
||||||
|
if (membership == null)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
lock (m_Cache)
|
||||||
|
{
|
||||||
|
// first, remove everything! add a user is a heavy-duty op
|
||||||
|
m_Cache.Clear();
|
||||||
|
|
||||||
|
m_Cache.AddOrUpdate("active-" + AgentID.ToString(), membership, GROUPS_CACHE_TIMEOUT);
|
||||||
|
m_Cache.AddOrUpdate("membership-" + AgentID.ToString() + "-" + GroupID.ToString(), membership, GROUPS_CACHE_TIMEOUT);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RemoveAgentFromGroup(string RequestingAgentID, string AgentID, UUID GroupID, VoidDelegate d)
|
||||||
|
{
|
||||||
|
d();
|
||||||
|
|
||||||
|
lock (m_Cache)
|
||||||
|
{
|
||||||
|
string cacheKey = "active-" + AgentID.ToString();
|
||||||
|
if (m_Cache.Contains(cacheKey))
|
||||||
|
m_Cache.Remove(cacheKey);
|
||||||
|
|
||||||
|
cacheKey = "memberships-" + AgentID.ToString();
|
||||||
|
if (m_Cache.Contains(cacheKey))
|
||||||
|
m_Cache.Remove(cacheKey);
|
||||||
|
|
||||||
|
cacheKey = "membership-" + AgentID.ToString() + "-" + GroupID.ToString();
|
||||||
|
if (m_Cache.Contains(cacheKey))
|
||||||
|
m_Cache.Remove(cacheKey);
|
||||||
|
|
||||||
|
cacheKey = "members-" + RequestingAgentID.ToString() + "-" + GroupID.ToString();
|
||||||
|
if (m_Cache.Contains(cacheKey))
|
||||||
|
m_Cache.Remove(cacheKey);
|
||||||
|
|
||||||
|
cacheKey = "roles-" + "-" + GroupID.ToString() + "-" + AgentID.ToString();
|
||||||
|
if (m_Cache.Contains(cacheKey))
|
||||||
|
m_Cache.Remove(cacheKey);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetAgentActiveGroup(string AgentID, GroupMembershipDelegate d)
|
||||||
|
{
|
||||||
|
GroupMembershipData activeGroup = d();
|
||||||
|
string cacheKey = "active-" + AgentID.ToString();
|
||||||
|
lock (m_Cache)
|
||||||
|
if (m_Cache.Contains(cacheKey))
|
||||||
|
m_Cache.AddOrUpdate(cacheKey, activeGroup, GROUPS_CACHE_TIMEOUT);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ExtendedGroupMembershipData GetAgentActiveMembership(string AgentID, GroupMembershipDelegate d)
|
||||||
|
{
|
||||||
|
object membership = null;
|
||||||
|
bool firstCall = false;
|
||||||
|
string cacheKey = "active-" + AgentID.ToString();
|
||||||
|
|
||||||
|
//m_log.DebugFormat("[XXX]: GetAgentActiveMembership {0}", cacheKey);
|
||||||
|
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
lock (m_Cache)
|
||||||
|
{
|
||||||
|
if (m_Cache.TryGetValue(cacheKey, out membership))
|
||||||
|
{
|
||||||
|
//m_log.DebugFormat("[XXX]: GetAgentActiveMembership {0} cached!", cacheKey);
|
||||||
|
return (ExtendedGroupMembershipData)membership;
|
||||||
|
}
|
||||||
|
|
||||||
|
// not cached
|
||||||
|
if (!m_ActiveRequests.ContainsKey(cacheKey))
|
||||||
|
{
|
||||||
|
m_ActiveRequests.Add(cacheKey, true);
|
||||||
|
firstCall = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (firstCall)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
membership = d();
|
||||||
|
|
||||||
|
lock (m_Cache)
|
||||||
|
{
|
||||||
|
m_Cache.AddOrUpdate(cacheKey, membership, GROUPS_CACHE_TIMEOUT);
|
||||||
|
return (ExtendedGroupMembershipData)membership;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
m_ActiveRequests.Remove(cacheKey);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
Thread.Sleep(50);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public ExtendedGroupMembershipData GetAgentGroupMembership(string AgentID, UUID GroupID, GroupMembershipDelegate d)
|
||||||
|
{
|
||||||
|
object membership = null;
|
||||||
|
bool firstCall = false;
|
||||||
|
string cacheKey = "membership-" + AgentID.ToString() + "-" + GroupID.ToString();
|
||||||
|
|
||||||
|
//m_log.DebugFormat("[XXX]: GetAgentGroupMembership {0}", cacheKey);
|
||||||
|
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
lock (m_Cache)
|
||||||
|
{
|
||||||
|
if (m_Cache.TryGetValue(cacheKey, out membership))
|
||||||
|
{
|
||||||
|
//m_log.DebugFormat("[XXX]: GetAgentGroupMembership {0}", cacheKey);
|
||||||
|
return (ExtendedGroupMembershipData)membership;
|
||||||
|
}
|
||||||
|
|
||||||
|
// not cached
|
||||||
|
if (!m_ActiveRequests.ContainsKey(cacheKey))
|
||||||
|
{
|
||||||
|
m_ActiveRequests.Add(cacheKey, true);
|
||||||
|
firstCall = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (firstCall)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
membership = d();
|
||||||
|
lock (m_Cache)
|
||||||
|
{
|
||||||
|
m_Cache.AddOrUpdate(cacheKey, membership, GROUPS_CACHE_TIMEOUT);
|
||||||
|
return (ExtendedGroupMembershipData)membership;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
m_ActiveRequests.Remove(cacheKey);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
Thread.Sleep(50);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<GroupMembershipData> GetAgentGroupMemberships(string AgentID, GroupMembershipListDelegate d)
|
||||||
|
{
|
||||||
|
object memberships = null;
|
||||||
|
bool firstCall = false;
|
||||||
|
string cacheKey = "memberships-" + AgentID.ToString();
|
||||||
|
|
||||||
|
//m_log.DebugFormat("[XXX]: GetAgentGroupMemberships {0}", cacheKey);
|
||||||
|
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
lock (m_Cache)
|
||||||
|
{
|
||||||
|
if (m_Cache.TryGetValue(cacheKey, out memberships))
|
||||||
|
{
|
||||||
|
//m_log.DebugFormat("[XXX]: GetAgentGroupMemberships {0} cached!", cacheKey);
|
||||||
|
return (List<GroupMembershipData>)memberships;
|
||||||
|
}
|
||||||
|
|
||||||
|
// not cached
|
||||||
|
if (!m_ActiveRequests.ContainsKey(cacheKey))
|
||||||
|
{
|
||||||
|
m_ActiveRequests.Add(cacheKey, true);
|
||||||
|
firstCall = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (firstCall)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
memberships = d();
|
||||||
|
lock (m_Cache)
|
||||||
|
{
|
||||||
|
m_Cache.AddOrUpdate(cacheKey, memberships, GROUPS_CACHE_TIMEOUT);
|
||||||
|
return (List<GroupMembershipData>)memberships;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
m_ActiveRequests.Remove(cacheKey);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
Thread.Sleep(50);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<GroupMembersData> GetGroupMembers(string RequestingAgentID, UUID GroupID, GroupMembersListDelegate d)
|
||||||
|
{
|
||||||
|
object members = null;
|
||||||
|
bool firstCall = false;
|
||||||
|
// we need to key in also on the requester, because different ppl have different view privileges
|
||||||
|
string cacheKey = "members-" + RequestingAgentID.ToString() + "-" + GroupID.ToString();
|
||||||
|
|
||||||
|
//m_log.DebugFormat("[XXX]: GetGroupMembers {0}", cacheKey);
|
||||||
|
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
lock (m_Cache)
|
||||||
|
{
|
||||||
|
if (m_Cache.TryGetValue(cacheKey, out members))
|
||||||
|
{
|
||||||
|
List<ExtendedGroupMembersData> xx = (List<ExtendedGroupMembersData>)members;
|
||||||
|
return xx.ConvertAll<GroupMembersData>(new Converter<ExtendedGroupMembersData, GroupMembersData>(m_ForeignImporter.ConvertGroupMembersData));
|
||||||
|
}
|
||||||
|
|
||||||
|
// not cached
|
||||||
|
if (!m_ActiveRequests.ContainsKey(cacheKey))
|
||||||
|
{
|
||||||
|
m_ActiveRequests.Add(cacheKey, true);
|
||||||
|
firstCall = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (firstCall)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
List<ExtendedGroupMembersData> _members = d();
|
||||||
|
|
||||||
|
if (_members != null && _members.Count > 0)
|
||||||
|
members = _members.ConvertAll<GroupMembersData>(new Converter<ExtendedGroupMembersData, GroupMembersData>(m_ForeignImporter.ConvertGroupMembersData));
|
||||||
|
else
|
||||||
|
members = new List<GroupMembersData>();
|
||||||
|
|
||||||
|
lock (m_Cache)
|
||||||
|
{
|
||||||
|
//m_Cache.AddOrUpdate(cacheKey, members, GROUPS_CACHE_TIMEOUT);
|
||||||
|
m_Cache.AddOrUpdate(cacheKey, _members, GROUPS_CACHE_TIMEOUT);
|
||||||
|
|
||||||
|
return (List<GroupMembersData>)members;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
m_ActiveRequests.Remove(cacheKey);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
Thread.Sleep(50);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool AddGroupRole(UUID groupID, UUID roleID, string description, string name, ulong powers, string title, BooleanDelegate d)
|
||||||
|
{
|
||||||
|
if (d())
|
||||||
|
{
|
||||||
|
GroupRolesData role = new GroupRolesData();
|
||||||
|
role.Description = description;
|
||||||
|
role.Members = 0;
|
||||||
|
role.Name = name;
|
||||||
|
role.Powers = powers;
|
||||||
|
role.RoleID = roleID;
|
||||||
|
role.Title = title;
|
||||||
|
|
||||||
|
lock (m_Cache)
|
||||||
|
{
|
||||||
|
m_Cache.AddOrUpdate("role-" + roleID.ToString(), role, GROUPS_CACHE_TIMEOUT);
|
||||||
|
|
||||||
|
// also remove this list
|
||||||
|
if (m_Cache.Contains("roles-" + groupID.ToString()))
|
||||||
|
m_Cache.Remove("roles-" + groupID.ToString());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool UpdateGroupRole(UUID groupID, UUID roleID, string name, string description, string title, ulong powers, BooleanDelegate d)
|
||||||
|
{
|
||||||
|
if (d())
|
||||||
|
{
|
||||||
|
object role;
|
||||||
|
lock (m_Cache)
|
||||||
|
if (m_Cache.TryGetValue("role-" + roleID.ToString(), out role))
|
||||||
|
{
|
||||||
|
GroupRolesData r = (GroupRolesData)role;
|
||||||
|
r.Description = description;
|
||||||
|
r.Name = name;
|
||||||
|
r.Powers = powers;
|
||||||
|
r.Title = title;
|
||||||
|
|
||||||
|
m_Cache.Update("role-" + roleID.ToString(), r, GROUPS_CACHE_TIMEOUT);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
lock (m_Cache)
|
||||||
|
{
|
||||||
|
if (m_Cache.Contains("role-" + roleID.ToString()))
|
||||||
|
m_Cache.Remove("role-" + roleID.ToString());
|
||||||
|
|
||||||
|
// also remove these lists, because they will have an outdated role
|
||||||
|
if (m_Cache.Contains("roles-" + groupID.ToString()))
|
||||||
|
m_Cache.Remove("roles-" + groupID.ToString());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RemoveGroupRole(string RequestingAgentID, UUID groupID, UUID roleID, VoidDelegate d)
|
||||||
|
{
|
||||||
|
d();
|
||||||
|
|
||||||
|
lock (m_Cache)
|
||||||
|
{
|
||||||
|
if (m_Cache.Contains("role-" + roleID.ToString()))
|
||||||
|
m_Cache.Remove("role-" + roleID.ToString());
|
||||||
|
|
||||||
|
// also remove the list, because it will have an removed role
|
||||||
|
if (m_Cache.Contains("roles-" + groupID.ToString()))
|
||||||
|
m_Cache.Remove("roles-" + groupID.ToString());
|
||||||
|
|
||||||
|
if (m_Cache.Contains("roles-" + groupID.ToString() + "-" + RequestingAgentID.ToString()))
|
||||||
|
m_Cache.Remove("roles-" + groupID.ToString() + "-" + RequestingAgentID.ToString());
|
||||||
|
|
||||||
|
if (m_Cache.Contains("rolemembers-" + RequestingAgentID.ToString() + "-" + groupID.ToString()))
|
||||||
|
m_Cache.Remove("rolemembers-" + RequestingAgentID.ToString() + "-" + groupID.ToString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<GroupRolesData> GetGroupRoles(string RequestingAgentID, UUID GroupID, GroupRolesListDelegate d)
|
||||||
|
{
|
||||||
|
object roles = null;
|
||||||
|
bool firstCall = false;
|
||||||
|
string cacheKey = "roles-" + GroupID.ToString();
|
||||||
|
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
lock (m_Cache)
|
||||||
|
{
|
||||||
|
if (m_Cache.TryGetValue(cacheKey, out roles))
|
||||||
|
return (List<GroupRolesData>)roles;
|
||||||
|
|
||||||
|
// not cached
|
||||||
|
if (!m_ActiveRequests.ContainsKey(cacheKey))
|
||||||
|
{
|
||||||
|
m_ActiveRequests.Add(cacheKey, true);
|
||||||
|
firstCall = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (firstCall)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
roles = d();
|
||||||
|
if (roles != null)
|
||||||
|
{
|
||||||
|
lock (m_Cache)
|
||||||
|
{
|
||||||
|
m_Cache.AddOrUpdate(cacheKey, roles, GROUPS_CACHE_TIMEOUT);
|
||||||
|
return (List<GroupRolesData>)roles;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
m_ActiveRequests.Remove(cacheKey);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
Thread.Sleep(50);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<GroupRoleMembersData> GetGroupRoleMembers(string RequestingAgentID, UUID GroupID, RoleMembersListDelegate d)
|
||||||
|
{
|
||||||
|
object rmembers = null;
|
||||||
|
bool firstCall = false;
|
||||||
|
// we need to key in also on the requester, because different ppl have different view privileges
|
||||||
|
string cacheKey = "rolemembers-" + RequestingAgentID.ToString() + "-" + GroupID.ToString();
|
||||||
|
|
||||||
|
//m_log.DebugFormat("[XXX]: GetGroupRoleMembers {0}", cacheKey);
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
lock (m_Cache)
|
||||||
|
{
|
||||||
|
if (m_Cache.TryGetValue(cacheKey, out rmembers))
|
||||||
|
{
|
||||||
|
List<ExtendedGroupRoleMembersData> xx = (List<ExtendedGroupRoleMembersData>)rmembers;
|
||||||
|
return xx.ConvertAll<GroupRoleMembersData>(m_ForeignImporter.ConvertGroupRoleMembersData);
|
||||||
|
}
|
||||||
|
|
||||||
|
// not cached
|
||||||
|
if (!m_ActiveRequests.ContainsKey(cacheKey))
|
||||||
|
{
|
||||||
|
m_ActiveRequests.Add(cacheKey, true);
|
||||||
|
firstCall = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (firstCall)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
List<ExtendedGroupRoleMembersData> _rmembers = d();
|
||||||
|
|
||||||
|
if (_rmembers != null && _rmembers.Count > 0)
|
||||||
|
rmembers = _rmembers.ConvertAll<GroupRoleMembersData>(new Converter<ExtendedGroupRoleMembersData, GroupRoleMembersData>(m_ForeignImporter.ConvertGroupRoleMembersData));
|
||||||
|
else
|
||||||
|
rmembers = new List<GroupRoleMembersData>();
|
||||||
|
|
||||||
|
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
|
||||||
|
{
|
||||||
|
m_ActiveRequests.Remove(cacheKey);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
Thread.Sleep(50);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddAgentToGroupRole(string RequestingAgentID, string AgentID, UUID GroupID, UUID RoleID, BooleanDelegate d)
|
||||||
|
{
|
||||||
|
if (d())
|
||||||
|
{
|
||||||
|
lock (m_Cache)
|
||||||
|
{
|
||||||
|
// update the cached role
|
||||||
|
string cacheKey = "role-" + RoleID.ToString();
|
||||||
|
object obj;
|
||||||
|
if (m_Cache.TryGetValue(cacheKey, out obj))
|
||||||
|
{
|
||||||
|
GroupRolesData r = (GroupRolesData)obj;
|
||||||
|
r.Members++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// add this agent to the list of role members
|
||||||
|
cacheKey = "rolemembers-" + RequestingAgentID.ToString() + "-" + GroupID.ToString();
|
||||||
|
if (m_Cache.TryGetValue(cacheKey, out obj))
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// This may throw an exception, in which case the agentID is not a UUID but a full ID
|
||||||
|
// In that case, let's just remove the whoe things from the cache
|
||||||
|
UUID id = new UUID(AgentID);
|
||||||
|
List<ExtendedGroupRoleMembersData> xx = (List<ExtendedGroupRoleMembersData>)obj;
|
||||||
|
List<GroupRoleMembersData> rmlist = xx.ConvertAll<GroupRoleMembersData>(m_ForeignImporter.ConvertGroupRoleMembersData);
|
||||||
|
GroupRoleMembersData rm = new GroupRoleMembersData();
|
||||||
|
rm.MemberID = id;
|
||||||
|
rm.RoleID = RoleID;
|
||||||
|
rmlist.Add(rm);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
m_Cache.Remove(cacheKey);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove the cached info about this agent's roles
|
||||||
|
// because we don't have enough local info about the new role
|
||||||
|
cacheKey = "roles-" + GroupID.ToString() + "-" + AgentID.ToString();
|
||||||
|
if (m_Cache.Contains(cacheKey))
|
||||||
|
m_Cache.Remove(cacheKey);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RemoveAgentFromGroupRole(string RequestingAgentID, string AgentID, UUID GroupID, UUID RoleID, BooleanDelegate d)
|
||||||
|
{
|
||||||
|
if (d())
|
||||||
|
{
|
||||||
|
lock (m_Cache)
|
||||||
|
{
|
||||||
|
// update the cached role
|
||||||
|
string cacheKey = "role-" + RoleID.ToString();
|
||||||
|
object obj;
|
||||||
|
if (m_Cache.TryGetValue(cacheKey, out obj))
|
||||||
|
{
|
||||||
|
GroupRolesData r = (GroupRolesData)obj;
|
||||||
|
r.Members--;
|
||||||
|
}
|
||||||
|
|
||||||
|
cacheKey = "roles-" + GroupID.ToString() + "-" + AgentID.ToString();
|
||||||
|
if (m_Cache.Contains(cacheKey))
|
||||||
|
m_Cache.Remove(cacheKey);
|
||||||
|
|
||||||
|
cacheKey = "rolemembers-" + RequestingAgentID.ToString() + "-" + GroupID.ToString();
|
||||||
|
if (m_Cache.Contains(cacheKey))
|
||||||
|
m_Cache.Remove(cacheKey);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<GroupRolesData> GetAgentGroupRoles(string RequestingAgentID, string AgentID, UUID GroupID, GroupRolesListDelegate d)
|
||||||
|
{
|
||||||
|
object roles = null;
|
||||||
|
bool firstCall = false;
|
||||||
|
string cacheKey = "roles-" + GroupID.ToString() + "-" + AgentID.ToString();
|
||||||
|
|
||||||
|
//m_log.DebugFormat("[XXX]: GetAgentGroupRoles {0}", cacheKey);
|
||||||
|
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
lock (m_Cache)
|
||||||
|
{
|
||||||
|
if (m_Cache.TryGetValue(cacheKey, out roles))
|
||||||
|
{
|
||||||
|
//m_log.DebugFormat("[XXX]: GetAgentGroupRoles {0} cached!", cacheKey);
|
||||||
|
return (List<GroupRolesData>)roles;
|
||||||
|
}
|
||||||
|
|
||||||
|
// not cached
|
||||||
|
if (!m_ActiveRequests.ContainsKey(cacheKey))
|
||||||
|
{
|
||||||
|
m_ActiveRequests.Add(cacheKey, true);
|
||||||
|
firstCall = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (firstCall)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
roles = d();
|
||||||
|
lock (m_Cache)
|
||||||
|
{
|
||||||
|
m_Cache.AddOrUpdate(cacheKey, roles, GROUPS_CACHE_TIMEOUT);
|
||||||
|
m_ActiveRequests.Remove(cacheKey);
|
||||||
|
return (List<GroupRolesData>)roles;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
m_ActiveRequests.Remove(cacheKey);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
Thread.Sleep(50);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetAgentActiveGroupRole(string AgentID, UUID GroupID, VoidDelegate d)
|
||||||
|
{
|
||||||
|
d();
|
||||||
|
|
||||||
|
lock (m_Cache)
|
||||||
|
{
|
||||||
|
// Invalidate cached info, because it has ActiveRoleID and Powers
|
||||||
|
string cacheKey = "membership-" + AgentID.ToString() + "-" + GroupID.ToString();
|
||||||
|
if (m_Cache.Contains(cacheKey))
|
||||||
|
m_Cache.Remove(cacheKey);
|
||||||
|
|
||||||
|
cacheKey = "memberships-" + AgentID.ToString();
|
||||||
|
if (m_Cache.Contains(cacheKey))
|
||||||
|
m_Cache.Remove(cacheKey);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void UpdateMembership(string AgentID, UUID GroupID, bool AcceptNotices, bool ListInProfile, VoidDelegate d)
|
||||||
|
{
|
||||||
|
d();
|
||||||
|
|
||||||
|
lock (m_Cache)
|
||||||
|
{
|
||||||
|
string cacheKey = "membership-" + AgentID.ToString() + "-" + GroupID.ToString();
|
||||||
|
if (m_Cache.Contains(cacheKey))
|
||||||
|
m_Cache.Remove(cacheKey);
|
||||||
|
|
||||||
|
cacheKey = "memberships-" + AgentID.ToString();
|
||||||
|
if (m_Cache.Contains(cacheKey))
|
||||||
|
m_Cache.Remove(cacheKey);
|
||||||
|
|
||||||
|
cacheKey = "active-" + AgentID.ToString();
|
||||||
|
object m = null;
|
||||||
|
if (m_Cache.TryGetValue(cacheKey, out m))
|
||||||
|
{
|
||||||
|
GroupMembershipData membership = (GroupMembershipData)m;
|
||||||
|
membership.ListInProfile = ListInProfile;
|
||||||
|
membership.AcceptNotices = AcceptNotices;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool AddGroupNotice(UUID groupID, UUID noticeID, GroupNoticeInfo notice, BooleanDelegate d)
|
||||||
|
{
|
||||||
|
if (d())
|
||||||
|
{
|
||||||
|
lock (m_Cache)
|
||||||
|
{
|
||||||
|
m_Cache.AddOrUpdate("notice-" + noticeID.ToString(), notice, GROUPS_CACHE_TIMEOUT);
|
||||||
|
string cacheKey = "notices-" + groupID.ToString();
|
||||||
|
if (m_Cache.Contains(cacheKey))
|
||||||
|
m_Cache.Remove(cacheKey);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public GroupNoticeInfo GetGroupNotice(UUID noticeID, NoticeDelegate d)
|
||||||
|
{
|
||||||
|
object notice = null;
|
||||||
|
bool firstCall = false;
|
||||||
|
string cacheKey = "notice-" + noticeID.ToString();
|
||||||
|
|
||||||
|
//m_log.DebugFormat("[XXX]: GetAgentGroupRoles {0}", cacheKey);
|
||||||
|
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
lock (m_Cache)
|
||||||
|
{
|
||||||
|
if (m_Cache.TryGetValue(cacheKey, out notice))
|
||||||
|
{
|
||||||
|
return (GroupNoticeInfo)notice;
|
||||||
|
}
|
||||||
|
|
||||||
|
// not cached
|
||||||
|
if (!m_ActiveRequests.ContainsKey(cacheKey))
|
||||||
|
{
|
||||||
|
m_ActiveRequests.Add(cacheKey, true);
|
||||||
|
firstCall = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (firstCall)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
GroupNoticeInfo _notice = d();
|
||||||
|
|
||||||
|
lock (m_Cache)
|
||||||
|
{
|
||||||
|
m_Cache.AddOrUpdate(cacheKey, _notice, GROUPS_CACHE_TIMEOUT);
|
||||||
|
return _notice;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
m_ActiveRequests.Remove(cacheKey);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
Thread.Sleep(50);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<ExtendedGroupNoticeData> GetGroupNotices(UUID GroupID, NoticeListDelegate d)
|
||||||
|
{
|
||||||
|
object notices = null;
|
||||||
|
bool firstCall = false;
|
||||||
|
string cacheKey = "notices-" + GroupID.ToString();
|
||||||
|
|
||||||
|
//m_log.DebugFormat("[XXX]: GetGroupNotices {0}", cacheKey);
|
||||||
|
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
lock (m_Cache)
|
||||||
|
{
|
||||||
|
if (m_Cache.TryGetValue(cacheKey, out notices))
|
||||||
|
{
|
||||||
|
//m_log.DebugFormat("[XXX]: GetGroupNotices {0} cached!", cacheKey);
|
||||||
|
return (List<ExtendedGroupNoticeData>)notices;
|
||||||
|
}
|
||||||
|
|
||||||
|
// not cached
|
||||||
|
if (!m_ActiveRequests.ContainsKey(cacheKey))
|
||||||
|
{
|
||||||
|
m_ActiveRequests.Add(cacheKey, true);
|
||||||
|
firstCall = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (firstCall)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
notices = d();
|
||||||
|
|
||||||
|
lock (m_Cache)
|
||||||
|
{
|
||||||
|
m_Cache.AddOrUpdate(cacheKey, notices, GROUPS_CACHE_TIMEOUT);
|
||||||
|
return (List<ExtendedGroupNoticeData>)notices;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
m_ActiveRequests.Remove(cacheKey);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
Thread.Sleep(50);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,101 @@
|
||||||
|
/*
|
||||||
|
* 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.Reflection;
|
||||||
|
using Nini.Config;
|
||||||
|
using OpenSim.Framework;
|
||||||
|
using OpenSim.Data;
|
||||||
|
using OpenSim.Services.Interfaces;
|
||||||
|
using OpenSim.Services.Base;
|
||||||
|
|
||||||
|
namespace OpenSim.Groups
|
||||||
|
{
|
||||||
|
public class GroupsServiceBase : ServiceBase
|
||||||
|
{
|
||||||
|
protected IGroupsData m_Database = null;
|
||||||
|
protected IGridUserData m_GridUserService = null;
|
||||||
|
|
||||||
|
public GroupsServiceBase(IConfigSource config, string cName)
|
||||||
|
: base(config)
|
||||||
|
{
|
||||||
|
string dllName = String.Empty;
|
||||||
|
string connString = String.Empty;
|
||||||
|
string realm = "os_groups";
|
||||||
|
string usersRealm = "GridUser";
|
||||||
|
string configName = (cName == string.Empty) ? "Groups" : cName;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Try reading the [DatabaseService] section, if it exists
|
||||||
|
//
|
||||||
|
IConfig dbConfig = config.Configs["DatabaseService"];
|
||||||
|
if (dbConfig != null)
|
||||||
|
{
|
||||||
|
if (dllName == String.Empty)
|
||||||
|
dllName = dbConfig.GetString("StorageProvider", String.Empty);
|
||||||
|
if (connString == String.Empty)
|
||||||
|
connString = dbConfig.GetString("ConnectionString", String.Empty);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// [Groups] section overrides [DatabaseService], if it exists
|
||||||
|
//
|
||||||
|
IConfig groupsConfig = config.Configs[configName];
|
||||||
|
if (groupsConfig != null)
|
||||||
|
{
|
||||||
|
dllName = groupsConfig.GetString("StorageProvider", dllName);
|
||||||
|
connString = groupsConfig.GetString("ConnectionString", connString);
|
||||||
|
realm = groupsConfig.GetString("Realm", realm);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// We tried, but this doesn't exist. We can't proceed.
|
||||||
|
//
|
||||||
|
if (dllName.Equals(String.Empty))
|
||||||
|
throw new Exception("No StorageProvider configured");
|
||||||
|
|
||||||
|
m_Database = LoadPlugin<IGroupsData>(dllName, new Object[] { connString, realm });
|
||||||
|
if (m_Database == null)
|
||||||
|
throw new Exception("Could not find a storage interface in the given module " + dllName);
|
||||||
|
|
||||||
|
//
|
||||||
|
// [GridUserService] section overrides [DatabaseService], if it exists
|
||||||
|
//
|
||||||
|
IConfig usersConfig = config.Configs["GridUserService"];
|
||||||
|
if (usersConfig != null)
|
||||||
|
{
|
||||||
|
dllName = usersConfig.GetString("StorageProvider", dllName);
|
||||||
|
connString = usersConfig.GetString("ConnectionString", connString);
|
||||||
|
usersRealm = usersConfig.GetString("Realm", usersRealm);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_GridUserService = LoadPlugin<IGridUserData>(dllName, new Object[] { connString, usersRealm });
|
||||||
|
if (m_GridUserService == null)
|
||||||
|
throw new Exception("Could not find a storage inferface for the given users module " + dllName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,361 @@
|
||||||
|
/*
|
||||||
|
* 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.Reflection;
|
||||||
|
using System.Timers;
|
||||||
|
using log4net;
|
||||||
|
using Nini.Config;
|
||||||
|
|
||||||
|
using OpenMetaverse;
|
||||||
|
using OpenSim.Data;
|
||||||
|
using OpenSim.Framework;
|
||||||
|
using OpenSim.Services.Interfaces;
|
||||||
|
|
||||||
|
namespace OpenSim.Groups
|
||||||
|
{
|
||||||
|
public class HGGroupsService : GroupsService
|
||||||
|
{
|
||||||
|
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
|
|
||||||
|
private IOfflineIMService m_OfflineIM;
|
||||||
|
private IUserAccountService m_UserAccounts;
|
||||||
|
private string m_HomeURI;
|
||||||
|
|
||||||
|
public HGGroupsService(IConfigSource config, IOfflineIMService im, IUserAccountService users, string homeURI)
|
||||||
|
: base(config, string.Empty)
|
||||||
|
{
|
||||||
|
m_OfflineIM = im;
|
||||||
|
m_UserAccounts = users;
|
||||||
|
m_HomeURI = homeURI;
|
||||||
|
if (!m_HomeURI.EndsWith("/"))
|
||||||
|
m_HomeURI += "/";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#region HG specific operations
|
||||||
|
|
||||||
|
public bool CreateGroupProxy(string RequestingAgentID, string agentID, string accessToken, UUID groupID, string serviceLocation, string name, out string reason)
|
||||||
|
{
|
||||||
|
reason = string.Empty;
|
||||||
|
Uri uri = null;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
uri = new Uri(serviceLocation);
|
||||||
|
}
|
||||||
|
catch (UriFormatException)
|
||||||
|
{
|
||||||
|
reason = "Bad location for group proxy";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if it already exists
|
||||||
|
GroupData grec = m_Database.RetrieveGroup(groupID);
|
||||||
|
if (grec == null ||
|
||||||
|
(grec != null && grec.Data["Location"] != string.Empty && grec.Data["Location"].ToLower() != serviceLocation.ToLower()))
|
||||||
|
{
|
||||||
|
// Create the group
|
||||||
|
grec = new GroupData();
|
||||||
|
grec.GroupID = groupID;
|
||||||
|
grec.Data = new Dictionary<string, string>();
|
||||||
|
grec.Data["Name"] = name + " @ " + uri.Authority;
|
||||||
|
grec.Data["Location"] = serviceLocation;
|
||||||
|
grec.Data["Charter"] = string.Empty;
|
||||||
|
grec.Data["InsigniaID"] = UUID.Zero.ToString();
|
||||||
|
grec.Data["FounderID"] = UUID.Zero.ToString();
|
||||||
|
grec.Data["MembershipFee"] = "0";
|
||||||
|
grec.Data["OpenEnrollment"] = "0";
|
||||||
|
grec.Data["ShowInList"] = "0";
|
||||||
|
grec.Data["AllowPublish"] = "0";
|
||||||
|
grec.Data["MaturePublish"] = "0";
|
||||||
|
grec.Data["OwnerRoleID"] = UUID.Zero.ToString();
|
||||||
|
|
||||||
|
|
||||||
|
if (!m_Database.StoreGroup(grec))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (grec.Data["Location"] == string.Empty)
|
||||||
|
{
|
||||||
|
reason = "Cannot add proxy membership to non-proxy group";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
UUID uid = UUID.Zero;
|
||||||
|
string url = string.Empty, first = string.Empty, last = string.Empty, tmp = string.Empty;
|
||||||
|
Util.ParseUniversalUserIdentifier(RequestingAgentID, out uid, out url, out first, out last, out tmp);
|
||||||
|
string fromName = first + "." + last + "@" + url;
|
||||||
|
|
||||||
|
// Invite to group again
|
||||||
|
InviteToGroup(fromName, groupID, new UUID(agentID), grec.Data["Name"]);
|
||||||
|
|
||||||
|
// Stick the proxy membership in the DB already
|
||||||
|
// we'll delete it if the agent declines the invitation
|
||||||
|
MembershipData membership = new MembershipData();
|
||||||
|
membership.PrincipalID = agentID;
|
||||||
|
membership.GroupID = groupID;
|
||||||
|
membership.Data = new Dictionary<string, string>();
|
||||||
|
membership.Data["SelectedRoleID"] = UUID.Zero.ToString();
|
||||||
|
membership.Data["Contribution"] = "0";
|
||||||
|
membership.Data["ListInProfile"] = "1";
|
||||||
|
membership.Data["AcceptNotices"] = "1";
|
||||||
|
membership.Data["AccessToken"] = accessToken;
|
||||||
|
|
||||||
|
m_Database.StoreMember(membership);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool RemoveAgentFromGroup(string RequestingAgentID, string AgentID, UUID GroupID, string token)
|
||||||
|
{
|
||||||
|
// check the token
|
||||||
|
MembershipData membership = m_Database.RetrieveMember(GroupID, AgentID);
|
||||||
|
if (membership != null)
|
||||||
|
{
|
||||||
|
if (token != string.Empty && token.Equals(membership.Data["AccessToken"]))
|
||||||
|
{
|
||||||
|
return RemoveAgentFromGroup(RequestingAgentID, AgentID, GroupID);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_log.DebugFormat("[Groups.HGGroupsService]: access token {0} did not match stored one {1}", token, membership.Data["AccessToken"]);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_log.DebugFormat("[Groups.HGGroupsService]: membership not found for {0}", AgentID);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public ExtendedGroupRecord GetGroupRecord(string RequestingAgentID, UUID GroupID, string groupName, string token)
|
||||||
|
{
|
||||||
|
// check the token
|
||||||
|
if (!VerifyToken(GroupID, RequestingAgentID, token))
|
||||||
|
return null;
|
||||||
|
|
||||||
|
ExtendedGroupRecord grec;
|
||||||
|
if (GroupID == UUID.Zero)
|
||||||
|
grec = GetGroupRecord(RequestingAgentID, groupName);
|
||||||
|
else
|
||||||
|
grec = GetGroupRecord(RequestingAgentID, GroupID);
|
||||||
|
|
||||||
|
if (grec != null)
|
||||||
|
FillFounderUUI(grec);
|
||||||
|
|
||||||
|
return grec;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<ExtendedGroupMembersData> GetGroupMembers(string RequestingAgentID, UUID GroupID, string token)
|
||||||
|
{
|
||||||
|
if (!VerifyToken(GroupID, RequestingAgentID, token))
|
||||||
|
return new List<ExtendedGroupMembersData>();
|
||||||
|
|
||||||
|
List<ExtendedGroupMembersData> members = GetGroupMembers(RequestingAgentID, GroupID);
|
||||||
|
|
||||||
|
// convert UUIDs to UUIs
|
||||||
|
members.ForEach(delegate (ExtendedGroupMembersData m)
|
||||||
|
{
|
||||||
|
if (m.AgentID.ToString().Length == 36) // UUID
|
||||||
|
{
|
||||||
|
UserAccount account = m_UserAccounts.GetUserAccount(UUID.Zero, new UUID(m.AgentID));
|
||||||
|
if (account != null)
|
||||||
|
m.AgentID = Util.UniversalIdentifier(account.PrincipalID, account.FirstName, account.LastName, m_HomeURI);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return members;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<GroupRolesData> GetGroupRoles(string RequestingAgentID, UUID GroupID, string token)
|
||||||
|
{
|
||||||
|
if (!VerifyToken(GroupID, RequestingAgentID, token))
|
||||||
|
return new List<GroupRolesData>();
|
||||||
|
|
||||||
|
return GetGroupRoles(RequestingAgentID, GroupID);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<ExtendedGroupRoleMembersData> GetGroupRoleMembers(string RequestingAgentID, UUID GroupID, string token)
|
||||||
|
{
|
||||||
|
if (!VerifyToken(GroupID, RequestingAgentID, token))
|
||||||
|
return new List<ExtendedGroupRoleMembersData>();
|
||||||
|
|
||||||
|
List<ExtendedGroupRoleMembersData> rolemembers = GetGroupRoleMembers(RequestingAgentID, GroupID);
|
||||||
|
|
||||||
|
// convert UUIDs to UUIs
|
||||||
|
rolemembers.ForEach(delegate(ExtendedGroupRoleMembersData m)
|
||||||
|
{
|
||||||
|
if (m.MemberID.ToString().Length == 36) // UUID
|
||||||
|
{
|
||||||
|
UserAccount account = m_UserAccounts.GetUserAccount(UUID.Zero, new UUID(m.MemberID));
|
||||||
|
if (account != null)
|
||||||
|
m.MemberID = Util.UniversalIdentifier(account.PrincipalID, account.FirstName, account.LastName, m_HomeURI);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return rolemembers;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool AddNotice(string RequestingAgentID, UUID groupID, UUID noticeID, string fromName, string subject, string message,
|
||||||
|
bool hasAttachment, byte attType, string attName, UUID attItemID, string attOwnerID)
|
||||||
|
{
|
||||||
|
// check that the group proxy exists
|
||||||
|
ExtendedGroupRecord grec = GetGroupRecord(RequestingAgentID, groupID);
|
||||||
|
if (grec == null)
|
||||||
|
{
|
||||||
|
m_log.DebugFormat("[Groups.HGGroupsService]: attempt at adding notice to non-existent group proxy");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// check that the group is remote
|
||||||
|
if (grec.ServiceLocation == string.Empty)
|
||||||
|
{
|
||||||
|
m_log.DebugFormat("[Groups.HGGroupsService]: attempt at adding notice to local (non-proxy) group");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// check that there isn't already a notice with the same ID
|
||||||
|
if (GetGroupNotice(RequestingAgentID, noticeID) != null)
|
||||||
|
{
|
||||||
|
m_log.DebugFormat("[Groups.HGGroupsService]: a notice with the same ID already exists", grec.ServiceLocation);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// This has good intentions (security) but it will potentially DDS the origin...
|
||||||
|
// We'll need to send a proof along with the message. Maybe encrypt the message
|
||||||
|
// using key pairs
|
||||||
|
//
|
||||||
|
//// check that the notice actually exists in the origin
|
||||||
|
//GroupsServiceHGConnector c = new GroupsServiceHGConnector(grec.ServiceLocation);
|
||||||
|
//if (!c.VerifyNotice(noticeID, groupID))
|
||||||
|
//{
|
||||||
|
// m_log.DebugFormat("[Groups.HGGroupsService]: notice does not exist at origin {0}", grec.ServiceLocation);
|
||||||
|
// return false;
|
||||||
|
//}
|
||||||
|
|
||||||
|
// ok, we're good!
|
||||||
|
return _AddNotice(groupID, noticeID, fromName, subject, message, hasAttachment, attType, attName, attItemID, attOwnerID);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool VerifyNotice(UUID noticeID, UUID groupID)
|
||||||
|
{
|
||||||
|
GroupNoticeInfo notice = GetGroupNotice(string.Empty, noticeID);
|
||||||
|
|
||||||
|
if (notice == null)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (notice.GroupID != groupID)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
private void InviteToGroup(string fromName, UUID groupID, UUID invitedAgentID, string groupName)
|
||||||
|
{
|
||||||
|
// Todo: Security check, probably also want to send some kind of notification
|
||||||
|
UUID InviteID = UUID.Random();
|
||||||
|
|
||||||
|
if (AddAgentToGroupInvite(InviteID, groupID, invitedAgentID.ToString()))
|
||||||
|
{
|
||||||
|
Guid inviteUUID = InviteID.Guid;
|
||||||
|
|
||||||
|
GridInstantMessage msg = new GridInstantMessage();
|
||||||
|
|
||||||
|
msg.imSessionID = inviteUUID;
|
||||||
|
|
||||||
|
// msg.fromAgentID = agentID.Guid;
|
||||||
|
msg.fromAgentID = groupID.Guid;
|
||||||
|
msg.toAgentID = invitedAgentID.Guid;
|
||||||
|
//msg.timestamp = (uint)Util.UnixTimeSinceEpoch();
|
||||||
|
msg.timestamp = 0;
|
||||||
|
msg.fromAgentName = fromName;
|
||||||
|
msg.message = string.Format("Please confirm your acceptance to join group {0}.", groupName);
|
||||||
|
msg.dialog = (byte)OpenMetaverse.InstantMessageDialog.GroupInvitation;
|
||||||
|
msg.fromGroup = true;
|
||||||
|
msg.offline = (byte)0;
|
||||||
|
msg.ParentEstateID = 0;
|
||||||
|
msg.Position = Vector3.Zero;
|
||||||
|
msg.RegionID = UUID.Zero.Guid;
|
||||||
|
msg.binaryBucket = new byte[20];
|
||||||
|
|
||||||
|
string reason = string.Empty;
|
||||||
|
m_OfflineIM.StoreMessage(msg, out reason);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool AddAgentToGroupInvite(UUID inviteID, UUID groupID, string agentID)
|
||||||
|
{
|
||||||
|
// Check whether the invitee is already a member of the group
|
||||||
|
MembershipData m = m_Database.RetrieveMember(groupID, agentID);
|
||||||
|
if (m != null)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Check whether there are pending invitations and delete them
|
||||||
|
InvitationData invite = m_Database.RetrieveInvitation(groupID, agentID);
|
||||||
|
if (invite != null)
|
||||||
|
m_Database.DeleteInvite(invite.InviteID);
|
||||||
|
|
||||||
|
invite = new InvitationData();
|
||||||
|
invite.InviteID = inviteID;
|
||||||
|
invite.PrincipalID = agentID;
|
||||||
|
invite.GroupID = groupID;
|
||||||
|
invite.RoleID = UUID.Zero;
|
||||||
|
invite.Data = new Dictionary<string, string>();
|
||||||
|
|
||||||
|
return m_Database.StoreInvitation(invite);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void FillFounderUUI(ExtendedGroupRecord grec)
|
||||||
|
{
|
||||||
|
UserAccount account = m_UserAccounts.GetUserAccount(UUID.Zero, grec.FounderID);
|
||||||
|
if (account != null)
|
||||||
|
grec.FounderUUI = Util.UniversalIdentifier(account.PrincipalID, account.FirstName, account.LastName, m_HomeURI);
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool VerifyToken(UUID groupID, string agentID, string token)
|
||||||
|
{
|
||||||
|
// check the token
|
||||||
|
MembershipData membership = m_Database.RetrieveMember(groupID, agentID);
|
||||||
|
if (membership != null)
|
||||||
|
{
|
||||||
|
if (token != string.Empty && token.Equals(membership.Data["AccessToken"]))
|
||||||
|
return true;
|
||||||
|
else
|
||||||
|
m_log.DebugFormat("[Groups.HGGroupsService]: access token {0} did not match stored one {1}", token, membership.Data["AccessToken"]);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
m_log.DebugFormat("[Groups.HGGroupsService]: membership not found for {0}", agentID);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,252 @@
|
||||||
|
/*
|
||||||
|
* 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.Reflection;
|
||||||
|
using log4net;
|
||||||
|
using Mono.Addins;
|
||||||
|
using Nini.Config;
|
||||||
|
using OpenMetaverse;
|
||||||
|
using OpenSim.Framework;
|
||||||
|
using OpenSim.Framework.Servers;
|
||||||
|
using OpenSim.Framework.Client;
|
||||||
|
using OpenSim.Region.Framework.Interfaces;
|
||||||
|
using OpenSim.Region.Framework.Scenes;
|
||||||
|
using OpenSim.Services.Interfaces;
|
||||||
|
|
||||||
|
namespace OpenSim.OfflineIM
|
||||||
|
{
|
||||||
|
[Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "OfflineIMConnectorModule")]
|
||||||
|
public class OfflineIMRegionModule : ISharedRegionModule, IOfflineIMService
|
||||||
|
{
|
||||||
|
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
|
|
||||||
|
private bool m_Enabled = false;
|
||||||
|
private List<Scene> m_SceneList = new List<Scene>();
|
||||||
|
IMessageTransferModule m_TransferModule = null;
|
||||||
|
private bool m_ForwardOfflineGroupMessages = true;
|
||||||
|
|
||||||
|
private IOfflineIMService m_OfflineIMService;
|
||||||
|
|
||||||
|
public void Initialise(IConfigSource config)
|
||||||
|
{
|
||||||
|
IConfig cnf = config.Configs["Messaging"];
|
||||||
|
if (cnf == null)
|
||||||
|
return;
|
||||||
|
if (cnf != null && cnf.GetString("OfflineMessageModule", string.Empty) != Name)
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_Enabled = true;
|
||||||
|
|
||||||
|
string serviceLocation = cnf.GetString("OfflineMessageURL", string.Empty);
|
||||||
|
if (serviceLocation == string.Empty)
|
||||||
|
m_OfflineIMService = new OfflineIMService(config);
|
||||||
|
else
|
||||||
|
m_OfflineIMService = new OfflineIMServiceRemoteConnector(config);
|
||||||
|
|
||||||
|
m_ForwardOfflineGroupMessages = cnf.GetBoolean("ForwardOfflineGroupMessages", m_ForwardOfflineGroupMessages);
|
||||||
|
m_log.DebugFormat("[OfflineIM.V2]: Offline messages enabled by {0}", Name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddRegion(Scene scene)
|
||||||
|
{
|
||||||
|
if (!m_Enabled)
|
||||||
|
return;
|
||||||
|
|
||||||
|
scene.RegisterModuleInterface<IOfflineIMService>(this);
|
||||||
|
m_SceneList.Add(scene);
|
||||||
|
scene.EventManager.OnNewClient += OnNewClient;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RegionLoaded(Scene scene)
|
||||||
|
{
|
||||||
|
if (!m_Enabled)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (m_TransferModule == null)
|
||||||
|
{
|
||||||
|
m_TransferModule = scene.RequestModuleInterface<IMessageTransferModule>();
|
||||||
|
if (m_TransferModule == null)
|
||||||
|
{
|
||||||
|
scene.EventManager.OnNewClient -= OnNewClient;
|
||||||
|
|
||||||
|
m_SceneList.Clear();
|
||||||
|
|
||||||
|
m_log.Error("[OfflineIM.V2]: No message transfer module is enabled. Disabling offline messages");
|
||||||
|
}
|
||||||
|
m_TransferModule.OnUndeliveredMessage += UndeliveredMessage;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RemoveRegion(Scene scene)
|
||||||
|
{
|
||||||
|
if (!m_Enabled)
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_SceneList.Remove(scene);
|
||||||
|
scene.EventManager.OnNewClient -= OnNewClient;
|
||||||
|
m_TransferModule.OnUndeliveredMessage -= UndeliveredMessage;
|
||||||
|
|
||||||
|
scene.ForEachClient(delegate(IClientAPI client)
|
||||||
|
{
|
||||||
|
client.OnRetrieveInstantMessages -= RetrieveInstantMessages;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void PostInitialise()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Name
|
||||||
|
{
|
||||||
|
get { return "Offline Message Module V2"; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public Type ReplaceableInterface
|
||||||
|
{
|
||||||
|
get { return null; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Close()
|
||||||
|
{
|
||||||
|
m_SceneList.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
private Scene FindScene(UUID agentID)
|
||||||
|
{
|
||||||
|
foreach (Scene s in m_SceneList)
|
||||||
|
{
|
||||||
|
ScenePresence presence = s.GetScenePresence(agentID);
|
||||||
|
if (presence != null && !presence.IsChildAgent)
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private IClientAPI FindClient(UUID agentID)
|
||||||
|
{
|
||||||
|
foreach (Scene s in m_SceneList)
|
||||||
|
{
|
||||||
|
ScenePresence presence = s.GetScenePresence(agentID);
|
||||||
|
if (presence != null && !presence.IsChildAgent)
|
||||||
|
return presence.ControllingClient;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnNewClient(IClientAPI client)
|
||||||
|
{
|
||||||
|
client.OnRetrieveInstantMessages += RetrieveInstantMessages;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void RetrieveInstantMessages(IClientAPI client)
|
||||||
|
{
|
||||||
|
m_log.DebugFormat("[OfflineIM.V2]: Retrieving stored messages for {0}", client.AgentId);
|
||||||
|
|
||||||
|
List<GridInstantMessage> msglist = m_OfflineIMService.GetMessages(client.AgentId);
|
||||||
|
|
||||||
|
if (msglist == null)
|
||||||
|
m_log.DebugFormat("[OfflineIM.V2]: WARNING null message list.");
|
||||||
|
|
||||||
|
foreach (GridInstantMessage im in msglist)
|
||||||
|
{
|
||||||
|
if (im.dialog == (byte)InstantMessageDialog.InventoryOffered)
|
||||||
|
// send it directly or else the item will be given twice
|
||||||
|
client.SendInstantMessage(im);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Send through scene event manager so all modules get a chance
|
||||||
|
// to look at this message before it gets delivered.
|
||||||
|
//
|
||||||
|
// Needed for proper state management for stored group
|
||||||
|
// invitations
|
||||||
|
//
|
||||||
|
Scene s = FindScene(client.AgentId);
|
||||||
|
if (s != null)
|
||||||
|
s.EventManager.TriggerIncomingInstantMessage(im);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UndeliveredMessage(GridInstantMessage im)
|
||||||
|
{
|
||||||
|
if (im.dialog != (byte)InstantMessageDialog.MessageFromObject &&
|
||||||
|
im.dialog != (byte)InstantMessageDialog.MessageFromAgent &&
|
||||||
|
im.dialog != (byte)InstantMessageDialog.GroupNotice &&
|
||||||
|
im.dialog != (byte)InstantMessageDialog.GroupInvitation &&
|
||||||
|
im.dialog != (byte)InstantMessageDialog.InventoryOffered)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!m_ForwardOfflineGroupMessages)
|
||||||
|
{
|
||||||
|
if (im.dialog == (byte)InstantMessageDialog.GroupNotice ||
|
||||||
|
im.dialog == (byte)InstantMessageDialog.GroupInvitation)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
string reason = string.Empty;
|
||||||
|
bool success = m_OfflineIMService.StoreMessage(im, out reason);
|
||||||
|
|
||||||
|
if (im.dialog == (byte)InstantMessageDialog.MessageFromAgent)
|
||||||
|
{
|
||||||
|
IClientAPI client = FindClient(new UUID(im.fromAgentID));
|
||||||
|
if (client == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
client.SendInstantMessage(new GridInstantMessage(
|
||||||
|
null, new UUID(im.toAgentID),
|
||||||
|
"System", new UUID(im.fromAgentID),
|
||||||
|
(byte)InstantMessageDialog.MessageFromAgent,
|
||||||
|
"User is not logged in. " +
|
||||||
|
(success ? "Message saved." : "Message not saved: " + reason),
|
||||||
|
false, new Vector3()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#region IOfflineIM
|
||||||
|
|
||||||
|
public List<GridInstantMessage> GetMessages(UUID principalID)
|
||||||
|
{
|
||||||
|
return m_OfflineIMService.GetMessages(principalID);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool StoreMessage(GridInstantMessage im, out string reason)
|
||||||
|
{
|
||||||
|
return m_OfflineIMService.StoreMessage(im, out reason);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void DeleteMessages(UUID userID)
|
||||||
|
{
|
||||||
|
m_OfflineIMService.DeleteMessages(userID);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,36 @@
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using Mono.Addins;
|
||||||
|
|
||||||
|
// General Information about an assembly is controlled through the following
|
||||||
|
// set of attributes. Change these attribute values to modify the information
|
||||||
|
// associated with an assembly.
|
||||||
|
[assembly: AssemblyTitle("OpenSim.Addons.OfflineIM")]
|
||||||
|
[assembly: AssemblyDescription("")]
|
||||||
|
[assembly: AssemblyConfiguration("")]
|
||||||
|
[assembly: AssemblyCompany("http://opensimulator.org")]
|
||||||
|
[assembly: AssemblyProduct("OpenSim.Addons.OfflineIM")]
|
||||||
|
[assembly: AssemblyCopyright("Copyright (c) OpenSimulator.org Developers")]
|
||||||
|
[assembly: AssemblyTrademark("")]
|
||||||
|
[assembly: AssemblyCulture("")]
|
||||||
|
|
||||||
|
// Setting ComVisible to false makes the types in this assembly not visible
|
||||||
|
// to COM components. If you need to access a type in this assembly from
|
||||||
|
// COM, set the ComVisible attribute to true on that type.
|
||||||
|
[assembly: ComVisible(false)]
|
||||||
|
|
||||||
|
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||||
|
[assembly: Guid("a16a9905-4393-4872-9fca-4c81bedbd9f2")]
|
||||||
|
|
||||||
|
// Version information for an assembly consists of the following four values:
|
||||||
|
//
|
||||||
|
// Major Version
|
||||||
|
// Minor Version
|
||||||
|
// Build Number
|
||||||
|
// Revision
|
||||||
|
//
|
||||||
|
[assembly: AssemblyVersion(OpenSim.VersionInfo.AssemblyVersionNumber)]
|
||||||
|
|
||||||
|
[assembly: Addin("OpenSim.OfflineIM", OpenSim.VersionInfo.VersionNumber)]
|
||||||
|
[assembly: AddinDependency("OpenSim.Region.Framework", OpenSim.VersionInfo.VersionNumber)]
|
|
@ -0,0 +1,171 @@
|
||||||
|
/*
|
||||||
|
* 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.Reflection;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
using OpenSim.Framework;
|
||||||
|
using OpenSim.Framework.ServiceAuth;
|
||||||
|
using OpenSim.Server.Base;
|
||||||
|
using OpenSim.Services.Interfaces;
|
||||||
|
|
||||||
|
using OpenMetaverse;
|
||||||
|
using log4net;
|
||||||
|
using Nini.Config;
|
||||||
|
|
||||||
|
namespace OpenSim.OfflineIM
|
||||||
|
{
|
||||||
|
public class OfflineIMServiceRemoteConnector : IOfflineIMService
|
||||||
|
{
|
||||||
|
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
|
|
||||||
|
private string m_ServerURI = string.Empty;
|
||||||
|
private IServiceAuth m_Auth;
|
||||||
|
private object m_Lock = new object();
|
||||||
|
|
||||||
|
public OfflineIMServiceRemoteConnector(string url)
|
||||||
|
{
|
||||||
|
m_ServerURI = url;
|
||||||
|
m_log.DebugFormat("[OfflineIM.V2.RemoteConnector]: Offline IM server at {0}", m_ServerURI);
|
||||||
|
}
|
||||||
|
|
||||||
|
public OfflineIMServiceRemoteConnector(IConfigSource config)
|
||||||
|
{
|
||||||
|
IConfig cnf = config.Configs["Messaging"];
|
||||||
|
if (cnf == null)
|
||||||
|
{
|
||||||
|
m_log.WarnFormat("[OfflineIM.V2.RemoteConnector]: Missing Messaging configuration");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
public List<GridInstantMessage> GetMessages(UUID principalID)
|
||||||
|
{
|
||||||
|
List<GridInstantMessage> ims = new List<GridInstantMessage>();
|
||||||
|
|
||||||
|
Dictionary<string, object> sendData = new Dictionary<string, object>();
|
||||||
|
sendData["PrincipalID"] = principalID;
|
||||||
|
Dictionary<string, object> ret = MakeRequest("GET", sendData);
|
||||||
|
|
||||||
|
if (ret == null)
|
||||||
|
return ims;
|
||||||
|
|
||||||
|
if (!ret.ContainsKey("RESULT"))
|
||||||
|
return ims;
|
||||||
|
|
||||||
|
string result = ret["RESULT"].ToString();
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (object v in ((Dictionary<string, object>)ret["RESULT"]).Values)
|
||||||
|
{
|
||||||
|
GridInstantMessage m = OfflineIMDataUtils.GridInstantMessage((Dictionary<string, object>)v);
|
||||||
|
ims.Add(m);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ims;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool StoreMessage(GridInstantMessage im, out string reason)
|
||||||
|
{
|
||||||
|
reason = string.Empty;
|
||||||
|
Dictionary<string, object> sendData = OfflineIMDataUtils.GridInstantMessage(im);
|
||||||
|
|
||||||
|
Dictionary<string, object> ret = MakeRequest("STORE", sendData);
|
||||||
|
|
||||||
|
if (ret == null)
|
||||||
|
{
|
||||||
|
reason = "Bad response from server";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
string result = ret["RESULT"].ToString();
|
||||||
|
if (result == "NULL" || result.ToLower() == "false")
|
||||||
|
{
|
||||||
|
reason = ret.ContainsKey("REASON") ? ret["REASON"].ToString() : "Unknown error";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void DeleteMessages(UUID userID)
|
||||||
|
{
|
||||||
|
Dictionary<string, object> sendData = new Dictionary<string, object>();
|
||||||
|
sendData["UserID"] = userID;
|
||||||
|
|
||||||
|
MakeRequest("DELETE", sendData);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
#region Make Request
|
||||||
|
|
||||||
|
private Dictionary<string, object> MakeRequest(string method, Dictionary<string, object> sendData)
|
||||||
|
{
|
||||||
|
sendData["METHOD"] = method;
|
||||||
|
|
||||||
|
string reply = string.Empty;
|
||||||
|
lock (m_Lock)
|
||||||
|
reply = SynchronousRestFormsRequester.MakeRequest("POST",
|
||||||
|
m_ServerURI + "/offlineim",
|
||||||
|
ServerUtils.BuildQueryString(sendData),
|
||||||
|
m_Auth);
|
||||||
|
|
||||||
|
Dictionary<string, object> replyData = ServerUtils.ParseXmlResponse(
|
||||||
|
reply);
|
||||||
|
|
||||||
|
return replyData;
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,223 @@
|
||||||
|
/*
|
||||||
|
* 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.Reflection;
|
||||||
|
using System.Text;
|
||||||
|
using System.Xml;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using Nini.Config;
|
||||||
|
using OpenSim.Framework;
|
||||||
|
using OpenSim.Server.Base;
|
||||||
|
using OpenSim.Services.Interfaces;
|
||||||
|
using OpenSim.Framework.Servers.HttpServer;
|
||||||
|
using OpenSim.Framework.ServiceAuth;
|
||||||
|
using OpenSim.Server.Handlers.Base;
|
||||||
|
using log4net;
|
||||||
|
using OpenMetaverse;
|
||||||
|
|
||||||
|
namespace OpenSim.OfflineIM
|
||||||
|
{
|
||||||
|
public class OfflineIMServiceRobustConnector : ServiceConnector
|
||||||
|
{
|
||||||
|
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
|
|
||||||
|
private IOfflineIMService m_OfflineIMService;
|
||||||
|
private string m_ConfigName = "Messaging";
|
||||||
|
|
||||||
|
public OfflineIMServiceRobustConnector(IConfigSource config, IHttpServer server, string configName) :
|
||||||
|
base(config, server, configName)
|
||||||
|
{
|
||||||
|
if (configName != String.Empty)
|
||||||
|
m_ConfigName = configName;
|
||||||
|
|
||||||
|
m_log.DebugFormat("[OfflineIM.V2.RobustConnector]: Starting with config name {0}", m_ConfigName);
|
||||||
|
|
||||||
|
m_OfflineIMService = new OfflineIMService(config);
|
||||||
|
|
||||||
|
IServiceAuth auth = ServiceAuth.Create(config, m_ConfigName);
|
||||||
|
|
||||||
|
server.AddStreamHandler(new OfflineIMServicePostHandler(m_OfflineIMService, auth));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class OfflineIMServicePostHandler : BaseStreamHandler
|
||||||
|
{
|
||||||
|
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
|
|
||||||
|
private IOfflineIMService m_OfflineIMService;
|
||||||
|
|
||||||
|
public OfflineIMServicePostHandler(IOfflineIMService service, IServiceAuth auth) :
|
||||||
|
base("POST", "/offlineim", auth)
|
||||||
|
{
|
||||||
|
m_OfflineIMService = service;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override byte[] ProcessRequest(string path, Stream requestData,
|
||||||
|
IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
|
||||||
|
{
|
||||||
|
StreamReader sr = new StreamReader(requestData);
|
||||||
|
string body = sr.ReadToEnd();
|
||||||
|
sr.Close();
|
||||||
|
body = body.Trim();
|
||||||
|
|
||||||
|
//m_log.DebugFormat("[XXX]: query String: {0}", body);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Dictionary<string, object> request =
|
||||||
|
ServerUtils.ParseQueryString(body);
|
||||||
|
|
||||||
|
if (!request.ContainsKey("METHOD"))
|
||||||
|
return FailureResult();
|
||||||
|
|
||||||
|
string method = request["METHOD"].ToString();
|
||||||
|
request.Remove("METHOD");
|
||||||
|
|
||||||
|
switch (method)
|
||||||
|
{
|
||||||
|
case "GET":
|
||||||
|
return HandleGet(request);
|
||||||
|
case "STORE":
|
||||||
|
return HandleStore(request);
|
||||||
|
case "DELETE":
|
||||||
|
return HandleDelete(request);
|
||||||
|
}
|
||||||
|
m_log.DebugFormat("[OFFLINE IM HANDLER]: unknown method request: {0}", method);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
m_log.Error(string.Format("[OFFLINE IM HANDLER]: Exception {0} ", e.Message), e);
|
||||||
|
}
|
||||||
|
|
||||||
|
return FailureResult();
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] HandleStore(Dictionary<string, object> request)
|
||||||
|
{
|
||||||
|
Dictionary<string, object> result = new Dictionary<string, object>();
|
||||||
|
|
||||||
|
GridInstantMessage im = OfflineIMDataUtils.GridInstantMessage(request);
|
||||||
|
|
||||||
|
string reason = string.Empty;
|
||||||
|
|
||||||
|
bool success = m_OfflineIMService.StoreMessage(im, out reason);
|
||||||
|
|
||||||
|
result["RESULT"] = success.ToString();
|
||||||
|
if (!success)
|
||||||
|
result["REASON"] = reason;
|
||||||
|
|
||||||
|
string xmlString = ServerUtils.BuildXmlResponse(result);
|
||||||
|
|
||||||
|
//m_log.DebugFormat("[XXX]: resp string: {0}", xmlString);
|
||||||
|
return Util.UTF8NoBomEncoding.GetBytes(xmlString);
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] HandleGet(Dictionary<string, object> request)
|
||||||
|
{
|
||||||
|
Dictionary<string, object> result = new Dictionary<string, object>();
|
||||||
|
|
||||||
|
if (!request.ContainsKey("PrincipalID"))
|
||||||
|
NullResult(result, "Bad network data");
|
||||||
|
else
|
||||||
|
{
|
||||||
|
UUID principalID = new UUID(request["PrincipalID"].ToString());
|
||||||
|
List<GridInstantMessage> ims = m_OfflineIMService.GetMessages(principalID);
|
||||||
|
|
||||||
|
Dictionary<string, object> dict = new Dictionary<string, object>();
|
||||||
|
int i = 0;
|
||||||
|
foreach (GridInstantMessage m in ims)
|
||||||
|
dict["im-" + i++] = OfflineIMDataUtils.GridInstantMessage(m);
|
||||||
|
|
||||||
|
result["RESULT"] = dict;
|
||||||
|
}
|
||||||
|
|
||||||
|
string xmlString = ServerUtils.BuildXmlResponse(result);
|
||||||
|
|
||||||
|
//m_log.DebugFormat("[XXX]: resp string: {0}", 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
|
||||||
|
|
||||||
|
private void NullResult(Dictionary<string, object> result, string reason)
|
||||||
|
{
|
||||||
|
result["RESULT"] = "NULL";
|
||||||
|
result["REASON"] = reason;
|
||||||
|
}
|
||||||
|
|
||||||
|
private byte[] FailureResult()
|
||||||
|
{
|
||||||
|
return BoolResult(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
private byte[] SuccessResult()
|
||||||
|
{
|
||||||
|
return BoolResult(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private byte[] BoolResult(bool value)
|
||||||
|
{
|
||||||
|
XmlDocument doc = new XmlDocument();
|
||||||
|
|
||||||
|
XmlNode xmlnode = doc.CreateNode(XmlNodeType.XmlDeclaration,
|
||||||
|
"", "");
|
||||||
|
|
||||||
|
doc.AppendChild(xmlnode);
|
||||||
|
|
||||||
|
XmlElement rootElement = doc.CreateElement("", "ServerResponse",
|
||||||
|
"");
|
||||||
|
|
||||||
|
doc.AppendChild(rootElement);
|
||||||
|
|
||||||
|
XmlElement result = doc.CreateElement("", "RESULT", "");
|
||||||
|
result.AppendChild(doc.CreateTextNode(value.ToString()));
|
||||||
|
|
||||||
|
rootElement.AppendChild(result);
|
||||||
|
|
||||||
|
return Util.DocToBytes(doc);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,134 @@
|
||||||
|
/*
|
||||||
|
* 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.IO;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Runtime.Serialization;
|
||||||
|
using System.Text;
|
||||||
|
using System.Timers;
|
||||||
|
using System.Xml;
|
||||||
|
using System.Xml.Serialization;
|
||||||
|
using log4net;
|
||||||
|
using Nini.Config;
|
||||||
|
|
||||||
|
using OpenMetaverse;
|
||||||
|
using OpenSim.Data;
|
||||||
|
using OpenSim.Framework;
|
||||||
|
using OpenSim.Services.Interfaces;
|
||||||
|
|
||||||
|
namespace OpenSim.OfflineIM
|
||||||
|
{
|
||||||
|
public class OfflineIMService : OfflineIMServiceBase, IOfflineIMService
|
||||||
|
{
|
||||||
|
// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
|
private const int MAX_IM = 25;
|
||||||
|
|
||||||
|
private XmlSerializer m_serializer;
|
||||||
|
private static bool m_Initialized = false;
|
||||||
|
|
||||||
|
public OfflineIMService(IConfigSource config)
|
||||||
|
: base(config)
|
||||||
|
{
|
||||||
|
m_serializer = new XmlSerializer(typeof(GridInstantMessage));
|
||||||
|
if (!m_Initialized)
|
||||||
|
{
|
||||||
|
m_Database.DeleteOld();
|
||||||
|
m_Initialized = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<GridInstantMessage> GetMessages(UUID principalID)
|
||||||
|
{
|
||||||
|
List<GridInstantMessage> ims = new List<GridInstantMessage>();
|
||||||
|
|
||||||
|
OfflineIMData[] messages = m_Database.Get("PrincipalID", principalID.ToString());
|
||||||
|
|
||||||
|
if (messages == null || (messages != null && messages.Length == 0))
|
||||||
|
return ims;
|
||||||
|
|
||||||
|
foreach (OfflineIMData m in messages)
|
||||||
|
{
|
||||||
|
using (MemoryStream mstream = new MemoryStream(Encoding.UTF8.GetBytes(m.Data["Message"])))
|
||||||
|
{
|
||||||
|
GridInstantMessage im = (GridInstantMessage)m_serializer.Deserialize(mstream);
|
||||||
|
ims.Add(im);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Then, delete them
|
||||||
|
m_Database.Delete("PrincipalID", principalID.ToString());
|
||||||
|
|
||||||
|
return ims;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool StoreMessage(GridInstantMessage im, out string reason)
|
||||||
|
{
|
||||||
|
reason = string.Empty;
|
||||||
|
|
||||||
|
// Check limits
|
||||||
|
UUID principalID = new UUID(im.toAgentID);
|
||||||
|
long count = m_Database.GetCount("PrincipalID", principalID.ToString());
|
||||||
|
if (count >= MAX_IM)
|
||||||
|
{
|
||||||
|
reason = "Number of offline IMs has maxed out";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
string imXml;
|
||||||
|
using (MemoryStream mstream = new MemoryStream())
|
||||||
|
{
|
||||||
|
XmlWriterSettings settings = new XmlWriterSettings();
|
||||||
|
settings.Encoding = Util.UTF8NoBomEncoding;
|
||||||
|
|
||||||
|
using (XmlWriter writer = XmlWriter.Create(mstream, settings))
|
||||||
|
{
|
||||||
|
m_serializer.Serialize(writer, im);
|
||||||
|
writer.Flush();
|
||||||
|
imXml = Util.UTF8NoBomEncoding.GetString(mstream.ToArray());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
OfflineIMData data = new OfflineIMData();
|
||||||
|
data.PrincipalID = principalID;
|
||||||
|
data.FromID = new UUID(im.fromAgentID);
|
||||||
|
data.Data = new Dictionary<string, string>();
|
||||||
|
data.Data["Message"] = imXml;
|
||||||
|
|
||||||
|
return m_Database.Store(data);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void DeleteMessages(UUID userID)
|
||||||
|
{
|
||||||
|
m_Database.Delete("PrincipalID", userID.ToString());
|
||||||
|
m_Database.Delete("FromID", userID.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,83 @@
|
||||||
|
/*
|
||||||
|
* 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.Reflection;
|
||||||
|
using Nini.Config;
|
||||||
|
using OpenSim.Framework;
|
||||||
|
using OpenSim.Data;
|
||||||
|
using OpenSim.Services.Interfaces;
|
||||||
|
using OpenSim.Services.Base;
|
||||||
|
|
||||||
|
namespace OpenSim.OfflineIM
|
||||||
|
{
|
||||||
|
public class OfflineIMServiceBase : ServiceBase
|
||||||
|
{
|
||||||
|
protected IOfflineIMData m_Database = null;
|
||||||
|
|
||||||
|
public OfflineIMServiceBase(IConfigSource config)
|
||||||
|
: base(config)
|
||||||
|
{
|
||||||
|
string dllName = String.Empty;
|
||||||
|
string connString = String.Empty;
|
||||||
|
string realm = "im_offline";
|
||||||
|
|
||||||
|
//
|
||||||
|
// Try reading the [DatabaseService] section, if it exists
|
||||||
|
//
|
||||||
|
IConfig dbConfig = config.Configs["DatabaseService"];
|
||||||
|
if (dbConfig != null)
|
||||||
|
{
|
||||||
|
if (dllName == String.Empty)
|
||||||
|
dllName = dbConfig.GetString("StorageProvider", String.Empty);
|
||||||
|
if (connString == String.Empty)
|
||||||
|
connString = dbConfig.GetString("ConnectionString", String.Empty);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// [Messaging] section overrides [DatabaseService], if it exists
|
||||||
|
//
|
||||||
|
IConfig imConfig = config.Configs["Messaging"];
|
||||||
|
if (imConfig != null)
|
||||||
|
{
|
||||||
|
dllName = imConfig.GetString("StorageProvider", dllName);
|
||||||
|
connString = imConfig.GetString("ConnectionString", connString);
|
||||||
|
realm = imConfig.GetString("Realm", realm);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// We tried, but this doesn't exist. We can't proceed.
|
||||||
|
//
|
||||||
|
if (dllName.Equals(String.Empty))
|
||||||
|
throw new Exception("No StorageProvider configured");
|
||||||
|
|
||||||
|
m_Database = LoadPlugin<IOfflineIMData>(dllName, new Object[] { connString, realm });
|
||||||
|
if (m_Database == null)
|
||||||
|
throw new Exception("Could not find a storage interface in the given module " + dllName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,38 @@
|
||||||
|
/*
|
||||||
|
* 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 Nini.Config;
|
||||||
|
using OpenSim.Framework;
|
||||||
|
|
||||||
|
namespace OpenSim.ApplicationPlugins.LoadRegions
|
||||||
|
{
|
||||||
|
public interface IRegionLoader
|
||||||
|
{
|
||||||
|
void SetIniConfigSource(IConfigSource configSource);
|
||||||
|
RegionInfo[] LoadRegions();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,208 @@
|
||||||
|
/*
|
||||||
|
* 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.Reflection;
|
||||||
|
using System.Threading;
|
||||||
|
using log4net;
|
||||||
|
using OpenMetaverse;
|
||||||
|
using OpenSim.Framework;
|
||||||
|
using OpenSim.Region.CoreModules.Agent.AssetTransaction;
|
||||||
|
using OpenSim.Region.CoreModules.Avatar.InstantMessage;
|
||||||
|
using OpenSim.Region.CoreModules.Scripting.DynamicTexture;
|
||||||
|
using OpenSim.Region.CoreModules.Scripting.LoadImageURL;
|
||||||
|
using OpenSim.Region.CoreModules.Scripting.XMLRPC;
|
||||||
|
using OpenSim.Services.Interfaces;
|
||||||
|
using Mono.Addins;
|
||||||
|
|
||||||
|
namespace OpenSim.ApplicationPlugins.LoadRegions
|
||||||
|
{
|
||||||
|
[Extension(Path="/OpenSim/Startup", Id="LoadRegions", NodeName="Plugin")]
|
||||||
|
public class LoadRegionsPlugin : IApplicationPlugin, IRegionCreator
|
||||||
|
{
|
||||||
|
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
|
|
||||||
|
public event NewRegionCreated OnNewRegionCreated;
|
||||||
|
private NewRegionCreated m_newRegionCreatedHandler;
|
||||||
|
|
||||||
|
#region IApplicationPlugin Members
|
||||||
|
|
||||||
|
// TODO: required by IPlugin, but likely not at all right
|
||||||
|
private string m_name = "LoadRegionsPlugin";
|
||||||
|
private string m_version = "0.0";
|
||||||
|
|
||||||
|
public string Version
|
||||||
|
{
|
||||||
|
get { return m_version; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Name
|
||||||
|
{
|
||||||
|
get { return m_name; }
|
||||||
|
}
|
||||||
|
|
||||||
|
protected OpenSimBase m_openSim;
|
||||||
|
|
||||||
|
public void Initialise()
|
||||||
|
{
|
||||||
|
m_log.Error("[LOAD REGIONS PLUGIN]: " + Name + " cannot be default-initialized!");
|
||||||
|
throw new PluginNotInitialisedException(Name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Initialise(OpenSimBase openSim)
|
||||||
|
{
|
||||||
|
m_openSim = openSim;
|
||||||
|
m_openSim.ApplicationRegistry.RegisterInterface<IRegionCreator>(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void PostInitialise()
|
||||||
|
{
|
||||||
|
//m_log.Info("[LOADREGIONS]: Load Regions addin being initialised");
|
||||||
|
|
||||||
|
IRegionLoader regionLoader;
|
||||||
|
if (m_openSim.ConfigSource.Source.Configs["Startup"].GetString("region_info_source", "filesystem") == "filesystem")
|
||||||
|
{
|
||||||
|
m_log.Info("[LOAD REGIONS PLUGIN]: Loading region configurations from filesystem");
|
||||||
|
regionLoader = new RegionLoaderFileSystem();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_log.Info("[LOAD REGIONS PLUGIN]: Loading region configurations from web");
|
||||||
|
regionLoader = new RegionLoaderWebServer();
|
||||||
|
}
|
||||||
|
|
||||||
|
regionLoader.SetIniConfigSource(m_openSim.ConfigSource.Source);
|
||||||
|
RegionInfo[] regionsToLoad = regionLoader.LoadRegions();
|
||||||
|
|
||||||
|
m_log.Info("[LOAD REGIONS PLUGIN]: Loading specific shared modules...");
|
||||||
|
//m_log.Info("[LOAD REGIONS PLUGIN]: DynamicTextureModule...");
|
||||||
|
//m_openSim.ModuleLoader.LoadDefaultSharedModule(new DynamicTextureModule());
|
||||||
|
//m_log.Info("[LOAD REGIONS PLUGIN]: LoadImageURLModule...");
|
||||||
|
//m_openSim.ModuleLoader.LoadDefaultSharedModule(new LoadImageURLModule());
|
||||||
|
//m_log.Info("[LOAD REGIONS PLUGIN]: XMLRPCModule...");
|
||||||
|
//m_openSim.ModuleLoader.LoadDefaultSharedModule(new XMLRPCModule());
|
||||||
|
// m_log.Info("[LOADREGIONSPLUGIN]: AssetTransactionModule...");
|
||||||
|
// m_openSim.ModuleLoader.LoadDefaultSharedModule(new AssetTransactionModule());
|
||||||
|
m_log.Info("[LOAD REGIONS PLUGIN]: Done.");
|
||||||
|
|
||||||
|
if (!CheckRegionsForSanity(regionsToLoad))
|
||||||
|
{
|
||||||
|
m_log.Error("[LOAD REGIONS PLUGIN]: Halting startup due to conflicts in region configurations");
|
||||||
|
Environment.Exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
List<IScene> createdScenes = new List<IScene>();
|
||||||
|
|
||||||
|
for (int i = 0; i < regionsToLoad.Length; i++)
|
||||||
|
{
|
||||||
|
IScene scene;
|
||||||
|
m_log.Debug("[LOAD REGIONS PLUGIN]: Creating Region: " + regionsToLoad[i].RegionName + " (ThreadID: " +
|
||||||
|
Thread.CurrentThread.ManagedThreadId.ToString() +
|
||||||
|
")");
|
||||||
|
|
||||||
|
bool changed = m_openSim.PopulateRegionEstateInfo(regionsToLoad[i]);
|
||||||
|
|
||||||
|
m_openSim.CreateRegion(regionsToLoad[i], true, out scene);
|
||||||
|
createdScenes.Add(scene);
|
||||||
|
|
||||||
|
if (changed)
|
||||||
|
m_openSim.EstateDataService.StoreEstateSettings(regionsToLoad[i].EstateSettings);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (IScene scene in createdScenes)
|
||||||
|
{
|
||||||
|
scene.Start();
|
||||||
|
|
||||||
|
m_newRegionCreatedHandler = OnNewRegionCreated;
|
||||||
|
if (m_newRegionCreatedHandler != null)
|
||||||
|
{
|
||||||
|
m_newRegionCreatedHandler(scene);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Check that region configuration information makes sense.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="regions"></param>
|
||||||
|
/// <returns>True if we're sane, false if we're insane</returns>
|
||||||
|
private bool CheckRegionsForSanity(RegionInfo[] regions)
|
||||||
|
{
|
||||||
|
if (regions.Length == 0)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
foreach (RegionInfo region in regions)
|
||||||
|
{
|
||||||
|
if (region.RegionID == UUID.Zero)
|
||||||
|
{
|
||||||
|
m_log.ErrorFormat(
|
||||||
|
"[LOAD REGIONS PLUGIN]: Region {0} has invalid UUID {1}",
|
||||||
|
region.RegionName, region.RegionID);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < regions.Length - 1; i++)
|
||||||
|
{
|
||||||
|
for (int j = i + 1; j < regions.Length; j++)
|
||||||
|
{
|
||||||
|
if (regions[i].RegionID == regions[j].RegionID)
|
||||||
|
{
|
||||||
|
m_log.ErrorFormat(
|
||||||
|
"[LOAD REGIONS PLUGIN]: Regions {0} and {1} have the same UUID {2}",
|
||||||
|
regions[i].RegionName, regions[j].RegionName, regions[i].RegionID);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else if (
|
||||||
|
regions[i].RegionLocX == regions[j].RegionLocX && regions[i].RegionLocY == regions[j].RegionLocY)
|
||||||
|
{
|
||||||
|
m_log.ErrorFormat(
|
||||||
|
"[LOAD REGIONS PLUGIN]: Regions {0} and {1} have the same grid location ({2}, {3})",
|
||||||
|
regions[i].RegionName, regions[j].RegionName, regions[i].RegionLocX, regions[i].RegionLocY);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else if (regions[i].InternalEndPoint.Port == regions[j].InternalEndPoint.Port)
|
||||||
|
{
|
||||||
|
m_log.ErrorFormat(
|
||||||
|
"[LOAD REGIONS PLUGIN]: Regions {0} and {1} have the same internal IP port {2}",
|
||||||
|
regions[i].RegionName, regions[j].RegionName, regions[i].InternalEndPoint.Port);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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.Reflection;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using Mono.Addins;
|
||||||
|
|
||||||
|
// General information about an assembly is controlled through the following
|
||||||
|
// set of attributes. Change these attribute values to modify the information
|
||||||
|
// associated with an assembly.
|
||||||
|
|
||||||
|
[assembly : AssemblyTitle("OpenSim.ApplicationPlugins.LoadRegions")]
|
||||||
|
[assembly : AssemblyDescription("")]
|
||||||
|
[assembly : AssemblyConfiguration("")]
|
||||||
|
[assembly : AssemblyCompany("http://opensimulator.org")]
|
||||||
|
[assembly : AssemblyProduct("OpenSim")]
|
||||||
|
[assembly : AssemblyCopyright("Copyright © OpenSimulator.org Developers 2007-2009")]
|
||||||
|
[assembly : AssemblyTrademark("")]
|
||||||
|
[assembly : AssemblyCulture("")]
|
||||||
|
|
||||||
|
// Setting ComVisible to false makes the types in this assembly not visible
|
||||||
|
// to COM components. If you need to access a type in this assembly from
|
||||||
|
// COM, set the ComVisible attribute to true on that type.
|
||||||
|
|
||||||
|
[assembly : ComVisible(false)]
|
||||||
|
|
||||||
|
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||||
|
|
||||||
|
[assembly : Guid("45b979d9-d8d4-42fd-9780-fe9ac7e86cb4")]
|
||||||
|
|
||||||
|
// Version information for an assembly consists of the following four values:
|
||||||
|
//
|
||||||
|
// Major Version
|
||||||
|
// Minor Version
|
||||||
|
// Build Number
|
||||||
|
// Revision
|
||||||
|
//
|
||||||
|
// You can specify all the values or you can default the Build and Revision Numbers
|
||||||
|
// by using the '*' as shown below:
|
||||||
|
|
||||||
|
[assembly : AssemblyVersion(OpenSim.VersionInfo.AssemblyVersionNumber)]
|
||||||
|
|
||||||
|
[assembly: Addin("OpenSim.ApplicationPlugins.LoadRegions", OpenSim.VersionInfo.VersionNumber)]
|
||||||
|
[assembly: AddinDependency("OpenSim", OpenSim.VersionInfo.VersionNumber)]
|
|
@ -0,0 +1,117 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) Contributors, http://opensimulator.org/
|
||||||
|
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of the OpenSimulator Project nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
||||||
|
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using log4net;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Reflection;
|
||||||
|
using Nini.Config;
|
||||||
|
using OpenSim.Framework;
|
||||||
|
|
||||||
|
namespace OpenSim.ApplicationPlugins.LoadRegions
|
||||||
|
{
|
||||||
|
public class RegionLoaderFileSystem : IRegionLoader
|
||||||
|
{
|
||||||
|
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
|
|
||||||
|
private IConfigSource m_configSource;
|
||||||
|
|
||||||
|
public void SetIniConfigSource(IConfigSource configSource)
|
||||||
|
{
|
||||||
|
m_configSource = configSource;
|
||||||
|
}
|
||||||
|
|
||||||
|
public RegionInfo[] LoadRegions()
|
||||||
|
{
|
||||||
|
string regionConfigPath = Path.Combine(Util.configDir(), "Regions");
|
||||||
|
bool allowRegionless = false;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
IConfig startupConfig = (IConfig)m_configSource.Configs["Startup"];
|
||||||
|
regionConfigPath = startupConfig.GetString("regionload_regionsdir", regionConfigPath).Trim();
|
||||||
|
allowRegionless = startupConfig.GetBoolean("allow_regionless", false);
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
// No INI setting recorded.
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Directory.Exists(regionConfigPath))
|
||||||
|
{
|
||||||
|
Directory.CreateDirectory(regionConfigPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
string[] configFiles = Directory.GetFiles(regionConfigPath, "*.xml");
|
||||||
|
string[] iniFiles = Directory.GetFiles(regionConfigPath, "*.ini");
|
||||||
|
|
||||||
|
// Create an empty Regions.ini if there are no existing config files.
|
||||||
|
if (!allowRegionless && configFiles.Length == 0 && iniFiles.Length == 0)
|
||||||
|
{
|
||||||
|
new RegionInfo("DEFAULT REGION CONFIG", Path.Combine(regionConfigPath, "Regions.ini"), false, m_configSource);
|
||||||
|
iniFiles = Directory.GetFiles(regionConfigPath, "*.ini");
|
||||||
|
}
|
||||||
|
|
||||||
|
m_log.InfoFormat("[REGION LOADER FILE SYSTEM]: Loading config files from {0}", regionConfigPath);
|
||||||
|
|
||||||
|
List<RegionInfo> regionInfos = new List<RegionInfo>();
|
||||||
|
|
||||||
|
int i = 0;
|
||||||
|
foreach (string file in iniFiles)
|
||||||
|
{
|
||||||
|
m_log.InfoFormat("[REGION LOADER FILE SYSTEM]: Loading config file {0}", file);
|
||||||
|
|
||||||
|
IConfigSource source = new IniConfigSource(file);
|
||||||
|
|
||||||
|
foreach (IConfig config in source.Configs)
|
||||||
|
{
|
||||||
|
RegionInfo regionInfo = new RegionInfo("REGION CONFIG #" + (i + 1), file, false, m_configSource, config.Name);
|
||||||
|
regionInfos.Add(regionInfo);
|
||||||
|
|
||||||
|
m_log.InfoFormat("[REGION LOADER FILE SYSTEM]: Loaded config for region {0}", regionInfo.RegionName);
|
||||||
|
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (string file in configFiles)
|
||||||
|
{
|
||||||
|
m_log.InfoFormat("[REGION LOADER FILE SYSTEM]: Loading config file {0}", file);
|
||||||
|
|
||||||
|
RegionInfo regionInfo = new RegionInfo("REGION CONFIG #" + (i + 1), file, false, m_configSource);
|
||||||
|
regionInfos.Add(regionInfo);
|
||||||
|
|
||||||
|
m_log.InfoFormat("[REGION LOADER FILE SYSTEM]: Loaded config for region {0}", regionInfo.RegionName);
|
||||||
|
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return regionInfos.ToArray();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,143 @@
|
||||||
|
/*
|
||||||
|
* 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.IO;
|
||||||
|
using System.Net;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Xml;
|
||||||
|
using log4net;
|
||||||
|
using Nini.Config;
|
||||||
|
using OpenSim.Framework;
|
||||||
|
|
||||||
|
namespace OpenSim.ApplicationPlugins.LoadRegions
|
||||||
|
{
|
||||||
|
public class RegionLoaderWebServer : IRegionLoader
|
||||||
|
{
|
||||||
|
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
|
|
||||||
|
private IConfigSource m_configSource;
|
||||||
|
|
||||||
|
public void SetIniConfigSource(IConfigSource configSource)
|
||||||
|
{
|
||||||
|
m_configSource = configSource;
|
||||||
|
}
|
||||||
|
|
||||||
|
public RegionInfo[] LoadRegions()
|
||||||
|
{
|
||||||
|
int tries = 3;
|
||||||
|
int wait = 2000;
|
||||||
|
|
||||||
|
if (m_configSource == null)
|
||||||
|
{
|
||||||
|
m_log.Error("[WEBLOADER]: Unable to load configuration source!");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
IConfig startupConfig = (IConfig)m_configSource.Configs["Startup"];
|
||||||
|
string url = startupConfig.GetString("regionload_webserver_url", String.Empty).Trim();
|
||||||
|
bool allowRegionless = startupConfig.GetBoolean("allow_regionless", false);
|
||||||
|
|
||||||
|
if (url == String.Empty)
|
||||||
|
{
|
||||||
|
m_log.Error("[WEBLOADER]: Unable to load webserver URL - URL was empty.");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
while (tries > 0)
|
||||||
|
{
|
||||||
|
RegionInfo[] regionInfos = new RegionInfo[] { };
|
||||||
|
int regionCount = 0;
|
||||||
|
HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(url);
|
||||||
|
webRequest.Timeout = 30000; //30 Second Timeout
|
||||||
|
m_log.DebugFormat("[WEBLOADER]: Sending download request to {0}", url);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
HttpWebResponse webResponse = (HttpWebResponse)webRequest.GetResponse();
|
||||||
|
m_log.Debug("[WEBLOADER]: Downloading region information...");
|
||||||
|
StreamReader reader = new StreamReader(webResponse.GetResponseStream());
|
||||||
|
string xmlSource = String.Empty;
|
||||||
|
string tempStr = reader.ReadLine();
|
||||||
|
while (tempStr != null)
|
||||||
|
{
|
||||||
|
xmlSource = xmlSource + tempStr;
|
||||||
|
tempStr = reader.ReadLine();
|
||||||
|
}
|
||||||
|
m_log.Debug("[WEBLOADER]: Done downloading region information from server. Total Bytes: " +
|
||||||
|
xmlSource.Length);
|
||||||
|
XmlDocument xmlDoc = new XmlDocument();
|
||||||
|
xmlDoc.LoadXml(xmlSource);
|
||||||
|
if (xmlDoc.FirstChild.Name == "Nini")
|
||||||
|
{
|
||||||
|
regionCount = xmlDoc.FirstChild.ChildNodes.Count;
|
||||||
|
|
||||||
|
if (regionCount > 0)
|
||||||
|
{
|
||||||
|
regionInfos = new RegionInfo[regionCount];
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < xmlDoc.FirstChild.ChildNodes.Count; i++)
|
||||||
|
{
|
||||||
|
m_log.Debug(xmlDoc.FirstChild.ChildNodes[i].OuterXml);
|
||||||
|
regionInfos[i] =
|
||||||
|
new RegionInfo("REGION CONFIG #" + (i + 1), xmlDoc.FirstChild.ChildNodes[i], false, m_configSource);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (WebException ex)
|
||||||
|
{
|
||||||
|
if (((HttpWebResponse)ex.Response).StatusCode == HttpStatusCode.NotFound)
|
||||||
|
{
|
||||||
|
if (!allowRegionless)
|
||||||
|
throw ex;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
throw ex;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (regionCount > 0 || allowRegionless)
|
||||||
|
return regionInfos;
|
||||||
|
|
||||||
|
m_log.Debug("[WEBLOADER]: Request yielded no regions.");
|
||||||
|
tries--;
|
||||||
|
if (tries > 0)
|
||||||
|
{
|
||||||
|
m_log.Debug("[WEBLOADER]: Retrying");
|
||||||
|
System.Threading.Thread.Sleep(wait);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_log.Error("[WEBLOADER]: No region configs were available.");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,36 @@
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using Mono.Addins;
|
||||||
|
|
||||||
|
// General Information about an assembly is controlled through the following
|
||||||
|
// set of attributes. Change these attribute values to modify the information
|
||||||
|
// associated with an assembly.
|
||||||
|
[assembly: AssemblyTitle("OpenSim.ApplicationPlugins.RegionModulesController")]
|
||||||
|
[assembly: AssemblyDescription("")]
|
||||||
|
[assembly: AssemblyConfiguration("")]
|
||||||
|
[assembly: AssemblyCompany("http://opensimulator.org")]
|
||||||
|
[assembly: AssemblyProduct("OpenSim")]
|
||||||
|
[assembly: AssemblyCopyright("OpenSimulator developers")]
|
||||||
|
[assembly: AssemblyTrademark("")]
|
||||||
|
[assembly: AssemblyCulture("")]
|
||||||
|
|
||||||
|
// Setting ComVisible to false makes the types in this assembly not visible
|
||||||
|
// to COM components. If you need to access a type in this assembly from
|
||||||
|
// COM, set the ComVisible attribute to true on that type.
|
||||||
|
[assembly: ComVisible(false)]
|
||||||
|
|
||||||
|
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||||
|
[assembly: Guid("c023816d-194e-40c1-9195-a0f281d4ac5d")]
|
||||||
|
|
||||||
|
// Version information for an assembly consists of the following four values:
|
||||||
|
//
|
||||||
|
// Major Version
|
||||||
|
// Minor Version
|
||||||
|
// Build Number
|
||||||
|
// Revision
|
||||||
|
//
|
||||||
|
[assembly: AssemblyVersion(OpenSim.VersionInfo.AssemblyVersionNumber)]
|
||||||
|
|
||||||
|
[assembly: Addin("OpenSim.ApplicationPlugins.RegionModulesController", OpenSim.VersionInfo.VersionNumber)]
|
||||||
|
[assembly: AddinDependency("OpenSim", OpenSim.VersionInfo.VersionNumber)]
|
|
@ -0,0 +1,535 @@
|
||||||
|
/*
|
||||||
|
* 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.Reflection;
|
||||||
|
using log4net;
|
||||||
|
using Mono.Addins;
|
||||||
|
using Nini.Config;
|
||||||
|
using OpenSim;
|
||||||
|
using OpenSim.Framework;
|
||||||
|
using OpenSim.Region.Framework.Interfaces;
|
||||||
|
using OpenSim.Region.Framework.Scenes;
|
||||||
|
|
||||||
|
namespace OpenSim.ApplicationPlugins.RegionModulesController
|
||||||
|
{
|
||||||
|
[Extension(Path = "/OpenSim/Startup", Id = "LoadRegions", NodeName = "Plugin")]
|
||||||
|
public class RegionModulesControllerPlugin : IRegionModulesController,
|
||||||
|
IApplicationPlugin
|
||||||
|
{
|
||||||
|
// Logger
|
||||||
|
private static readonly ILog m_log =
|
||||||
|
LogManager.GetLogger(
|
||||||
|
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
|
||||||
|
private OpenSimBase m_openSim;
|
||||||
|
|
||||||
|
// Our name
|
||||||
|
private string m_name;
|
||||||
|
|
||||||
|
// Internal lists to collect information about modules present
|
||||||
|
private List<TypeExtensionNode> m_nonSharedModules =
|
||||||
|
new List<TypeExtensionNode>();
|
||||||
|
private List<TypeExtensionNode> m_sharedModules =
|
||||||
|
new List<TypeExtensionNode>();
|
||||||
|
|
||||||
|
// List of shared module instances, for adding to Scenes
|
||||||
|
private List<ISharedRegionModule> m_sharedInstances =
|
||||||
|
new List<ISharedRegionModule>();
|
||||||
|
|
||||||
|
public RegionModulesControllerPlugin()
|
||||||
|
{
|
||||||
|
LoadModulesFromAddins = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
#region IApplicationPlugin implementation
|
||||||
|
|
||||||
|
public void Initialise (OpenSimBase openSim)
|
||||||
|
{
|
||||||
|
m_openSim = openSim;
|
||||||
|
m_openSim.ApplicationRegistry.RegisterInterface<IRegionModulesController>(this);
|
||||||
|
m_log.DebugFormat("[REGIONMODULES]: Initializing...");
|
||||||
|
|
||||||
|
if (!LoadModulesFromAddins)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Who we are
|
||||||
|
string id = AddinManager.CurrentAddin.Id;
|
||||||
|
|
||||||
|
// Make friendly name
|
||||||
|
int pos = id.LastIndexOf(".");
|
||||||
|
if (pos == -1)
|
||||||
|
m_name = id;
|
||||||
|
else
|
||||||
|
m_name = id.Substring(pos + 1);
|
||||||
|
|
||||||
|
// The [Modules] section in the ini file
|
||||||
|
IConfig modulesConfig =
|
||||||
|
m_openSim.ConfigSource.Source.Configs["Modules"];
|
||||||
|
if (modulesConfig == null)
|
||||||
|
modulesConfig = m_openSim.ConfigSource.Source.AddConfig("Modules");
|
||||||
|
|
||||||
|
Dictionary<RuntimeAddin, IList<int>> loadedModules = new Dictionary<RuntimeAddin, IList<int>>();
|
||||||
|
|
||||||
|
// Scan modules and load all that aren't disabled
|
||||||
|
foreach (TypeExtensionNode node in AddinManager.GetExtensionNodes("/OpenSim/RegionModules"))
|
||||||
|
AddNode(node, modulesConfig, loadedModules);
|
||||||
|
|
||||||
|
foreach (KeyValuePair<RuntimeAddin, IList<int>> loadedModuleData in loadedModules)
|
||||||
|
{
|
||||||
|
m_log.InfoFormat(
|
||||||
|
"[REGIONMODULES]: From plugin {0}, (version {1}), loaded {2} modules, {3} shared, {4} non-shared {5} unknown",
|
||||||
|
loadedModuleData.Key.Id,
|
||||||
|
loadedModuleData.Key.Version,
|
||||||
|
loadedModuleData.Value[0] + loadedModuleData.Value[1] + loadedModuleData.Value[2],
|
||||||
|
loadedModuleData.Value[0], loadedModuleData.Value[1], loadedModuleData.Value[2]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load and init the module. We try a constructor with a port
|
||||||
|
// if a port was given, fall back to one without if there is
|
||||||
|
// no port or the more specific constructor fails.
|
||||||
|
// This will be removed, so that any module capable of using a port
|
||||||
|
// must provide a constructor with a port in the future.
|
||||||
|
// For now, we do this so migration is easy.
|
||||||
|
//
|
||||||
|
foreach (TypeExtensionNode node in m_sharedModules)
|
||||||
|
{
|
||||||
|
Object[] ctorArgs = new Object[] { (uint)0 };
|
||||||
|
|
||||||
|
// Read the config again
|
||||||
|
string moduleString =
|
||||||
|
modulesConfig.GetString("Setup_" + node.Id, String.Empty);
|
||||||
|
// Test to see if we want this module
|
||||||
|
if (moduleString == "disabled")
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Get the port number, if there is one
|
||||||
|
if (moduleString != String.Empty)
|
||||||
|
{
|
||||||
|
// Get the port number from the string
|
||||||
|
string[] moduleParts = moduleString.Split(new char[] { '/' },
|
||||||
|
2);
|
||||||
|
if (moduleParts.Length > 1)
|
||||||
|
ctorArgs[0] = Convert.ToUInt32(moduleParts[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try loading and initilaizing the module, using the
|
||||||
|
// port if appropriate
|
||||||
|
ISharedRegionModule module = null;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
module = (ISharedRegionModule)Activator.CreateInstance(
|
||||||
|
node.Type, ctorArgs);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
module = (ISharedRegionModule)Activator.CreateInstance(
|
||||||
|
node.Type);
|
||||||
|
}
|
||||||
|
|
||||||
|
// OK, we're up and running
|
||||||
|
m_sharedInstances.Add(module);
|
||||||
|
module.Initialise(m_openSim.ConfigSource.Source);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void PostInitialise ()
|
||||||
|
{
|
||||||
|
m_log.DebugFormat("[REGIONMODULES]: PostInitializing...");
|
||||||
|
|
||||||
|
// Immediately run PostInitialise on shared modules
|
||||||
|
foreach (ISharedRegionModule module in m_sharedInstances)
|
||||||
|
{
|
||||||
|
module.PostInitialise();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#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
|
||||||
|
//
|
||||||
|
public void Initialise ()
|
||||||
|
{
|
||||||
|
throw new System.NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region IDisposable implementation
|
||||||
|
|
||||||
|
// Cleanup
|
||||||
|
//
|
||||||
|
public void Dispose ()
|
||||||
|
{
|
||||||
|
// We expect that all regions have been removed already
|
||||||
|
while (m_sharedInstances.Count > 0)
|
||||||
|
{
|
||||||
|
m_sharedInstances[0].Close();
|
||||||
|
m_sharedInstances.RemoveAt(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_sharedModules.Clear();
|
||||||
|
m_nonSharedModules.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
public string Version
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return AddinManager.CurrentAddin.Version;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Name
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return m_name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Region Module interfacesController implementation
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Check that the given module is no disabled in the [Modules] section of the config files.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="node"></param>
|
||||||
|
/// <param name="modulesConfig">The config section</param>
|
||||||
|
/// <returns>true if the module is enabled, false if it is disabled</returns>
|
||||||
|
protected bool CheckModuleEnabled(TypeExtensionNode node, IConfig modulesConfig)
|
||||||
|
{
|
||||||
|
// Get the config string
|
||||||
|
string moduleString =
|
||||||
|
modulesConfig.GetString("Setup_" + node.Id, String.Empty);
|
||||||
|
|
||||||
|
// We have a selector
|
||||||
|
if (moduleString != String.Empty)
|
||||||
|
{
|
||||||
|
// Allow disabling modules even if they don't have
|
||||||
|
// support for it
|
||||||
|
if (moduleString == "disabled")
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Split off port, if present
|
||||||
|
string[] moduleParts = moduleString.Split(new char[] { '/' }, 2);
|
||||||
|
// Format is [port/][class]
|
||||||
|
string className = moduleParts[0];
|
||||||
|
if (moduleParts.Length > 1)
|
||||||
|
className = moduleParts[1];
|
||||||
|
|
||||||
|
// Match the class name if given
|
||||||
|
if (className != String.Empty &&
|
||||||
|
node.Type.ToString() != className)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The root of all evil.
|
||||||
|
// This is where we handle adding the modules to scenes when they
|
||||||
|
// load. This means that here we deal with replaceable interfaces,
|
||||||
|
// nonshared modules, etc.
|
||||||
|
//
|
||||||
|
public void AddRegionToModules (Scene scene)
|
||||||
|
{
|
||||||
|
Dictionary<Type, ISharedRegionModule> deferredSharedModules =
|
||||||
|
new Dictionary<Type, ISharedRegionModule>();
|
||||||
|
Dictionary<Type, INonSharedRegionModule> deferredNonSharedModules =
|
||||||
|
new Dictionary<Type, INonSharedRegionModule>();
|
||||||
|
|
||||||
|
// We need this to see if a module has already been loaded and
|
||||||
|
// has defined a replaceable interface. It's a generic call,
|
||||||
|
// so this can't be used directly. It will be used later
|
||||||
|
Type s = scene.GetType();
|
||||||
|
MethodInfo mi = s.GetMethod("RequestModuleInterface");
|
||||||
|
|
||||||
|
// This will hold the shared modules we actually load
|
||||||
|
List<ISharedRegionModule> sharedlist =
|
||||||
|
new List<ISharedRegionModule>();
|
||||||
|
|
||||||
|
// Iterate over the shared modules that have been loaded
|
||||||
|
// Add them to the new Scene
|
||||||
|
foreach (ISharedRegionModule module in m_sharedInstances)
|
||||||
|
{
|
||||||
|
// Here is where we check if a replaceable interface
|
||||||
|
// is defined. If it is, the module is checked against
|
||||||
|
// the interfaces already defined. If the interface is
|
||||||
|
// defined, we simply skip the module. Else, if the module
|
||||||
|
// defines a replaceable interface, we add it to the deferred
|
||||||
|
// list.
|
||||||
|
Type replaceableInterface = module.ReplaceableInterface;
|
||||||
|
if (replaceableInterface != null)
|
||||||
|
{
|
||||||
|
MethodInfo mii = mi.MakeGenericMethod(replaceableInterface);
|
||||||
|
|
||||||
|
if (mii.Invoke(scene, new object[0]) != null)
|
||||||
|
{
|
||||||
|
m_log.DebugFormat("[REGIONMODULE]: Not loading {0} because another module has registered {1}", module.Name, replaceableInterface.ToString());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
deferredSharedModules[replaceableInterface] = module;
|
||||||
|
m_log.DebugFormat("[REGIONMODULE]: Deferred load of {0}", module.Name);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_log.DebugFormat("[REGIONMODULE]: Adding scene {0} to shared module {1}",
|
||||||
|
scene.RegionInfo.RegionName, module.Name);
|
||||||
|
|
||||||
|
module.AddRegion(scene);
|
||||||
|
scene.AddRegionModule(module.Name, module);
|
||||||
|
|
||||||
|
sharedlist.Add(module);
|
||||||
|
}
|
||||||
|
|
||||||
|
IConfig modulesConfig =
|
||||||
|
m_openSim.ConfigSource.Source.Configs["Modules"];
|
||||||
|
|
||||||
|
// Scan for, and load, nonshared modules
|
||||||
|
List<INonSharedRegionModule> list = new List<INonSharedRegionModule>();
|
||||||
|
foreach (TypeExtensionNode node in m_nonSharedModules)
|
||||||
|
{
|
||||||
|
Object[] ctorArgs = new Object[] {0};
|
||||||
|
|
||||||
|
// Read the config
|
||||||
|
string moduleString =
|
||||||
|
modulesConfig.GetString("Setup_" + node.Id, String.Empty);
|
||||||
|
|
||||||
|
// We may not want to load this at all
|
||||||
|
if (moduleString == "disabled")
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Get the port number, if there is one
|
||||||
|
if (moduleString != String.Empty)
|
||||||
|
{
|
||||||
|
// Get the port number from the string
|
||||||
|
string[] moduleParts = moduleString.Split(new char[] {'/'},
|
||||||
|
2);
|
||||||
|
if (moduleParts.Length > 1)
|
||||||
|
ctorArgs[0] = Convert.ToUInt32(moduleParts[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Actually load it
|
||||||
|
INonSharedRegionModule module = null;
|
||||||
|
|
||||||
|
Type[] ctorParamTypes = new Type[ctorArgs.Length];
|
||||||
|
for (int i = 0; i < ctorParamTypes.Length; i++)
|
||||||
|
ctorParamTypes[i] = ctorArgs[i].GetType();
|
||||||
|
|
||||||
|
if (node.Type.GetConstructor(ctorParamTypes) != null)
|
||||||
|
module = (INonSharedRegionModule)Activator.CreateInstance(node.Type, ctorArgs);
|
||||||
|
else
|
||||||
|
module = (INonSharedRegionModule)Activator.CreateInstance(node.Type);
|
||||||
|
|
||||||
|
// Check for replaceable interfaces
|
||||||
|
Type replaceableInterface = module.ReplaceableInterface;
|
||||||
|
if (replaceableInterface != null)
|
||||||
|
{
|
||||||
|
MethodInfo mii = mi.MakeGenericMethod(replaceableInterface);
|
||||||
|
|
||||||
|
if (mii.Invoke(scene, new object[0]) != null)
|
||||||
|
{
|
||||||
|
m_log.DebugFormat("[REGIONMODULE]: Not loading {0} because another module has registered {1}", module.Name, replaceableInterface.ToString());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
deferredNonSharedModules[replaceableInterface] = module;
|
||||||
|
m_log.DebugFormat("[REGIONMODULE]: Deferred load of {0}", module.Name);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_log.DebugFormat("[REGIONMODULE]: Adding scene {0} to non-shared module {1}",
|
||||||
|
scene.RegionInfo.RegionName, module.Name);
|
||||||
|
|
||||||
|
// Initialise the module
|
||||||
|
module.Initialise(m_openSim.ConfigSource.Source);
|
||||||
|
|
||||||
|
list.Add(module);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now add the modules that we found to the scene. If a module
|
||||||
|
// wishes to override a replaceable interface, it needs to
|
||||||
|
// register it in Initialise, so that the deferred module
|
||||||
|
// won't load.
|
||||||
|
foreach (INonSharedRegionModule module in list)
|
||||||
|
{
|
||||||
|
module.AddRegion(scene);
|
||||||
|
scene.AddRegionModule(module.Name, module);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now all modules without a replaceable base interface are loaded
|
||||||
|
// Replaceable modules have either been skipped, or omitted.
|
||||||
|
// Now scan the deferred modules here
|
||||||
|
foreach (ISharedRegionModule module in deferredSharedModules.Values)
|
||||||
|
{
|
||||||
|
// Determine if the interface has been replaced
|
||||||
|
Type replaceableInterface = module.ReplaceableInterface;
|
||||||
|
MethodInfo mii = mi.MakeGenericMethod(replaceableInterface);
|
||||||
|
|
||||||
|
if (mii.Invoke(scene, new object[0]) != null)
|
||||||
|
{
|
||||||
|
m_log.DebugFormat("[REGIONMODULE]: Not loading {0} because another module has registered {1}", module.Name, replaceableInterface.ToString());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_log.DebugFormat("[REGIONMODULE]: Adding scene {0} to shared module {1} (deferred)",
|
||||||
|
scene.RegionInfo.RegionName, module.Name);
|
||||||
|
|
||||||
|
// Not replaced, load the module
|
||||||
|
module.AddRegion(scene);
|
||||||
|
scene.AddRegionModule(module.Name, module);
|
||||||
|
|
||||||
|
sharedlist.Add(module);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Same thing for nonshared modules, load them unless overridden
|
||||||
|
List<INonSharedRegionModule> deferredlist =
|
||||||
|
new List<INonSharedRegionModule>();
|
||||||
|
|
||||||
|
foreach (INonSharedRegionModule module in deferredNonSharedModules.Values)
|
||||||
|
{
|
||||||
|
// Check interface override
|
||||||
|
Type replaceableInterface = module.ReplaceableInterface;
|
||||||
|
if (replaceableInterface != null)
|
||||||
|
{
|
||||||
|
MethodInfo mii = mi.MakeGenericMethod(replaceableInterface);
|
||||||
|
|
||||||
|
if (mii.Invoke(scene, new object[0]) != null)
|
||||||
|
{
|
||||||
|
m_log.DebugFormat("[REGIONMODULE]: Not loading {0} because another module has registered {1}", module.Name, replaceableInterface.ToString());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_log.DebugFormat("[REGIONMODULE]: Adding scene {0} to non-shared module {1} (deferred)",
|
||||||
|
scene.RegionInfo.RegionName, module.Name);
|
||||||
|
|
||||||
|
module.Initialise(m_openSim.ConfigSource.Source);
|
||||||
|
|
||||||
|
list.Add(module);
|
||||||
|
deferredlist.Add(module);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Finally, load valid deferred modules
|
||||||
|
foreach (INonSharedRegionModule module in deferredlist)
|
||||||
|
{
|
||||||
|
module.AddRegion(scene);
|
||||||
|
scene.AddRegionModule(module.Name, module);
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is needed for all module types. Modules will register
|
||||||
|
// Interfaces with scene in AddScene, and will also need a means
|
||||||
|
// to access interfaces registered by other modules. Without
|
||||||
|
// this extra method, a module attempting to use another modules's
|
||||||
|
// interface would be successful only depending on load order,
|
||||||
|
// which can't be depended upon, or modules would need to resort
|
||||||
|
// to ugly kludges to attempt to request interfaces when needed
|
||||||
|
// and unneccessary caching logic repeated in all modules.
|
||||||
|
// The extra function stub is just that much cleaner
|
||||||
|
//
|
||||||
|
foreach (ISharedRegionModule module in sharedlist)
|
||||||
|
{
|
||||||
|
module.RegionLoaded(scene);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (INonSharedRegionModule module in list)
|
||||||
|
{
|
||||||
|
module.RegionLoaded(scene);
|
||||||
|
}
|
||||||
|
|
||||||
|
scene.AllModulesLoaded();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RemoveRegionFromModules (Scene scene)
|
||||||
|
{
|
||||||
|
foreach (IRegionModuleBase module in scene.RegionModules.Values)
|
||||||
|
{
|
||||||
|
m_log.DebugFormat("[REGIONMODULE]: Removing scene {0} from module {1}",
|
||||||
|
scene.RegionInfo.RegionName, module.Name);
|
||||||
|
module.RemoveRegion(scene);
|
||||||
|
if (module is INonSharedRegionModule)
|
||||||
|
{
|
||||||
|
// as we were the only user, this instance has to die
|
||||||
|
module.Close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
scene.RegionModules.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,36 @@
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using Mono.Addins;
|
||||||
|
|
||||||
|
// General Information about an assembly is controlled through the following
|
||||||
|
// set of attributes. Change these attribute values to modify the information
|
||||||
|
// associated with an assembly.
|
||||||
|
[assembly: AssemblyTitle("OpenSim.ApplicationPlugins.RemoteController")]
|
||||||
|
[assembly: AssemblyDescription("")]
|
||||||
|
[assembly: AssemblyConfiguration("")]
|
||||||
|
[assembly: AssemblyCompany("http://opensimulator.org")]
|
||||||
|
[assembly: AssemblyProduct("OpenSim")]
|
||||||
|
[assembly: AssemblyCopyright("Copyright OpenSimulator developers © 2012")]
|
||||||
|
[assembly: AssemblyTrademark("")]
|
||||||
|
[assembly: AssemblyCulture("")]
|
||||||
|
|
||||||
|
// Setting ComVisible to false makes the types in this assembly not visible
|
||||||
|
// to COM components. If you need to access a type in this assembly from
|
||||||
|
// COM, set the ComVisible attribute to true on that type.
|
||||||
|
[assembly: ComVisible(false)]
|
||||||
|
|
||||||
|
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||||
|
[assembly: Guid("efec6e69-fc4a-4e21-86e6-4a261c12d4db")]
|
||||||
|
|
||||||
|
// Version information for an assembly consists of the following four values:
|
||||||
|
//
|
||||||
|
// Major Version
|
||||||
|
// Minor Version
|
||||||
|
// Build Number
|
||||||
|
// Revision
|
||||||
|
//
|
||||||
|
[assembly: AssemblyVersion(OpenSim.VersionInfo.AssemblyVersionNumber)]
|
||||||
|
|
||||||
|
[assembly: Addin("OpenSim.ApplicationPlugins.RemoteController", OpenSim.VersionInfo.VersionNumber)]
|
||||||
|
[assembly: AddinDependency("OpenSim", OpenSim.VersionInfo.VersionNumber)]
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,326 @@
|
||||||
|
/*
|
||||||
|
* 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.Collections.Concurrent;
|
||||||
|
using System.IO;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Threading;
|
||||||
|
using log4net;
|
||||||
|
using Nini.Config;
|
||||||
|
using OpenMetaverse;
|
||||||
|
using OpenSim.Framework.Servers;
|
||||||
|
using OpenSim.Framework.Servers.HttpServer;
|
||||||
|
using OpenSim.Services.Interfaces;
|
||||||
|
|
||||||
|
// using OpenSim.Region.Framework.Interfaces;
|
||||||
|
|
||||||
|
namespace OpenSim.Framework.Capabilities
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// XXX Probably not a particularly nice way of allow us to get the scene presence from the scene (chiefly so that
|
||||||
|
/// we can popup a message on the user's client if the inventory service has permanently failed). But I didn't want
|
||||||
|
/// to just pass the whole Scene into CAPS.
|
||||||
|
/// </summary>
|
||||||
|
public delegate IClientAPI GetClientDelegate(UUID agentID);
|
||||||
|
|
||||||
|
public class Caps : IDisposable
|
||||||
|
{
|
||||||
|
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
|
|
||||||
|
private string m_httpListenerHostName;
|
||||||
|
private uint m_httpListenPort;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// This is the uuid portion of every CAPS path. It is used to make capability urls private to the requester.
|
||||||
|
/// </summary>
|
||||||
|
private string m_capsObjectPath;
|
||||||
|
public string CapsObjectPath { get { return m_capsObjectPath; } }
|
||||||
|
|
||||||
|
private CapsHandlers m_capsHandlers;
|
||||||
|
|
||||||
|
private ConcurrentDictionary<string, PollServiceEventArgs> m_pollServiceHandlers
|
||||||
|
= new ConcurrentDictionary<string, PollServiceEventArgs>();
|
||||||
|
|
||||||
|
private Dictionary<string, string> m_externalCapsHandlers = new Dictionary<string, string>();
|
||||||
|
|
||||||
|
private IHttpServer m_httpListener;
|
||||||
|
private UUID m_agentID;
|
||||||
|
private string m_regionName;
|
||||||
|
private ManualResetEvent m_capsActive = new ManualResetEvent(false);
|
||||||
|
|
||||||
|
public UUID AgentID
|
||||||
|
{
|
||||||
|
get { return m_agentID; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public string RegionName
|
||||||
|
{
|
||||||
|
get { return m_regionName; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public string HostName
|
||||||
|
{
|
||||||
|
get { return m_httpListenerHostName; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public uint Port
|
||||||
|
{
|
||||||
|
get { return m_httpListenPort; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public IHttpServer HttpListener
|
||||||
|
{
|
||||||
|
get { return m_httpListener; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool SSLCaps
|
||||||
|
{
|
||||||
|
get { return m_httpListener.UseSSL; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public string SSLCommonName
|
||||||
|
{
|
||||||
|
get { return m_httpListener.SSLCommonName; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public CapsHandlers CapsHandlers
|
||||||
|
{
|
||||||
|
get { return m_capsHandlers; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public Dictionary<string, string> 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,
|
||||||
|
UUID agent, string regionName)
|
||||||
|
{
|
||||||
|
m_capsObjectPath = capsPath;
|
||||||
|
m_httpListener = httpServer;
|
||||||
|
m_httpListenerHostName = httpListen;
|
||||||
|
|
||||||
|
m_httpListenPort = httpPort;
|
||||||
|
|
||||||
|
if (httpServer != null && httpServer.UseSSL)
|
||||||
|
{
|
||||||
|
m_httpListenPort = httpServer.SSLPort;
|
||||||
|
httpListen = httpServer.SSLCommonName;
|
||||||
|
httpPort = httpServer.SSLPort;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_agentID = agent;
|
||||||
|
m_capsHandlers = new CapsHandlers(httpServer, httpListen, httpPort);
|
||||||
|
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>
|
||||||
|
/// Register a handler. This allows modules to register handlers.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="capName"></param>
|
||||||
|
/// <param name="handler"></param>
|
||||||
|
public void RegisterHandler(string capName, IRequestHandler handler)
|
||||||
|
{
|
||||||
|
//m_log.DebugFormat("[CAPS]: Registering handler for \"{0}\": path {1}", capName, handler.Path);
|
||||||
|
m_capsHandlers[capName] = handler;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RegisterSimpleHandler(string capName, ISimpleStreamHandler handler, bool addToListener = true)
|
||||||
|
{
|
||||||
|
//m_log.DebugFormat("[CAPS]: Registering handler for \"{0}\": path {1}", capName, handler.Path);
|
||||||
|
m_capsHandlers.AddSimpleHandler(capName, handler, addToListener);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RegisterPollHandler(string capName, PollServiceEventArgs pollServiceHandler)
|
||||||
|
{
|
||||||
|
// m_log.DebugFormat(
|
||||||
|
// "[CAPS]: Registering handler with name {0}, url {1} for {2}",
|
||||||
|
// capName, pollServiceHandler.Url, m_agentID, m_regionName);
|
||||||
|
|
||||||
|
if(!m_pollServiceHandlers.TryAdd(capName, pollServiceHandler))
|
||||||
|
{
|
||||||
|
m_log.ErrorFormat(
|
||||||
|
"[CAPS]: Handler with name {0} already registered (ulr {1}, agent {2}, region {3}",
|
||||||
|
capName, pollServiceHandler.Url, m_agentID, m_regionName);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_httpListener.AddPollServiceHTTPHandler(pollServiceHandler);
|
||||||
|
|
||||||
|
// uint port = (MainServer.Instance == null) ? 0 : MainServer.Instance.Port;
|
||||||
|
// string protocol = "http";
|
||||||
|
// string hostName = m_httpListenerHostName;
|
||||||
|
//
|
||||||
|
// if (MainServer.Instance.UseSSL)
|
||||||
|
// {
|
||||||
|
// hostName = MainServer.Instance.SSLCommonName;
|
||||||
|
// port = MainServer.Instance.SSLPort;
|
||||||
|
// protocol = "https";
|
||||||
|
// }
|
||||||
|
|
||||||
|
// RegisterHandler(
|
||||||
|
// capName, String.Format("{0}://{1}:{2}{3}", protocol, hostName, port, pollServiceHandler.Url));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Register an external handler. The service for this capability is somewhere else
|
||||||
|
/// given by the URL.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="capsName"></param>
|
||||||
|
/// <param name="url"></param>
|
||||||
|
public void RegisterHandler(string capsName, string url)
|
||||||
|
{
|
||||||
|
m_externalCapsHandlers.Add(capsName, url);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Remove all CAPS service handlers.
|
||||||
|
/// </summary>
|
||||||
|
public void DeregisterHandlers()
|
||||||
|
{
|
||||||
|
foreach (string capsName in m_capsHandlers.Caps)
|
||||||
|
{
|
||||||
|
m_capsHandlers.Remove(capsName);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (PollServiceEventArgs handler in m_pollServiceHandlers.Values)
|
||||||
|
{
|
||||||
|
m_httpListener.RemovePollServiceHTTPHandler(handler.Url);
|
||||||
|
}
|
||||||
|
m_pollServiceHandlers.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool TryGetPollHandler(string name, out PollServiceEventArgs pollHandler)
|
||||||
|
{
|
||||||
|
return m_pollServiceHandlers.TryGetValue(name, out pollHandler);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Dictionary<string, PollServiceEventArgs> GetPollHandlers()
|
||||||
|
{
|
||||||
|
return new Dictionary<string, PollServiceEventArgs>(m_pollServiceHandlers);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Return an LLSD-serializable Hashtable describing the
|
||||||
|
/// capabilities and their handler details.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="excludeSeed">If true, then exclude the seed cap.</param>
|
||||||
|
public Hashtable GetCapsDetails(bool excludeSeed, List<string> requestedCaps)
|
||||||
|
{
|
||||||
|
Hashtable caps = CapsHandlers.GetCapsDetails(excludeSeed, requestedCaps);
|
||||||
|
|
||||||
|
lock (m_pollServiceHandlers)
|
||||||
|
{
|
||||||
|
foreach (KeyValuePair <string, PollServiceEventArgs> kvp in m_pollServiceHandlers)
|
||||||
|
{
|
||||||
|
if (!requestedCaps.Contains(kvp.Key))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
string hostName = m_httpListenerHostName;
|
||||||
|
uint port = (MainServer.Instance == null) ? 0 : MainServer.Instance.Port;
|
||||||
|
string protocol = "http";
|
||||||
|
|
||||||
|
if (MainServer.Instance.UseSSL)
|
||||||
|
{
|
||||||
|
hostName = MainServer.Instance.SSLCommonName;
|
||||||
|
port = MainServer.Instance.SSLPort;
|
||||||
|
protocol = "https";
|
||||||
|
}
|
||||||
|
caps[kvp.Key] = string.Format("{0}://{1}:{2}{3}", protocol, hostName, port, kvp.Value.Url);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add the external too
|
||||||
|
foreach (KeyValuePair<string, string> kvp in ExternalCapsHandlers)
|
||||||
|
{
|
||||||
|
if (!requestedCaps.Contains(kvp.Key))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
caps[kvp.Key] = kvp.Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return caps;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Activate()
|
||||||
|
{
|
||||||
|
m_capsActive.Set();
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool WaitForActivation()
|
||||||
|
{
|
||||||
|
// Wait for 30s. If that elapses, return false and run without caps
|
||||||
|
return m_capsActive.WaitOne(120000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,224 @@
|
||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Collections.Concurrent;
|
||||||
|
using OpenSim.Framework.Servers;
|
||||||
|
using OpenSim.Framework.Servers.HttpServer;
|
||||||
|
|
||||||
|
namespace OpenSim.Framework.Capabilities
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// CapsHandlers is a cap handler container but also takes
|
||||||
|
/// care of adding and removing cap handlers to and from the
|
||||||
|
/// supplied BaseHttpServer.
|
||||||
|
/// </summary>
|
||||||
|
public class CapsHandlers
|
||||||
|
{
|
||||||
|
private Dictionary<string, IRequestHandler> m_capsHandlers = new Dictionary<string, IRequestHandler>();
|
||||||
|
private ConcurrentDictionary<string, ISimpleStreamHandler> m_capsSimpleHandlers = new ConcurrentDictionary<string, ISimpleStreamHandler>();
|
||||||
|
private IHttpServer m_httpListener;
|
||||||
|
private string m_httpListenerHostName;
|
||||||
|
private uint m_httpListenerPort;
|
||||||
|
private bool m_useSSL = 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)
|
||||||
|
{
|
||||||
|
m_httpListener = httpListener;
|
||||||
|
m_httpListenerHostName = httpListenerHostname;
|
||||||
|
m_httpListenerPort = httpListenerPort;
|
||||||
|
if (httpListener != null && httpListener.UseSSL)
|
||||||
|
m_useSSL = true;
|
||||||
|
else
|
||||||
|
m_useSSL = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Remove the cap handler for a capability.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="capsName">name of the capability of the cap
|
||||||
|
/// handler to be removed</param>
|
||||||
|
public void Remove(string capsName)
|
||||||
|
{
|
||||||
|
lock (m_capsHandlers)
|
||||||
|
{
|
||||||
|
if(m_capsHandlers.ContainsKey(capsName))
|
||||||
|
{
|
||||||
|
m_httpListener.RemoveStreamHandler("POST", m_capsHandlers[capsName].Path);
|
||||||
|
m_httpListener.RemoveStreamHandler("PUT", m_capsHandlers[capsName].Path);
|
||||||
|
m_httpListener.RemoveStreamHandler("GET", m_capsHandlers[capsName].Path);
|
||||||
|
m_httpListener.RemoveStreamHandler("DELETE", m_capsHandlers[capsName].Path);
|
||||||
|
m_capsHandlers.Remove(capsName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(m_capsSimpleHandlers.TryRemove(capsName, out ISimpleStreamHandler hdr))
|
||||||
|
{
|
||||||
|
m_httpListener.RemoveSimpleStreamHandler(hdr.Path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddSimpleHandler(string capName, ISimpleStreamHandler handler, bool addToListener = true)
|
||||||
|
{
|
||||||
|
if(ContainsCap(capName))
|
||||||
|
Remove(capName);
|
||||||
|
if(m_capsSimpleHandlers.TryAdd(capName, handler) && addToListener)
|
||||||
|
m_httpListener.AddSimpleStreamHandler(handler);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool ContainsCap(string cap)
|
||||||
|
{
|
||||||
|
lock (m_capsHandlers)
|
||||||
|
if (m_capsHandlers.ContainsKey(cap))
|
||||||
|
return true;
|
||||||
|
return m_capsSimpleHandlers.ContainsKey(cap);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The indexer allows us to treat the CapsHandlers object
|
||||||
|
/// in an intuitive dictionary like way.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// The indexer will throw an exception when you try to
|
||||||
|
/// retrieve a cap handler for a cap that is not contained in
|
||||||
|
/// CapsHandlers.
|
||||||
|
/// </remarks>
|
||||||
|
public IRequestHandler this[string idx]
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
lock (m_capsHandlers)
|
||||||
|
return m_capsHandlers[idx];
|
||||||
|
}
|
||||||
|
|
||||||
|
set
|
||||||
|
{
|
||||||
|
lock (m_capsHandlers)
|
||||||
|
{
|
||||||
|
if (m_capsHandlers.ContainsKey(idx))
|
||||||
|
{
|
||||||
|
m_httpListener.RemoveStreamHandler("POST", m_capsHandlers[idx].Path);
|
||||||
|
m_httpListener.RemoveStreamHandler("PUT", m_capsHandlers[idx].Path);
|
||||||
|
m_httpListener.RemoveStreamHandler("GET", m_capsHandlers[idx].Path);
|
||||||
|
m_httpListener.RemoveStreamHandler("DELETE", m_capsHandlers[idx].Path);
|
||||||
|
m_capsHandlers.Remove(idx);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (null == value) return;
|
||||||
|
|
||||||
|
m_capsHandlers[idx] = value;
|
||||||
|
m_httpListener.AddStreamHandler(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Return the list of cap names for which this CapsHandlers
|
||||||
|
/// object contains cap handlers.
|
||||||
|
/// </summary>
|
||||||
|
public string[] Caps
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
lock (m_capsHandlers)
|
||||||
|
{
|
||||||
|
string[] __keys = new string[m_capsHandlers.Keys.Count + m_capsSimpleHandlers.Keys.Count];
|
||||||
|
m_capsHandlers.Keys.CopyTo(__keys, 0);
|
||||||
|
m_capsSimpleHandlers.Keys.CopyTo(__keys, m_capsHandlers.Keys.Count);
|
||||||
|
return __keys;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Return an LLSD-serializable Hashtable describing the
|
||||||
|
/// capabilities and their handler details.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="excludeSeed">If true, then exclude the seed cap.</param>
|
||||||
|
public Hashtable GetCapsDetails(bool excludeSeed, List<string> requestedCaps)
|
||||||
|
{
|
||||||
|
Hashtable caps = new Hashtable();
|
||||||
|
|
||||||
|
string protocol = m_useSSL ? "https://" : "http://";
|
||||||
|
string baseUrl = protocol + m_httpListenerHostName + ":" + m_httpListenerPort.ToString();
|
||||||
|
|
||||||
|
if (requestedCaps == null)
|
||||||
|
{
|
||||||
|
lock (m_capsHandlers)
|
||||||
|
{
|
||||||
|
foreach (KeyValuePair<string, ISimpleStreamHandler> kvp in m_capsSimpleHandlers)
|
||||||
|
caps[kvp.Key] = baseUrl + kvp.Value.Path;
|
||||||
|
foreach (KeyValuePair<string, IRequestHandler> kvp in m_capsHandlers)
|
||||||
|
caps[kvp.Key] = baseUrl + kvp.Value.Path;
|
||||||
|
}
|
||||||
|
return caps;
|
||||||
|
}
|
||||||
|
|
||||||
|
lock (m_capsHandlers)
|
||||||
|
{
|
||||||
|
for(int i = 0; i < requestedCaps.Count; ++i)
|
||||||
|
{
|
||||||
|
string capsName = requestedCaps[i];
|
||||||
|
if (excludeSeed && "SEED" == capsName)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (m_capsSimpleHandlers.TryGetValue(capsName, out ISimpleStreamHandler shdr))
|
||||||
|
{
|
||||||
|
caps[capsName] = baseUrl + shdr.Path;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (m_capsHandlers.TryGetValue(capsName, out IRequestHandler chdr))
|
||||||
|
{
|
||||||
|
caps[capsName] = baseUrl + chdr.Path;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return caps;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns a copy of the dictionary of all the HTTP cap handlers
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>
|
||||||
|
/// The dictionary copy. The key is the capability name, the value is the HTTP handler.
|
||||||
|
/// </returns>
|
||||||
|
public Dictionary<string, IRequestHandler> GetCapsHandlers()
|
||||||
|
{
|
||||||
|
lock (m_capsHandlers)
|
||||||
|
return new Dictionary<string, IRequestHandler>(m_capsHandlers);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,449 @@
|
||||||
|
/*
|
||||||
|
* 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,85 @@
|
||||||
|
/*
|
||||||
|
* 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 Nini.Config;
|
||||||
|
using OpenSim.Server.Base;
|
||||||
|
using OpenSim.Services.Interfaces;
|
||||||
|
using OpenSim.Framework;
|
||||||
|
using OpenSim.Framework.Servers.HttpServer;
|
||||||
|
using OpenSim.Server.Handlers.Base;
|
||||||
|
using OpenMetaverse;
|
||||||
|
using OpenMetaverse.StructuredData;
|
||||||
|
|
||||||
|
|
||||||
|
namespace OpenSim.Capabilities.Handlers
|
||||||
|
{
|
||||||
|
public class FetchInvDescServerConnector : ServiceConnector
|
||||||
|
{
|
||||||
|
private IInventoryService m_InventoryService;
|
||||||
|
private ILibraryService m_LibraryService;
|
||||||
|
private string m_ConfigName = "CapsService";
|
||||||
|
|
||||||
|
public FetchInvDescServerConnector(IConfigSource config, IHttpServer server, string configName) :
|
||||||
|
base(config, server, configName)
|
||||||
|
{
|
||||||
|
if (configName != String.Empty)
|
||||||
|
m_ConfigName = configName;
|
||||||
|
|
||||||
|
IConfig serverConfig = config.Configs[m_ConfigName];
|
||||||
|
if (serverConfig == null)
|
||||||
|
throw new Exception(String.Format("No section '{0}' in config file", m_ConfigName));
|
||||||
|
|
||||||
|
string invService = serverConfig.GetString("InventoryService", String.Empty);
|
||||||
|
|
||||||
|
if (invService == String.Empty)
|
||||||
|
throw new Exception("No InventoryService in config file");
|
||||||
|
|
||||||
|
Object[] args = new Object[] { config };
|
||||||
|
m_InventoryService =
|
||||||
|
ServerUtils.LoadPlugin<IInventoryService>(invService, args);
|
||||||
|
|
||||||
|
if (m_InventoryService == null)
|
||||||
|
throw new Exception(String.Format("Failed to load InventoryService from {0}; config is {1}", invService, m_ConfigName));
|
||||||
|
|
||||||
|
string libService = serverConfig.GetString("LibraryService", String.Empty);
|
||||||
|
m_LibraryService =
|
||||||
|
ServerUtils.LoadPlugin<ILibraryService>(libService, args);
|
||||||
|
|
||||||
|
ExpiringKey<UUID> m_badRequests = new ExpiringKey<UUID>(30000);
|
||||||
|
|
||||||
|
FetchInvDescHandler webFetchHandler = new FetchInvDescHandler(m_InventoryService, m_LibraryService, null);
|
||||||
|
ISimpleStreamHandler reqHandler
|
||||||
|
= new SimpleStreamHandler("/CAPS/WebFetchInvDesc/", delegate(IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
|
||||||
|
{
|
||||||
|
webFetchHandler.FetchInventoryDescendentsRequest(httpRequest, httpResponse, m_badRequests);
|
||||||
|
});
|
||||||
|
|
||||||
|
server.AddSimpleStreamHandler(reqHandler);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,166 @@
|
||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,71 @@
|
||||||
|
/*
|
||||||
|
* 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 Nini.Config;
|
||||||
|
using OpenSim.Server.Base;
|
||||||
|
using OpenSim.Services.Interfaces;
|
||||||
|
using OpenSim.Framework.Servers.HttpServer;
|
||||||
|
using OpenSim.Server.Handlers.Base;
|
||||||
|
using OpenMetaverse;
|
||||||
|
|
||||||
|
namespace OpenSim.Capabilities.Handlers
|
||||||
|
{
|
||||||
|
public class FetchInventory2ServerConnector : ServiceConnector
|
||||||
|
{
|
||||||
|
private IInventoryService m_InventoryService;
|
||||||
|
private string m_ConfigName = "CapsService";
|
||||||
|
|
||||||
|
public FetchInventory2ServerConnector(IConfigSource config, IHttpServer server, string configName)
|
||||||
|
: base(config, server, configName)
|
||||||
|
{
|
||||||
|
if (configName != String.Empty)
|
||||||
|
m_ConfigName = configName;
|
||||||
|
|
||||||
|
IConfig serverConfig = config.Configs[m_ConfigName];
|
||||||
|
if (serverConfig == null)
|
||||||
|
throw new Exception(String.Format("No section '{0}' in config file", m_ConfigName));
|
||||||
|
|
||||||
|
string invService = serverConfig.GetString("InventoryService", String.Empty);
|
||||||
|
|
||||||
|
if (invService == String.Empty)
|
||||||
|
throw new Exception("No InventoryService in config file");
|
||||||
|
|
||||||
|
Object[] args = new Object[] { config };
|
||||||
|
m_InventoryService = ServerUtils.LoadPlugin<IInventoryService>(invService, args);
|
||||||
|
|
||||||
|
if (m_InventoryService == null)
|
||||||
|
throw new Exception(String.Format("Failed to load InventoryService from {0}; config is {1}", invService, m_ConfigName));
|
||||||
|
|
||||||
|
FetchInventory2Handler fiHandler = new FetchInventory2Handler(m_InventoryService, UUID.Zero);
|
||||||
|
IRequestHandler reqHandler
|
||||||
|
= new RestStreamHandler(
|
||||||
|
"POST", "/CAPS/FetchInventory/", fiHandler.FetchInventoryRequest, "FetchInventory", null);
|
||||||
|
server.AddStreamHandler(reqHandler);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,170 @@
|
||||||
|
/*
|
||||||
|
* 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");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,300 @@
|
||||||
|
/*
|
||||||
|
* 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,190 @@
|
||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,155 @@
|
||||||
|
/*
|
||||||
|
* 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.Reflection;
|
||||||
|
using System.IO;
|
||||||
|
using System.Web;
|
||||||
|
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 GetMeshHandler
|
||||||
|
{
|
||||||
|
private static readonly ILog m_log =
|
||||||
|
LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
|
|
||||||
|
private IAssetService m_assetService;
|
||||||
|
|
||||||
|
public const string DefaultFormat = "vnd.ll.mesh";
|
||||||
|
|
||||||
|
public GetMeshHandler(IAssetService assService)
|
||||||
|
{
|
||||||
|
m_assetService = assService;
|
||||||
|
}
|
||||||
|
public Hashtable Handle(Hashtable request)
|
||||||
|
{
|
||||||
|
return ProcessGetMesh(request, UUID.Zero, null); ;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Hashtable ProcessGetMesh(Hashtable request, UUID AgentId, Caps cap)
|
||||||
|
{
|
||||||
|
Hashtable responsedata = new Hashtable();
|
||||||
|
if (m_assetService == null)
|
||||||
|
{
|
||||||
|
responsedata["int_response_code"] = (int)System.Net.HttpStatusCode.ServiceUnavailable;
|
||||||
|
responsedata["str_response_string"] = "The asset service is unavailable";
|
||||||
|
responsedata["keepalive"] = false;
|
||||||
|
return responsedata;
|
||||||
|
}
|
||||||
|
|
||||||
|
responsedata["int_response_code"] = (int)System.Net.HttpStatusCode.BadRequest;
|
||||||
|
responsedata["content_type"] = "text/plain";
|
||||||
|
responsedata["int_bytes"] = 0;
|
||||||
|
|
||||||
|
string meshStr = string.Empty;
|
||||||
|
if (request.ContainsKey("mesh_id"))
|
||||||
|
meshStr = request["mesh_id"].ToString();
|
||||||
|
|
||||||
|
if (String.IsNullOrEmpty(meshStr))
|
||||||
|
return responsedata;
|
||||||
|
|
||||||
|
UUID meshID = UUID.Zero;
|
||||||
|
if(!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;
|
||||||
|
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.";
|
||||||
|
return responsedata;
|
||||||
|
}
|
||||||
|
|
||||||
|
end = Utils.Clamp(end, 0, mesh.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);
|
||||||
|
Hashtable headers = new Hashtable();
|
||||||
|
headers["Content-Range"] = String.Format("bytes {0}-{1}/{2}", start, end, mesh.Data.Length);
|
||||||
|
responsedata["headers"] = headers;
|
||||||
|
responsedata["int_response_code"] = (int)System.Net.HttpStatusCode.PartialContent;
|
||||||
|
|
||||||
|
byte[] d = new byte[len];
|
||||||
|
Array.Copy(mesh.Data, start, d, 0, len);
|
||||||
|
responsedata["bin_response_data"] = d;
|
||||||
|
responsedata["int_bytes"] = len;
|
||||||
|
return responsedata;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,78 @@
|
||||||
|
/*
|
||||||
|
* 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 Nini.Config;
|
||||||
|
using OpenMetaverse;
|
||||||
|
using OpenSim.Framework.Servers.HttpServer;
|
||||||
|
using OpenSim.Server.Base;
|
||||||
|
using OpenSim.Server.Handlers.Base;
|
||||||
|
using OpenSim.Services.Interfaces;
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace OpenSim.Capabilities.Handlers
|
||||||
|
{
|
||||||
|
public class GetMeshServerConnector : ServiceConnector
|
||||||
|
{
|
||||||
|
private IAssetService m_AssetService;
|
||||||
|
private string m_ConfigName = "CapsService";
|
||||||
|
|
||||||
|
public GetMeshServerConnector(IConfigSource config, IHttpServer server, string configName) :
|
||||||
|
base(config, server, configName)
|
||||||
|
{
|
||||||
|
if (configName != String.Empty)
|
||||||
|
m_ConfigName = configName;
|
||||||
|
|
||||||
|
IConfig serverConfig = config.Configs[m_ConfigName];
|
||||||
|
if (serverConfig == null)
|
||||||
|
throw new Exception(String.Format("No section '{0}' in config file", m_ConfigName));
|
||||||
|
|
||||||
|
string assetService = serverConfig.GetString("AssetService", String.Empty);
|
||||||
|
|
||||||
|
if (assetService == String.Empty)
|
||||||
|
throw new Exception("No AssetService in config file");
|
||||||
|
|
||||||
|
Object[] args = new Object[] { config };
|
||||||
|
m_AssetService =
|
||||||
|
ServerUtils.LoadPlugin<IAssetService>(assetService, args);
|
||||||
|
|
||||||
|
if (m_AssetService == null)
|
||||||
|
throw new Exception(String.Format("Failed to load AssetService from {0}; config is {1}", assetService, m_ConfigName));
|
||||||
|
|
||||||
|
string rurl = serverConfig.GetString("GetMeshRedirectURL");
|
||||||
|
|
||||||
|
GetMeshHandler gmeshHandler = new GetMeshHandler(m_AssetService);
|
||||||
|
IRequestHandler reqHandler
|
||||||
|
= new RestHTTPHandler(
|
||||||
|
"GET",
|
||||||
|
"/" + UUID.Random(),
|
||||||
|
httpMethod => gmeshHandler.ProcessGetMesh(httpMethod, UUID.Zero, null),
|
||||||
|
"GetMesh",
|
||||||
|
null);
|
||||||
|
server.AddStreamHandler(reqHandler); ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,365 @@
|
||||||
|
/*
|
||||||
|
* 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.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 GetTextureHandler
|
||||||
|
{
|
||||||
|
private static readonly ILog m_log =
|
||||||
|
LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
|
|
||||||
|
private IAssetService m_assetService;
|
||||||
|
|
||||||
|
public const string DefaultFormat = "x-j2c";
|
||||||
|
|
||||||
|
public GetTextureHandler(IAssetService assService)
|
||||||
|
{
|
||||||
|
m_assetService = assService;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Hashtable Handle(Hashtable request)
|
||||||
|
{
|
||||||
|
Hashtable ret = new Hashtable();
|
||||||
|
ret["int_response_code"] = (int)System.Net.HttpStatusCode.NotFound;
|
||||||
|
ret["content_type"] = "text/plain";
|
||||||
|
ret["int_bytes"] = 0;
|
||||||
|
string textureStr = (string)request["texture_id"];
|
||||||
|
string format = (string)request["format"];
|
||||||
|
|
||||||
|
//m_log.DebugFormat("[GETTEXTURE]: called {0}", textureStr);
|
||||||
|
|
||||||
|
if (m_assetService == null)
|
||||||
|
{
|
||||||
|
m_log.Error("[GETTEXTURE]: Cannot fetch texture " + textureStr + " without an asset service");
|
||||||
|
}
|
||||||
|
|
||||||
|
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 = new string[1] { DefaultFormat }; // default
|
||||||
|
if (((Hashtable)request["headers"])["Accept"] != null)
|
||||||
|
formats = WebUtil.GetPreferredImageTypes((string)((Hashtable)request["headers"])["Accept"]);
|
||||||
|
if (formats.Length == 0)
|
||||||
|
formats = new string[1] { DefaultFormat }; // default
|
||||||
|
|
||||||
|
}
|
||||||
|
// OK, we have an array with preferred formats, possibly with only one entry
|
||||||
|
bool foundtexture = false;
|
||||||
|
foreach (string f in formats)
|
||||||
|
{
|
||||||
|
foundtexture = FetchTexture(request, ret, textureID, f);
|
||||||
|
if (foundtexture)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (!foundtexture)
|
||||||
|
{
|
||||||
|
ret["int_response_code"] = 404;
|
||||||
|
ret["error_status_text"] = "not found";
|
||||||
|
ret["str_response_string"] = "not found";
|
||||||
|
ret["content_type"] = "text/plain";
|
||||||
|
ret["int_bytes"] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_log.Warn("[GETTEXTURE]: Failed to parse a texture_id from GetTexture request: " + (string)request["uri"]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// m_log.DebugFormat(
|
||||||
|
// "[GETTEXTURE]: For texture {0} sending back response {1}, data length {2}",
|
||||||
|
// textureID, httpResponse.StatusCode, httpResponse.ContentLength);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="httpRequest"></param>
|
||||||
|
/// <param name="httpResponse"></param>
|
||||||
|
/// <param name="textureID"></param>
|
||||||
|
/// <param name="format"></param>
|
||||||
|
/// <returns>False for "caller try another codec"; true otherwise</returns>
|
||||||
|
private bool FetchTexture(Hashtable request, Hashtable response, UUID textureID, string format)
|
||||||
|
{
|
||||||
|
// m_log.DebugFormat("[GETTEXTURE]: {0} with requested format {1}", textureID, format);
|
||||||
|
AssetBase texture;
|
||||||
|
|
||||||
|
string fullID = textureID.ToString();
|
||||||
|
if (format != DefaultFormat)
|
||||||
|
fullID = fullID + "-" + format;
|
||||||
|
|
||||||
|
// try the cache
|
||||||
|
texture = m_assetService.GetCached(fullID);
|
||||||
|
|
||||||
|
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)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (format == DefaultFormat)
|
||||||
|
{
|
||||||
|
WriteTextureData(request, response, texture, format);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
AssetBase newTexture = new AssetBase(texture.ID + "-" + format, texture.Name, (sbyte)AssetType.Texture, texture.Metadata.CreatorID);
|
||||||
|
newTexture.Data = ConvertTextureData(texture, format);
|
||||||
|
if (newTexture.Data.Length == 0)
|
||||||
|
return false; // !!! Caller try another codec, please!
|
||||||
|
|
||||||
|
newTexture.Flags = AssetFlags.Collectable;
|
||||||
|
newTexture.Temporary = true;
|
||||||
|
newTexture.Local = true;
|
||||||
|
m_assetService.Store(newTexture);
|
||||||
|
WriteTextureData(request, response, newTexture, format);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else // it was on the cache
|
||||||
|
{
|
||||||
|
//m_log.DebugFormat("[GETTEXTURE]: texture was in the cache");
|
||||||
|
WriteTextureData(request, response, texture, format);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//response = new Hashtable();
|
||||||
|
|
||||||
|
|
||||||
|
//WriteTextureData(request,response,null,format);
|
||||||
|
// not found
|
||||||
|
//m_log.Warn("[GETTEXTURE]: Texture " + textureID + " not found");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void WriteTextureData(Hashtable request, Hashtable response, AssetBase texture, string format)
|
||||||
|
{
|
||||||
|
Hashtable headers = new Hashtable();
|
||||||
|
response["headers"] = headers;
|
||||||
|
|
||||||
|
string range = String.Empty;
|
||||||
|
|
||||||
|
if (((Hashtable)request["headers"])["range"] != null)
|
||||||
|
range = (string)((Hashtable)request["headers"])["range"];
|
||||||
|
|
||||||
|
else if (((Hashtable)request["headers"])["Range"] != null)
|
||||||
|
range = (string)((Hashtable)request["headers"])["Range"];
|
||||||
|
|
||||||
|
if (!String.IsNullOrEmpty(range)) // JP2's only
|
||||||
|
{
|
||||||
|
// 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 >= 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;
|
||||||
|
// viewers don't seem to handle RequestedRangeNotSatisfiable and keep retrying with same parameters
|
||||||
|
response["int_response_code"] = (int)System.Net.HttpStatusCode.NotFound;
|
||||||
|
}
|
||||||
|
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);
|
||||||
|
|
||||||
|
response["content-type"] = texture.Metadata.ContentType;
|
||||||
|
response["int_response_code"] = (int)System.Net.HttpStatusCode.PartialContent;
|
||||||
|
headers["Content-Range"] = String.Format("bytes {0}-{1}/{2}", start, end, texture.Data.Length);
|
||||||
|
|
||||||
|
byte[] d = new byte[len];
|
||||||
|
Array.Copy(texture.Data, start, d, 0, len);
|
||||||
|
response["bin_response_data"] = d;
|
||||||
|
response["int_bytes"] = len;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_log.Warn("[GETTEXTURE]: Malformed Range header: " + range);
|
||||||
|
response["int_response_code"] = (int)System.Net.HttpStatusCode.BadRequest;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else // JP2's or other formats
|
||||||
|
{
|
||||||
|
// Full content request
|
||||||
|
response["int_response_code"] = (int)System.Net.HttpStatusCode.OK;
|
||||||
|
if (format == DefaultFormat)
|
||||||
|
response["content_type"] = texture.Metadata.ContentType;
|
||||||
|
else
|
||||||
|
response["content_type"] = "image/" + format;
|
||||||
|
|
||||||
|
response["bin_response_data"] = texture.Data;
|
||||||
|
response["int_bytes"] = texture.Data.Length;
|
||||||
|
|
||||||
|
// response.Body.Write(texture.Data, 0, texture.Data.Length);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,394 @@
|
||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,73 @@
|
||||||
|
/*
|
||||||
|
* 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 Nini.Config;
|
||||||
|
using OpenSim.Server.Base;
|
||||||
|
using OpenSim.Services.Interfaces;
|
||||||
|
using OpenSim.Framework.Servers.HttpServer;
|
||||||
|
using OpenSim.Server.Handlers.Base;
|
||||||
|
using OpenMetaverse;
|
||||||
|
|
||||||
|
|
||||||
|
namespace OpenSim.Capabilities.Handlers
|
||||||
|
{
|
||||||
|
public class GetTextureServerConnector : ServiceConnector
|
||||||
|
{
|
||||||
|
private IAssetService m_AssetService;
|
||||||
|
private string m_ConfigName = "CapsService";
|
||||||
|
|
||||||
|
public GetTextureServerConnector(IConfigSource config, IHttpServer server, string configName) :
|
||||||
|
base(config, server, configName)
|
||||||
|
{
|
||||||
|
if (configName != String.Empty)
|
||||||
|
m_ConfigName = configName;
|
||||||
|
|
||||||
|
IConfig serverConfig = config.Configs[m_ConfigName];
|
||||||
|
if (serverConfig == null)
|
||||||
|
throw new Exception(String.Format("No section '{0}' in config file", m_ConfigName));
|
||||||
|
|
||||||
|
string assetService = serverConfig.GetString("AssetService", String.Empty);
|
||||||
|
|
||||||
|
if (assetService == String.Empty)
|
||||||
|
throw new Exception("No AssetService in config file");
|
||||||
|
|
||||||
|
Object[] args = new Object[] { config };
|
||||||
|
m_AssetService =
|
||||||
|
ServerUtils.LoadPlugin<IAssetService>(assetService, args);
|
||||||
|
|
||||||
|
if (m_AssetService == null)
|
||||||
|
throw new Exception(String.Format("Failed to load AssetService from {0}; config is {1}", assetService, m_ConfigName));
|
||||||
|
|
||||||
|
string rurl = serverConfig.GetString("GetTextureRedirectURL");
|
||||||
|
;
|
||||||
|
server.AddStreamHandler(
|
||||||
|
new GetTextureRobustHandler("/CAPS/GetTexture", m_AssetService, "GetTexture", null, rurl));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,64 @@
|
||||||
|
/*
|
||||||
|
* 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.Net;
|
||||||
|
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.Tests.Common;
|
||||||
|
|
||||||
|
/*
|
||||||
|
namespace OpenSim.Capabilities.Handlers.GetTexture.Tests
|
||||||
|
{
|
||||||
|
[TestFixture]
|
||||||
|
public class GetTextureHandlerTests : OpenSimTestCase
|
||||||
|
{
|
||||||
|
[Test]
|
||||||
|
public void TestTextureNotFound()
|
||||||
|
{
|
||||||
|
TestHelpers.InMethod();
|
||||||
|
|
||||||
|
// Overkill - we only really need the asset service, not a whole scene.
|
||||||
|
Scene scene = new SceneHelpers().SetupScene();
|
||||||
|
|
||||||
|
GetTextureHandler handler = new GetTextureHandler("/gettexture", scene.AssetService, "TestGetTexture", null, null);
|
||||||
|
TestOSHttpRequest req = new TestOSHttpRequest();
|
||||||
|
TestOSHttpResponse resp = new TestOSHttpResponse();
|
||||||
|
req.Url = new Uri("http://localhost/?texture_id=00000000-0000-1111-9999-000000000012");
|
||||||
|
handler.Handle(null, null, req, resp);
|
||||||
|
Assert.That(resp.StatusCode, Is.EqualTo((int)System.Net.HttpStatusCode.NotFound));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
|
@ -0,0 +1,33 @@
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
// General Information about an assembly is controlled through the following
|
||||||
|
// set of attributes. Change these attribute values to modify the information
|
||||||
|
// associated with an assembly.
|
||||||
|
[assembly: AssemblyTitle("OpenSim.Capabilities.Handlers")]
|
||||||
|
[assembly: AssemblyDescription("")]
|
||||||
|
[assembly: AssemblyConfiguration("")]
|
||||||
|
[assembly: AssemblyCompany("http://opensimulator.org")]
|
||||||
|
[assembly: AssemblyProduct("OpenSim")]
|
||||||
|
[assembly: AssemblyCopyright("OpenSimulator developers")]
|
||||||
|
[assembly: AssemblyTrademark("")]
|
||||||
|
[assembly: AssemblyCulture("")]
|
||||||
|
|
||||||
|
// Setting ComVisible to false makes the types in this assembly not visible
|
||||||
|
// to COM components. If you need to access a type in this assembly from
|
||||||
|
// COM, set the ComVisible attribute to true on that type.
|
||||||
|
[assembly: ComVisible(false)]
|
||||||
|
|
||||||
|
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||||
|
[assembly: Guid("32350823-e1df-45e3-b7fa-0a58b4372433")]
|
||||||
|
|
||||||
|
// Version information for an assembly consists of the following four values:
|
||||||
|
//
|
||||||
|
// Major Version
|
||||||
|
// Minor Version
|
||||||
|
// Build Number
|
||||||
|
// Revision
|
||||||
|
//
|
||||||
|
[assembly: AssemblyVersion(OpenSim.VersionInfo.AssemblyVersionNumber)]
|
||||||
|
|
|
@ -1,30 +1,29 @@
|
||||||
/*
|
/*
|
||||||
* 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.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
* modification, are permitted provided that the following conditions are met:
|
* modification, are permitted provided that the following conditions are met:
|
||||||
* * Redistributions of source code must retain the above copyright
|
* * Redistributions of source code must retain the above copyright
|
||||||
* notice, this list of conditions and the following disclaimer.
|
* notice, this list of conditions and the following disclaimer.
|
||||||
* * Redistributions in binary form must reproduce the above copyright
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
* documentation and/or other materials provided with the distribution.
|
* documentation and/or other materials provided with the distribution.
|
||||||
* * Neither the name of the OpenSim Project nor the
|
* * Neither the name of the OpenSimulator Project nor the
|
||||||
* names of its contributors may be used to endorse or promote products
|
* names of its contributors may be used to endorse or promote products
|
||||||
* derived from this software without specific prior written permission.
|
* derived from this software without specific prior written permission.
|
||||||
*
|
*
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
||||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
* 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
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*
|
*/
|
||||||
*/
|
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
|
@ -33,17 +32,17 @@ using System.IO;
|
||||||
using System.Security.Cryptography;
|
using System.Security.Cryptography;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Xml;
|
using System.Xml;
|
||||||
using libsecondlife;
|
using OpenMetaverse;
|
||||||
|
|
||||||
namespace OpenSim.Region.Capabilities
|
namespace OpenSim.Framework.Capabilities
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Borrowed from (a older version of ) libsl for now, as their new llsd code doesn't work we our decoding code.
|
/// Borrowed from (a older version of) libsl for now, as their new llsd code doesn't work we our decoding code.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static class LLSD
|
public static class LLSD
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
///
|
///
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class LLSDParseException : Exception
|
public class LLSDParseException : Exception
|
||||||
{
|
{
|
||||||
|
@ -53,7 +52,7 @@ namespace OpenSim.Region.Capabilities
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
///
|
///
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class LLSDSerializeException : Exception
|
public class LLSDSerializeException : Exception
|
||||||
{
|
{
|
||||||
|
@ -63,61 +62,66 @@ namespace OpenSim.Region.Capabilities
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
///
|
///
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="b"></param>
|
/// <param name="b"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public static object LLSDDeserialize(byte[] b)
|
public static object LLSDDeserialize(byte[] b)
|
||||||
{
|
{
|
||||||
return LLSDDeserialize(new MemoryStream(b, false));
|
using (MemoryStream ms = new MemoryStream(b, false))
|
||||||
|
{
|
||||||
|
return LLSDDeserialize(ms);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
///
|
///
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="st"></param>
|
/// <param name="st"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public static object LLSDDeserialize(Stream st)
|
public static object LLSDDeserialize(Stream st)
|
||||||
{
|
{
|
||||||
XmlTextReader reader = new XmlTextReader(st);
|
using (XmlTextReader reader = new XmlTextReader(st))
|
||||||
reader.Read();
|
{
|
||||||
SkipWS(reader);
|
reader.Read();
|
||||||
|
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>
|
||||||
///
|
///
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="obj"></param>
|
/// <param name="obj"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public static byte[] LLSDSerialize(object obj)
|
public static byte[] LLSDSerialize(object obj)
|
||||||
{
|
{
|
||||||
StringWriter sw = new StringWriter();
|
using(StringWriter sw = new StringWriter())
|
||||||
XmlTextWriter writer = new XmlTextWriter(sw);
|
using(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();
|
||||||
writer.Close();
|
return Util.UTF8.GetBytes(sw.ToString());
|
||||||
|
}
|
||||||
return Encoding.UTF8.GetBytes(sw.ToString());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
///
|
///
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="writer"></param>
|
/// <param name="writer"></param>
|
||||||
/// <param name="obj"></param>
|
/// <param name="obj"></param>
|
||||||
|
@ -159,9 +163,9 @@ namespace OpenSim.Region.Capabilities
|
||||||
{
|
{
|
||||||
throw new Exception("ulong in LLSD is currently not implemented, fix me!");
|
throw new Exception("ulong in LLSD is currently not implemented, fix me!");
|
||||||
}
|
}
|
||||||
else if (obj is LLUUID)
|
else if (obj is UUID)
|
||||||
{
|
{
|
||||||
LLUUID u = (LLUUID) obj;
|
UUID u = (UUID) obj;
|
||||||
writer.WriteStartElement(String.Empty, "uuid", String.Empty);
|
writer.WriteStartElement(String.Empty, "uuid", String.Empty);
|
||||||
writer.WriteString(u.ToString());
|
writer.WriteString(u.ToString());
|
||||||
writer.WriteEndElement();
|
writer.WriteEndElement();
|
||||||
|
@ -218,7 +222,7 @@ namespace OpenSim.Region.Capabilities
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
///
|
///
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="reader"></param>
|
/// <param name="reader"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
|
@ -295,11 +299,11 @@ namespace OpenSim.Region.Capabilities
|
||||||
if (reader.IsEmptyElement)
|
if (reader.IsEmptyElement)
|
||||||
{
|
{
|
||||||
reader.Read();
|
reader.Read();
|
||||||
return LLUUID.Zero;
|
return UUID.Zero;
|
||||||
}
|
}
|
||||||
|
|
||||||
reader.Read();
|
reader.Read();
|
||||||
ret = new LLUUID(reader.ReadString().Trim());
|
ret = new UUID(reader.ReadString().Trim());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case "string":
|
case "string":
|
||||||
|
@ -330,7 +334,7 @@ namespace OpenSim.Region.Capabilities
|
||||||
|
|
||||||
reader.Read();
|
reader.Read();
|
||||||
FromBase64Transform b64 = new FromBase64Transform(FromBase64TransformMode.IgnoreWhiteSpaces);
|
FromBase64Transform b64 = new FromBase64Transform(FromBase64TransformMode.IgnoreWhiteSpaces);
|
||||||
byte[] inp = Encoding.ASCII.GetBytes(reader.ReadString());
|
byte[] inp = Util.UTF8.GetBytes(reader.ReadString());
|
||||||
ret = b64.TransformFinalBlock(inp, 0, inp.Length);
|
ret = b64.TransformFinalBlock(inp, 0, inp.Length);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -361,7 +365,7 @@ namespace OpenSim.Region.Capabilities
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
///
|
///
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="reader"></param>
|
/// <param name="reader"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
|
@ -406,7 +410,7 @@ namespace OpenSim.Region.Capabilities
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
///
|
///
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="reader"></param>
|
/// <param name="reader"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
|
@ -442,7 +446,7 @@ namespace OpenSim.Region.Capabilities
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
///
|
///
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="count"></param>
|
/// <param name="count"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
|
@ -454,7 +458,7 @@ namespace OpenSim.Region.Capabilities
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
///
|
///
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="obj"></param>
|
/// <param name="obj"></param>
|
||||||
/// <param name="indent"></param>
|
/// <param name="indent"></param>
|
||||||
|
@ -477,9 +481,9 @@ namespace OpenSim.Region.Capabilities
|
||||||
{
|
{
|
||||||
return GetSpaces(indent) + "- float " + obj.ToString() + "\n";
|
return GetSpaces(indent) + "- float " + obj.ToString() + "\n";
|
||||||
}
|
}
|
||||||
else if (obj is LLUUID)
|
else if (obj is UUID)
|
||||||
{
|
{
|
||||||
return GetSpaces(indent) + "- uuid " + ((LLUUID) obj).ToString() + Environment.NewLine;
|
return GetSpaces(indent) + "- uuid " + ((UUID) obj).ToString() + Environment.NewLine;
|
||||||
}
|
}
|
||||||
else if (obj is Hashtable)
|
else if (obj is Hashtable)
|
||||||
{
|
{
|
||||||
|
@ -510,7 +514,7 @@ namespace OpenSim.Region.Capabilities
|
||||||
}
|
}
|
||||||
else if (obj is byte[])
|
else if (obj is byte[])
|
||||||
{
|
{
|
||||||
return GetSpaces(indent) + "- binary\n" + Helpers.FieldToHexString((byte[]) obj, GetSpaces(indent)) +
|
return GetSpaces(indent) + "- binary\n" + Utils.BytesToHexString((byte[]) obj, GetSpaces(indent)) +
|
||||||
Environment.NewLine;
|
Environment.NewLine;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -562,21 +566,21 @@ namespace OpenSim.Region.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,
|
||||||
Helpers.EnUsCulture.NumberFormat, out value))
|
Culture.NumberFormatInfo, 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");
|
||||||
}
|
}
|
||||||
case 'u':
|
case 'u':
|
||||||
{
|
{
|
||||||
if (llsd.Length < 17) throw new LLSDParseException("LLUUID value type with no value");
|
if (llsd.Length < 17) throw new LLSDParseException("UUID value type with no value");
|
||||||
LLUUID value;
|
UUID value;
|
||||||
endPos = FindEnd(llsd, 1);
|
endPos = FindEnd(llsd, 1);
|
||||||
|
|
||||||
if (LLUUID.TryParse(llsd.Substring(1, endPos - 1), out value))
|
if (UUID.TryParse(llsd.Substring(1, endPos - 1), out value))
|
||||||
return value;
|
return value;
|
||||||
else
|
else
|
||||||
throw new LLSDParseException("Failed to parse LLUUID value type");
|
throw new LLSDParseException("Failed to parse UUID value type");
|
||||||
}
|
}
|
||||||
case 'b':
|
case 'b':
|
||||||
//byte[] value = new byte[llsd.Length - 1];
|
//byte[] value = new byte[llsd.Length - 1];
|
||||||
|
@ -662,7 +666,7 @@ namespace OpenSim.Region.Capabilities
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
///
|
///
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="reader"></param>
|
/// <param name="reader"></param>
|
||||||
private static void SkipWS(XmlTextReader reader)
|
private static void SkipWS(XmlTextReader reader)
|
||||||
|
@ -677,4 +681,4 @@ namespace OpenSim.Region.Capabilities
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -0,0 +1,41 @@
|
||||||
|
/*
|
||||||
|
* 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
|
||||||
|
{
|
||||||
|
[LLSDType("ARRAY")]
|
||||||
|
public class OSDArray
|
||||||
|
{
|
||||||
|
public ArrayList Array = new ArrayList();
|
||||||
|
|
||||||
|
public OSDArray()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,52 @@
|
||||||
|
/*
|
||||||
|
* 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 OpenMetaverse;
|
||||||
|
|
||||||
|
namespace OpenSim.Framework.Capabilities
|
||||||
|
{
|
||||||
|
|
||||||
|
[LLSDType("MAP")]
|
||||||
|
public class LLSDAssetUploadComplete
|
||||||
|
{
|
||||||
|
public string new_asset = String.Empty;
|
||||||
|
public UUID new_inventory_item = UUID.Zero;
|
||||||
|
// public UUID new_texture_folder_id = UUID.Zero;
|
||||||
|
public string state = String.Empty;
|
||||||
|
public LLSDAssetUploadError error = null;
|
||||||
|
//public bool success = false;
|
||||||
|
public int new_next_owner_mask = 0;
|
||||||
|
public int new_group_mask = 0;
|
||||||
|
public int new_everyone_mask = 0;
|
||||||
|
public int inventory_item_flags = 0;
|
||||||
|
|
||||||
|
public LLSDAssetUploadComplete()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,59 @@
|
||||||
|
/*
|
||||||
|
* 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 OpenMetaverse;
|
||||||
|
|
||||||
|
namespace OpenSim.Framework.Capabilities
|
||||||
|
{
|
||||||
|
[OSDMap]
|
||||||
|
public class LLSDAssetResource
|
||||||
|
{
|
||||||
|
public OSDArray instance_list = new OSDArray();
|
||||||
|
public OSDArray texture_list = new OSDArray();
|
||||||
|
public OSDArray mesh_list = new OSDArray();
|
||||||
|
public string metric = String.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
[OSDMap]
|
||||||
|
public class LLSDAssetUploadRequest
|
||||||
|
{
|
||||||
|
public string asset_type = String.Empty;
|
||||||
|
public string description = String.Empty;
|
||||||
|
public UUID folder_id = UUID.Zero;
|
||||||
|
public UUID texture_folder_id = UUID.Zero;
|
||||||
|
public int next_owner_mask = 0;
|
||||||
|
public int group_mask = 0;
|
||||||
|
public int everyone_mask = 0;
|
||||||
|
public string inventory_type = String.Empty;
|
||||||
|
public string name = String.Empty;
|
||||||
|
public LLSDAssetResource asset_resources = new LLSDAssetResource();
|
||||||
|
public LLSDAssetUploadRequest()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,87 @@
|
||||||
|
/*
|
||||||
|
* 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 OpenMetaverse;
|
||||||
|
|
||||||
|
namespace OpenSim.Framework.Capabilities
|
||||||
|
{
|
||||||
|
[OSDMap]
|
||||||
|
public class LLSDAssetUploadError
|
||||||
|
{
|
||||||
|
public string message = String.Empty;
|
||||||
|
public UUID identifier = UUID.Zero;
|
||||||
|
}
|
||||||
|
|
||||||
|
[OSDMap]
|
||||||
|
public class LLSDAssetUploadResponsePricebrkDown
|
||||||
|
{
|
||||||
|
public int mesh_streaming;
|
||||||
|
public int mesh_physics;
|
||||||
|
public int mesh_instance;
|
||||||
|
public int texture;
|
||||||
|
public int model;
|
||||||
|
}
|
||||||
|
|
||||||
|
[OSDMap]
|
||||||
|
public class LLSDAssetUploadResponseData
|
||||||
|
{
|
||||||
|
public double resource_cost;
|
||||||
|
public double model_streaming_cost;
|
||||||
|
public double simulation_cost;
|
||||||
|
public double physics_cost;
|
||||||
|
public LLSDAssetUploadResponsePricebrkDown upload_price_breakdown = new LLSDAssetUploadResponsePricebrkDown();
|
||||||
|
}
|
||||||
|
|
||||||
|
[OSDMap]
|
||||||
|
public class LLSDAssetUploadResponse
|
||||||
|
{
|
||||||
|
public string uploader = String.Empty;
|
||||||
|
public string state = String.Empty;
|
||||||
|
public int upload_price = 0;
|
||||||
|
public LLSDAssetUploadResponseData data = null;
|
||||||
|
public LLSDAssetUploadError error = null;
|
||||||
|
public LLSDAssetUploadResponse()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
[OSDMap]
|
||||||
|
public class LLSDNewFileAngentInventoryVariablePriceReplyResponse
|
||||||
|
{
|
||||||
|
public int resource_cost;
|
||||||
|
public string state;
|
||||||
|
public int upload_price;
|
||||||
|
public string rsvp;
|
||||||
|
|
||||||
|
public LLSDNewFileAngentInventoryVariablePriceReplyResponse()
|
||||||
|
{
|
||||||
|
state = "confirm_upload";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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 OpenMetaverse;
|
||||||
|
|
||||||
|
namespace OpenSim.Framework.Capabilities
|
||||||
|
{
|
||||||
|
[OSDMap]
|
||||||
|
public class LLSDAvatarPicker
|
||||||
|
{
|
||||||
|
public string next_page_url;
|
||||||
|
// an array of LLSDPerson
|
||||||
|
public OSDArray agents = new OSDArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
[OSDMap]
|
||||||
|
public class LLSDPerson
|
||||||
|
{
|
||||||
|
public string username;
|
||||||
|
public string display_name;
|
||||||
|
//'display_name_next_update':d"1970-01-01T00:00:00Z"
|
||||||
|
public string legacy_first_name;
|
||||||
|
public string legacy_last_name;
|
||||||
|
public UUID id;
|
||||||
|
public bool is_display_name_default;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,40 @@
|
||||||
|
/*
|
||||||
|
* 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
|
||||||
|
{
|
||||||
|
[LLSDType("MAP")]
|
||||||
|
public class LLSDCapEvent
|
||||||
|
{
|
||||||
|
public int id = 0;
|
||||||
|
public OSDArray events = new OSDArray();
|
||||||
|
|
||||||
|
public LLSDCapEvent()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,37 @@
|
||||||
|
/*
|
||||||
|
* 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
|
||||||
|
{
|
||||||
|
[LLSDType("MAP")]
|
||||||
|
public class LLSDEmpty
|
||||||
|
{
|
||||||
|
public LLSDEmpty()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,204 @@
|
||||||
|
/*
|
||||||
|
* 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.IO;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Xml;
|
||||||
|
using OpenMetaverse;
|
||||||
|
|
||||||
|
namespace OpenSim.Framework.Capabilities
|
||||||
|
{
|
||||||
|
public class LLSDHelpers
|
||||||
|
{
|
||||||
|
// private static readonly log4net.ILog m_log
|
||||||
|
// = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
|
|
||||||
|
public static string SerialiseLLSDReply(object obj)
|
||||||
|
{
|
||||||
|
using(StringWriter sw = new StringWriter())
|
||||||
|
using(XmlTextWriter writer = new XmlTextWriter(sw))
|
||||||
|
{
|
||||||
|
writer.Formatting = Formatting.None;
|
||||||
|
writer.WriteStartElement(String.Empty, "llsd", String.Empty);
|
||||||
|
SerializeOSDType(writer, obj);
|
||||||
|
writer.WriteEndElement();
|
||||||
|
writer.Flush();
|
||||||
|
//m_log.DebugFormat("[LLSD Helpers]: Generated serialized LLSD reply {0}", sw.ToString());
|
||||||
|
|
||||||
|
return sw.ToString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string SerialiseLLSDReplyNoHeader(object obj)
|
||||||
|
{
|
||||||
|
using(StringWriter sw = new StringWriter())
|
||||||
|
using(XmlTextWriter writer = new XmlTextWriter(sw))
|
||||||
|
{
|
||||||
|
writer.Formatting = Formatting.None;
|
||||||
|
SerializeOSDType(writer, obj);
|
||||||
|
writer.Flush();
|
||||||
|
//m_log.DebugFormat("[LLSD Helpers]: Generated serialized LLSD reply {0}", sw.ToString());
|
||||||
|
|
||||||
|
return sw.ToString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void SerializeOSDType(XmlTextWriter writer, object obj)
|
||||||
|
{
|
||||||
|
Type myType = obj.GetType();
|
||||||
|
LLSDType[] llsdattributes = (LLSDType[]) myType.GetCustomAttributes(typeof (LLSDType), false);
|
||||||
|
if (llsdattributes.Length > 0)
|
||||||
|
{
|
||||||
|
switch (llsdattributes[0].ObjectType)
|
||||||
|
{
|
||||||
|
case "MAP":
|
||||||
|
writer.WriteStartElement(String.Empty, "map", String.Empty);
|
||||||
|
FieldInfo[] fields = myType.GetFields();
|
||||||
|
for (int i = 0; i < fields.Length; i++)
|
||||||
|
{
|
||||||
|
if (fields[i] != null && fields[i].GetValue(obj) != null)
|
||||||
|
{
|
||||||
|
object fieldValue = fields[i].GetValue(obj);
|
||||||
|
LLSDType[] fieldAttributes =
|
||||||
|
(LLSDType[]) fieldValue.GetType().GetCustomAttributes(typeof (LLSDType), false);
|
||||||
|
if (fieldAttributes.Length > 0)
|
||||||
|
{
|
||||||
|
writer.WriteStartElement(String.Empty, "key", String.Empty);
|
||||||
|
string fieldName = fields[i].Name;
|
||||||
|
fieldName = fieldName.Replace("___", "-");
|
||||||
|
writer.WriteString(fieldName);
|
||||||
|
writer.WriteEndElement();
|
||||||
|
SerializeOSDType(writer, fieldValue);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
writer.WriteStartElement(String.Empty, "key", String.Empty);
|
||||||
|
string fieldName = fields[i].Name;
|
||||||
|
fieldName = fieldName.Replace("___", "-");
|
||||||
|
writer.WriteString(fieldName);
|
||||||
|
writer.WriteEndElement();
|
||||||
|
LLSD.LLSDWriteOne(writer, fieldValue);
|
||||||
|
// OpenMetaverse.StructuredData.LLSDParser.SerializeXmlElement(
|
||||||
|
// writer, OpenMetaverse.StructuredData.OSD.FromObject(fieldValue));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// TODO from ADAM: There is a nullref being caused by fields[i] being null
|
||||||
|
// on some computers. Unsure what is causing this, but would appreciate
|
||||||
|
// if sdague could take a look at this.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
writer.WriteEndElement();
|
||||||
|
break;
|
||||||
|
case "ARRAY":
|
||||||
|
// OSDArray arrayObject = obj as OSDArray;
|
||||||
|
// ArrayList a = arrayObject.Array;
|
||||||
|
ArrayList a = (ArrayList) obj.GetType().GetField("Array").GetValue(obj);
|
||||||
|
if (a != null)
|
||||||
|
{
|
||||||
|
writer.WriteStartElement(String.Empty, "array", String.Empty);
|
||||||
|
foreach (object item in a)
|
||||||
|
{
|
||||||
|
SerializeOSDType(writer, item);
|
||||||
|
}
|
||||||
|
writer.WriteEndElement();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LLSD.LLSDWriteOne(writer, obj);
|
||||||
|
//OpenMetaverse.StructuredData.LLSDParser.SerializeXmlElement(
|
||||||
|
// writer, OpenMetaverse.StructuredData.OSD.FromObject(obj));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static object DeserialiseOSDMap(Hashtable llsd, object obj)
|
||||||
|
{
|
||||||
|
Type myType = obj.GetType();
|
||||||
|
LLSDType[] llsdattributes = (LLSDType[]) myType.GetCustomAttributes(typeof (LLSDType), false);
|
||||||
|
if (llsdattributes.Length > 0)
|
||||||
|
{
|
||||||
|
switch (llsdattributes[0].ObjectType)
|
||||||
|
{
|
||||||
|
case "MAP":
|
||||||
|
IDictionaryEnumerator enumerator = llsd.GetEnumerator();
|
||||||
|
while (enumerator.MoveNext())
|
||||||
|
{
|
||||||
|
string keyName = (string)enumerator.Key;
|
||||||
|
keyName = keyName.Replace("-","_");
|
||||||
|
FieldInfo field = myType.GetField(keyName);
|
||||||
|
if (field != null)
|
||||||
|
{
|
||||||
|
// if (enumerator.Value is OpenMetaverse.StructuredData.OSDMap)
|
||||||
|
if (enumerator.Value is Hashtable)
|
||||||
|
{
|
||||||
|
object fieldValue = field.GetValue(obj);
|
||||||
|
DeserialiseOSDMap((Hashtable) enumerator.Value, fieldValue);
|
||||||
|
// DeserialiseOSDMap((OpenMetaverse.StructuredData.OSDMap) enumerator.Value, fieldValue);
|
||||||
|
}
|
||||||
|
else if (enumerator.Value is ArrayList)
|
||||||
|
{
|
||||||
|
object fieldValue = field.GetValue(obj);
|
||||||
|
fieldValue.GetType().GetField("Array").SetValue(fieldValue, enumerator.Value);
|
||||||
|
//TODO
|
||||||
|
// the LLSD map/array types in the array need to be deserialised
|
||||||
|
// but first we need to know the right class to deserialise them into.
|
||||||
|
}
|
||||||
|
else if(enumerator.Value is Boolean && field.FieldType == typeof(int) )
|
||||||
|
{
|
||||||
|
int i = (bool)enumerator.Value ? 1 : 0;
|
||||||
|
field.SetValue(obj, i);
|
||||||
|
}
|
||||||
|
else if(field.FieldType == typeof(bool) && enumerator.Value is int)
|
||||||
|
{
|
||||||
|
bool b = (int)enumerator.Value != 0;
|
||||||
|
field.SetValue(obj, b);
|
||||||
|
}
|
||||||
|
else if(field.FieldType == typeof(UUID) && enumerator.Value is string)
|
||||||
|
{
|
||||||
|
UUID u;
|
||||||
|
UUID.TryParse((string)enumerator.Value, out u);
|
||||||
|
field.SetValue(obj, u);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
field.SetValue(obj, enumerator.Value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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
|
||||||
|
{
|
||||||
|
[OSDMap]
|
||||||
|
public class LLSDInventoryFolder
|
||||||
|
{
|
||||||
|
public UUID folder_id;
|
||||||
|
public UUID parent_id;
|
||||||
|
public string name;
|
||||||
|
public int type;
|
||||||
|
public int preferred_type;
|
||||||
|
public int version;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,105 @@
|
||||||
|
/*
|
||||||
|
* 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 LLSDInventoryItem
|
||||||
|
{
|
||||||
|
public UUID parent_id;
|
||||||
|
|
||||||
|
public UUID asset_id;
|
||||||
|
public UUID item_id;
|
||||||
|
public LLSDPermissions permissions;
|
||||||
|
public int type;
|
||||||
|
public int inv_type;
|
||||||
|
public int flags;
|
||||||
|
|
||||||
|
public LLSDSaleInfo sale_info;
|
||||||
|
public string name;
|
||||||
|
public string desc;
|
||||||
|
public int created_at;
|
||||||
|
}
|
||||||
|
|
||||||
|
[OSDMap]
|
||||||
|
public class LLSDPermissions
|
||||||
|
{
|
||||||
|
public UUID creator_id;
|
||||||
|
public UUID owner_id;
|
||||||
|
public UUID group_id;
|
||||||
|
public int base_mask;
|
||||||
|
public int owner_mask;
|
||||||
|
public int group_mask;
|
||||||
|
public int everyone_mask;
|
||||||
|
public int next_owner_mask;
|
||||||
|
public bool is_owner_group;
|
||||||
|
}
|
||||||
|
|
||||||
|
[OSDMap]
|
||||||
|
public class LLSDSaleInfo
|
||||||
|
{
|
||||||
|
public int sale_price;
|
||||||
|
public int sale_type;
|
||||||
|
}
|
||||||
|
|
||||||
|
[OSDMap]
|
||||||
|
public class LLSDInventoryDescendents
|
||||||
|
{
|
||||||
|
public OSDArray folders = new OSDArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
[OSDMap]
|
||||||
|
public class LLSDFetchInventoryDescendents
|
||||||
|
{
|
||||||
|
public UUID folder_id;
|
||||||
|
public UUID owner_id;
|
||||||
|
public int sort_order;
|
||||||
|
public bool fetch_folders;
|
||||||
|
public bool fetch_items;
|
||||||
|
}
|
||||||
|
|
||||||
|
[OSDMap]
|
||||||
|
public class LLSDInventoryFolderContents
|
||||||
|
{
|
||||||
|
public UUID agent_id;
|
||||||
|
public int descendents;
|
||||||
|
public UUID folder_id;
|
||||||
|
public OSDArray categories = new OSDArray();
|
||||||
|
public OSDArray items = new OSDArray();
|
||||||
|
public UUID owner_id;
|
||||||
|
public int version;
|
||||||
|
}
|
||||||
|
|
||||||
|
[OSDMap]
|
||||||
|
public class LLSDFetchInventory
|
||||||
|
{
|
||||||
|
public UUID agent_id;
|
||||||
|
public OSDArray items = new OSDArray();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,45 @@
|
||||||
|
/*
|
||||||
|
* 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 OSDMapLayer
|
||||||
|
{
|
||||||
|
public int Left = 0;
|
||||||
|
public int Right = 0;
|
||||||
|
public int Top = 0;
|
||||||
|
public int Bottom = 0;
|
||||||
|
public UUID ImageID = UUID.Zero;
|
||||||
|
|
||||||
|
public OSDMapLayer()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,40 @@
|
||||||
|
/*
|
||||||
|
* 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
|
||||||
|
{
|
||||||
|
[LLSDType("MAP")]
|
||||||
|
public class LLSDMapLayerResponse
|
||||||
|
{
|
||||||
|
public LLSDMapRequest AgentData = new LLSDMapRequest();
|
||||||
|
public OSDArray LayerData = new OSDArray();
|
||||||
|
|
||||||
|
public LLSDMapLayerResponse()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,39 @@
|
||||||
|
/*
|
||||||
|
* 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
|
||||||
|
{
|
||||||
|
[LLSDType("MAP")]
|
||||||
|
public class LLSDMapRequest
|
||||||
|
{
|
||||||
|
public int Flags = 0;
|
||||||
|
|
||||||
|
public LLSDMapRequest()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
/*
|
||||||
|
* 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
|
||||||
|
{
|
||||||
|
public delegate TResponse LLSDMethod<TRequest, TResponse>(TRequest request);
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
/*
|
||||||
|
* 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
|
||||||
|
{
|
||||||
|
public delegate TResponse LLSDMethodString<TRequest, TResponse>(TRequest request, string path);
|
||||||
|
}
|
|
@ -0,0 +1,75 @@
|
||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
using System.IO;
|
||||||
|
using System.Text;
|
||||||
|
using OpenSim.Framework.Servers;
|
||||||
|
using OpenSim.Framework.Servers.HttpServer;
|
||||||
|
|
||||||
|
namespace OpenSim.Framework.Capabilities
|
||||||
|
{
|
||||||
|
public class LLSDStreamhandler<TRequest, TResponse> : BaseStreamHandler
|
||||||
|
where TRequest : new()
|
||||||
|
{
|
||||||
|
private LLSDMethod<TRequest, TResponse> m_method;
|
||||||
|
|
||||||
|
public LLSDStreamhandler(string httpMethod, string path, LLSDMethod<TRequest, TResponse> method)
|
||||||
|
: this(httpMethod, path, method, null, null) {}
|
||||||
|
|
||||||
|
public LLSDStreamhandler(
|
||||||
|
string httpMethod, string path, LLSDMethod<TRequest, TResponse> method, string name, string description)
|
||||||
|
: base(httpMethod, path, name, description)
|
||||||
|
{
|
||||||
|
m_method = method;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override byte[] ProcessRequest(string path, Stream request,
|
||||||
|
IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
|
||||||
|
{
|
||||||
|
//Encoding encoding = Util.UTF8;
|
||||||
|
//StreamReader streamReader = new StreamReader(request, false);
|
||||||
|
|
||||||
|
//string requestBody = streamReader.ReadToEnd();
|
||||||
|
//streamReader.Close();
|
||||||
|
|
||||||
|
// OpenMetaverse.StructuredData.OSDMap hash = (OpenMetaverse.StructuredData.OSDMap)
|
||||||
|
// OpenMetaverse.StructuredData.LLSDParser.DeserializeXml(new XmlTextReader(request));
|
||||||
|
|
||||||
|
Hashtable hash = (Hashtable) LLSD.LLSDDeserialize(request);
|
||||||
|
if(hash == null)
|
||||||
|
return new byte[0];
|
||||||
|
|
||||||
|
TRequest llsdRequest = new TRequest();
|
||||||
|
LLSDHelpers.DeserialiseOSDMap(hash, llsdRequest);
|
||||||
|
|
||||||
|
TResponse response = m_method(llsdRequest);
|
||||||
|
|
||||||
|
return Util.UTF8NoBomEncoding.GetBytes(LLSDHelpers.SerialiseLLSDReply(response));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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 LLSDTaskInventoryUploadComplete
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The task inventory item that was updated
|
||||||
|
/// </summary>
|
||||||
|
public UUID item_id;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The task that was updated
|
||||||
|
/// </summary>
|
||||||
|
public UUID task_id;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// State of the upload. So far have only even seen this set to "complete"
|
||||||
|
/// </summary>
|
||||||
|
public string state;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,54 @@
|
||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
using System;
|
||||||
|
using System.Collections;
|
||||||
|
|
||||||
|
namespace OpenSim.Framework.Capabilities
|
||||||
|
{
|
||||||
|
[OSDMap]
|
||||||
|
public class LLSDTaskScriptUploadComplete
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The task inventory item that was updated
|
||||||
|
/// </summary>
|
||||||
|
public UUID new_asset;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Was it compiled?
|
||||||
|
/// </summary>
|
||||||
|
public bool compiled;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// State of the upload. So far have only even seen this set to "complete"
|
||||||
|
/// </summary>
|
||||||
|
public string state;
|
||||||
|
|
||||||
|
public OSDArray errors;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,40 @@
|
||||||
|
/*
|
||||||
|
* 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
|
||||||
|
{
|
||||||
|
[LLSDType("MAP")]
|
||||||
|
public class LLSDTest
|
||||||
|
{
|
||||||
|
public int Test1 = 20;
|
||||||
|
public int Test2 = 10;
|
||||||
|
|
||||||
|
public LLSDTest()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,55 @@
|
||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
namespace OpenSim.Framework.Capabilities
|
||||||
|
{
|
||||||
|
[AttributeUsage(AttributeTargets.Class)]
|
||||||
|
public class LLSDType : Attribute
|
||||||
|
{
|
||||||
|
protected string myType;
|
||||||
|
|
||||||
|
public LLSDType(string type)
|
||||||
|
{
|
||||||
|
myType = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string ObjectType
|
||||||
|
{
|
||||||
|
get { return myType; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[AttributeUsage(AttributeTargets.Class)]
|
||||||
|
public class OSDMap : LLSDType
|
||||||
|
{
|
||||||
|
public OSDMap() : base("MAP")
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,33 @@
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
// General Information about an assembly is controlled through the following
|
||||||
|
// set of attributes. Change these attribute values to modify the information
|
||||||
|
// associated with an assembly.
|
||||||
|
[assembly: AssemblyTitle("OpenSim.Capabilities")]
|
||||||
|
[assembly: AssemblyDescription("")]
|
||||||
|
[assembly: AssemblyConfiguration("")]
|
||||||
|
[assembly: AssemblyCompany("http://opensimulator.org")]
|
||||||
|
[assembly: AssemblyProduct("OpenSim")]
|
||||||
|
[assembly: AssemblyCopyright("OpenSimulator developers")]
|
||||||
|
[assembly: AssemblyTrademark("")]
|
||||||
|
[assembly: AssemblyCulture("")]
|
||||||
|
|
||||||
|
// Setting ComVisible to false makes the types in this assembly not visible
|
||||||
|
// to COM components. If you need to access a type in this assembly from
|
||||||
|
// COM, set the ComVisible attribute to true on that type.
|
||||||
|
[assembly: ComVisible(false)]
|
||||||
|
|
||||||
|
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||||
|
[assembly: Guid("7d1a55b1-8fab-42ff-9c83-066a9cc34d76")]
|
||||||
|
|
||||||
|
// Version information for an assembly consists of the following four values:
|
||||||
|
//
|
||||||
|
// Major Version
|
||||||
|
// Minor Version
|
||||||
|
// Build Number
|
||||||
|
// Revision
|
||||||
|
//
|
||||||
|
[assembly: AssemblyVersion("0.7.6.*")]
|
||||||
|
[assembly: AssemblyFileVersion("1.0.0.0")]
|
|
@ -0,0 +1,225 @@
|
||||||
|
/*
|
||||||
|
* 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 Nini.Config;
|
||||||
|
using log4net;
|
||||||
|
using System.Reflection;
|
||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Xml;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using OpenSim.Server.Base;
|
||||||
|
using OpenSim.Framework;
|
||||||
|
using OpenSim.Framework.Console;
|
||||||
|
using OpenMetaverse;
|
||||||
|
|
||||||
|
namespace OpenSim.ConsoleClient
|
||||||
|
{
|
||||||
|
public class OpenSimConsoleClient
|
||||||
|
{
|
||||||
|
protected static ServicesServerBase m_Server = null;
|
||||||
|
private static string m_Host;
|
||||||
|
private static int m_Port;
|
||||||
|
private static string m_User;
|
||||||
|
private static string m_Pass;
|
||||||
|
private static UUID m_SessionID;
|
||||||
|
|
||||||
|
static int Main(string[] args)
|
||||||
|
{
|
||||||
|
m_Server = new ServicesServerBase("Client", args);
|
||||||
|
|
||||||
|
IConfig serverConfig = m_Server.Config.Configs["Startup"];
|
||||||
|
if (serverConfig == null)
|
||||||
|
{
|
||||||
|
System.Console.WriteLine("Startup config section missing in .ini file");
|
||||||
|
throw new Exception("Configuration error");
|
||||||
|
}
|
||||||
|
|
||||||
|
ArgvConfigSource argvConfig = new ArgvConfigSource(args);
|
||||||
|
|
||||||
|
argvConfig.AddSwitch("Startup", "host", "h");
|
||||||
|
argvConfig.AddSwitch("Startup", "port", "p");
|
||||||
|
argvConfig.AddSwitch("Startup", "user", "u");
|
||||||
|
argvConfig.AddSwitch("Startup", "pass", "P");
|
||||||
|
|
||||||
|
m_Server.Config.Merge(argvConfig);
|
||||||
|
|
||||||
|
m_User = serverConfig.GetString("user", "Test");
|
||||||
|
m_Host = serverConfig.GetString("host", "localhost");
|
||||||
|
m_Port = serverConfig.GetInt("port", 8003);
|
||||||
|
m_Pass = serverConfig.GetString("pass", "secret");
|
||||||
|
|
||||||
|
Requester.MakeRequest("http://"+m_Host+":"+m_Port.ToString()+"/StartSession/", String.Format("USER={0}&PASS={1}", m_User, m_Pass), LoginReply);
|
||||||
|
|
||||||
|
string pidFile = serverConfig.GetString("PIDFile", String.Empty);
|
||||||
|
|
||||||
|
while (m_Server.Running)
|
||||||
|
{
|
||||||
|
System.Threading.Thread.Sleep(500);
|
||||||
|
MainConsole.Instance.Prompt();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pidFile != String.Empty)
|
||||||
|
File.Delete(pidFile);
|
||||||
|
|
||||||
|
Environment.Exit(0);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void SendCommand(string module, string[] cmd)
|
||||||
|
{
|
||||||
|
string sendCmd = "";
|
||||||
|
string[] cmdlist = new string[cmd.Length - 1];
|
||||||
|
|
||||||
|
sendCmd = cmd[0];
|
||||||
|
|
||||||
|
if (cmd.Length > 1)
|
||||||
|
{
|
||||||
|
Array.Copy(cmd, 1, cmdlist, 0, cmd.Length - 1);
|
||||||
|
sendCmd += " \"" + String.Join("\" \"", cmdlist) + "\"";
|
||||||
|
}
|
||||||
|
|
||||||
|
Requester.MakeRequest("http://"+m_Host+":"+m_Port.ToString()+"/SessionCommand/", String.Format("ID={0}&COMMAND={1}", m_SessionID, sendCmd), CommandReply);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void LoginReply(string requestUrl, string requestData, string replyData)
|
||||||
|
{
|
||||||
|
XmlDocument doc = new XmlDocument();
|
||||||
|
|
||||||
|
doc.LoadXml(replyData);
|
||||||
|
|
||||||
|
XmlNodeList rootL = doc.GetElementsByTagName("ConsoleSession");
|
||||||
|
if (rootL.Count != 1)
|
||||||
|
{
|
||||||
|
MainConsole.Instance.Output("Connection data info was not valid");
|
||||||
|
Environment.Exit(1);
|
||||||
|
}
|
||||||
|
XmlElement rootNode = (XmlElement)rootL[0];
|
||||||
|
|
||||||
|
if (rootNode == null)
|
||||||
|
{
|
||||||
|
MainConsole.Instance.Output("Connection data info was not valid");
|
||||||
|
Environment.Exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
XmlNodeList helpNodeL = rootNode.GetElementsByTagName("HelpTree");
|
||||||
|
if (helpNodeL.Count != 1)
|
||||||
|
{
|
||||||
|
MainConsole.Instance.Output("Connection data info was not valid");
|
||||||
|
Environment.Exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
XmlElement helpNode = (XmlElement)helpNodeL[0];
|
||||||
|
if (helpNode == null)
|
||||||
|
{
|
||||||
|
MainConsole.Instance.Output("Connection data info was not valid");
|
||||||
|
Environment.Exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
XmlNodeList sessionL = rootNode.GetElementsByTagName("SessionID");
|
||||||
|
if (sessionL.Count != 1)
|
||||||
|
{
|
||||||
|
MainConsole.Instance.Output("Connection data info was not valid");
|
||||||
|
Environment.Exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
XmlElement sessionNode = (XmlElement)sessionL[0];
|
||||||
|
if (sessionNode == null)
|
||||||
|
{
|
||||||
|
MainConsole.Instance.Output("Connection data info was not valid");
|
||||||
|
Environment.Exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!UUID.TryParse(sessionNode.InnerText, out m_SessionID))
|
||||||
|
{
|
||||||
|
MainConsole.Instance.Output("Connection data info was not valid");
|
||||||
|
Environment.Exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
MainConsole.Instance.Commands.FromXml(helpNode, SendCommand);
|
||||||
|
|
||||||
|
Requester.MakeRequest("http://"+m_Host+":"+m_Port.ToString()+"/ReadResponses/"+m_SessionID.ToString()+"/", String.Empty, ReadResponses);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void ReadResponses(string requestUrl, string requestData, string replyData)
|
||||||
|
{
|
||||||
|
XmlDocument doc = new XmlDocument();
|
||||||
|
|
||||||
|
doc.LoadXml(replyData);
|
||||||
|
|
||||||
|
XmlNodeList rootNodeL = doc.GetElementsByTagName("ConsoleSession");
|
||||||
|
if (rootNodeL.Count != 1 || rootNodeL[0] == null)
|
||||||
|
{
|
||||||
|
Requester.MakeRequest(requestUrl, requestData, ReadResponses);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<string> lines = new List<string>();
|
||||||
|
|
||||||
|
foreach (XmlNode part in rootNodeL[0].ChildNodes)
|
||||||
|
{
|
||||||
|
if (part.Name != "Line")
|
||||||
|
continue;
|
||||||
|
|
||||||
|
lines.Add(part.InnerText);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cut down scrollback to 100 lines (4 screens)
|
||||||
|
// for the command line client
|
||||||
|
//
|
||||||
|
while (lines.Count > 100)
|
||||||
|
lines.RemoveAt(0);
|
||||||
|
|
||||||
|
string prompt = String.Empty;
|
||||||
|
|
||||||
|
foreach (string l in lines)
|
||||||
|
{
|
||||||
|
string[] parts = l.Split(new char[] {':'}, 3);
|
||||||
|
if (parts.Length != 3)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (parts[2].StartsWith("+++") || parts[2].StartsWith("-++"))
|
||||||
|
prompt = parts[2];
|
||||||
|
else
|
||||||
|
MainConsole.Instance.Output(parts[2].Trim(), parts[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Requester.MakeRequest(requestUrl, requestData, ReadResponses);
|
||||||
|
|
||||||
|
if (prompt.StartsWith("+++"))
|
||||||
|
MainConsole.Instance.ReadLine(prompt.Substring(3), true, true);
|
||||||
|
else if (prompt.StartsWith("-++"))
|
||||||
|
SendCommand(String.Empty, new string[] { MainConsole.Instance.ReadLine(prompt.Substring(3), false, true) });
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void CommandReply(string requestUrl, string requestData, string replyData)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,33 @@
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
// General Information about an assembly is controlled through the following
|
||||||
|
// set of attributes. Change these attribute values to modify the information
|
||||||
|
// associated with an assembly.
|
||||||
|
[assembly: AssemblyTitle("OpenSim.ConsoleClient")]
|
||||||
|
[assembly: AssemblyDescription("")]
|
||||||
|
[assembly: AssemblyConfiguration("")]
|
||||||
|
[assembly: AssemblyCompany("http://opensimulator.org")]
|
||||||
|
[assembly: AssemblyProduct("OpenSim")]
|
||||||
|
[assembly: AssemblyCopyright("OpenSimulator developers")]
|
||||||
|
[assembly: AssemblyTrademark("")]
|
||||||
|
[assembly: AssemblyCulture("")]
|
||||||
|
|
||||||
|
// Setting ComVisible to false makes the types in this assembly not visible
|
||||||
|
// to COM components. If you need to access a type in this assembly from
|
||||||
|
// COM, set the ComVisible attribute to true on that type.
|
||||||
|
[assembly: ComVisible(false)]
|
||||||
|
|
||||||
|
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||||
|
[assembly: Guid("8945df94-2e5e-475b-88fa-35a7cdde6fd7")]
|
||||||
|
|
||||||
|
// Version information for an assembly consists of the following four values:
|
||||||
|
//
|
||||||
|
// Major Version
|
||||||
|
// Minor Version
|
||||||
|
// Build Number
|
||||||
|
// Revision
|
||||||
|
//
|
||||||
|
[assembly: AssemblyVersion("0.7.6.*")]
|
||||||
|
[assembly: AssemblyFileVersion("1.0.0.0")]
|
|
@ -0,0 +1,85 @@
|
||||||
|
/*
|
||||||
|
* 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.IO;
|
||||||
|
using System.Net;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Text;
|
||||||
|
using System.Xml;
|
||||||
|
using System.Xml.Serialization;
|
||||||
|
using log4net;
|
||||||
|
|
||||||
|
namespace OpenSim.ConsoleClient
|
||||||
|
{
|
||||||
|
public delegate void ReplyDelegate(string requestUrl, string requestData, string replyData);
|
||||||
|
|
||||||
|
public class Requester
|
||||||
|
{
|
||||||
|
public static void MakeRequest(string requestUrl, string data,
|
||||||
|
ReplyDelegate action)
|
||||||
|
{
|
||||||
|
WebRequest request = WebRequest.Create(requestUrl);
|
||||||
|
|
||||||
|
request.Method = "POST";
|
||||||
|
|
||||||
|
request.ContentType = "application/x-www-form-urlencoded";
|
||||||
|
|
||||||
|
byte[] buffer = Encoding.ASCII.GetBytes(data);
|
||||||
|
int length = (int) buffer.Length;
|
||||||
|
request.ContentLength = length;
|
||||||
|
|
||||||
|
request.BeginGetRequestStream(delegate(IAsyncResult res)
|
||||||
|
{
|
||||||
|
Stream requestStream = request.EndGetRequestStream(res);
|
||||||
|
|
||||||
|
requestStream.Write(buffer, 0, length);
|
||||||
|
|
||||||
|
request.BeginGetResponse(delegate(IAsyncResult ar)
|
||||||
|
{
|
||||||
|
string reply = String.Empty;
|
||||||
|
|
||||||
|
using (WebResponse response = request.EndGetResponse(ar))
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using (Stream s = response.GetResponseStream())
|
||||||
|
using (StreamReader r = new StreamReader(s))
|
||||||
|
reply = r.ReadToEnd();
|
||||||
|
|
||||||
|
}
|
||||||
|
catch (System.InvalidOperationException)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
action(requestUrl, data, reply);
|
||||||
|
}, null);
|
||||||
|
}, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,52 @@
|
||||||
|
/*
|
||||||
|
* 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.Text;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
using OpenMetaverse;
|
||||||
|
using OpenSim.Framework;
|
||||||
|
|
||||||
|
namespace OpenSim.Data
|
||||||
|
{
|
||||||
|
public abstract class AssetDataBase : IAssetDataPlugin
|
||||||
|
{
|
||||||
|
public abstract AssetBase GetAsset(UUID uuid);
|
||||||
|
public abstract bool StoreAsset(AssetBase asset);
|
||||||
|
public abstract bool[] AssetsExist(UUID[] uuids);
|
||||||
|
|
||||||
|
public abstract List<AssetMetadata> FetchAssetMetadataSet(int start, int count);
|
||||||
|
|
||||||
|
public abstract string Version { get; }
|
||||||
|
public abstract string Name { get; }
|
||||||
|
public abstract void Initialise(string connect);
|
||||||
|
public abstract void Initialise();
|
||||||
|
public abstract void Dispose();
|
||||||
|
public abstract bool Delete(string id);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,72 @@
|
||||||
|
/*
|
||||||
|
* 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.Text;
|
||||||
|
using OpenMetaverse;
|
||||||
|
|
||||||
|
namespace OpenSim.Data
|
||||||
|
{
|
||||||
|
|
||||||
|
public static class DBGuid
|
||||||
|
{
|
||||||
|
/// <summary>This function converts a value returned from the database in one of the
|
||||||
|
/// supported formats into a UUID. This function is not actually DBMS-specific right
|
||||||
|
/// now
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="id"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static UUID FromDB(object id)
|
||||||
|
{
|
||||||
|
if ((id == null) || (id == DBNull.Value))
|
||||||
|
return UUID.Zero;
|
||||||
|
|
||||||
|
Type idtype = id.GetType();
|
||||||
|
|
||||||
|
if (idtype == typeof(Guid))
|
||||||
|
return new UUID((Guid)id);
|
||||||
|
|
||||||
|
if (id.GetType() == typeof(string))
|
||||||
|
{
|
||||||
|
Guid gg;
|
||||||
|
if (Guid.TryParse((string)id, out gg))
|
||||||
|
return new UUID(gg);
|
||||||
|
return UUID.Zero;
|
||||||
|
}
|
||||||
|
|
||||||
|
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());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,46 @@
|
||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
using OpenSim.Framework;
|
||||||
|
|
||||||
|
namespace OpenSim.Data
|
||||||
|
{
|
||||||
|
public class AgentPreferencesData
|
||||||
|
{
|
||||||
|
public Dictionary<string, string> Data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface IAgentPreferencesData
|
||||||
|
{
|
||||||
|
bool Store(AgentPreferencesData data);
|
||||||
|
AgentPreferencesData GetPrefs(UUID agentID);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,43 @@
|
||||||
|
/*
|
||||||
|
* 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 interface IAssetDataPlugin : IPlugin
|
||||||
|
{
|
||||||
|
AssetBase GetAsset(UUID uuid);
|
||||||
|
bool StoreAsset(AssetBase asset);
|
||||||
|
bool[] AssetsExist(UUID[] uuids);
|
||||||
|
List<AssetMetadata> FetchAssetMetadataSet(int start, int count);
|
||||||
|
void Initialise(string connect);
|
||||||
|
bool Delete(string id);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,56 @@
|
||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
using OpenSim.Framework;
|
||||||
|
|
||||||
|
namespace OpenSim.Data
|
||||||
|
{
|
||||||
|
public class AuthenticationData
|
||||||
|
{
|
||||||
|
public UUID PrincipalID;
|
||||||
|
public Dictionary<string, object> Data;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// An interface for connecting to the authentication datastore
|
||||||
|
/// </summary>
|
||||||
|
public interface IAuthenticationData
|
||||||
|
{
|
||||||
|
AuthenticationData Get(UUID principalID);
|
||||||
|
|
||||||
|
bool Store(AuthenticationData data);
|
||||||
|
|
||||||
|
bool SetDataItem(UUID principalID, string item, string value);
|
||||||
|
|
||||||
|
bool SetToken(UUID principalID, string token, int lifetime);
|
||||||
|
|
||||||
|
bool CheckToken(UUID principalID, string token, int lifetime);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,49 @@
|
||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
using OpenSim.Framework;
|
||||||
|
|
||||||
|
namespace OpenSim.Data
|
||||||
|
{
|
||||||
|
// This MUST be a ref type!
|
||||||
|
public class AvatarBaseData
|
||||||
|
{
|
||||||
|
public UUID PrincipalID;
|
||||||
|
public Dictionary<string, string> Data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface IAvatarData
|
||||||
|
{
|
||||||
|
AvatarBaseData[] Get(string field, string val);
|
||||||
|
bool Store(AvatarBaseData data);
|
||||||
|
bool Delete(UUID principalID, string name);
|
||||||
|
bool Delete(string field, string val);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,120 @@
|
||||||
|
/*
|
||||||
|
* 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 interface IEstateDataStore
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Initialise the data store.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="connectstring"></param>
|
||||||
|
void Initialise(string connectstring);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Load estate settings for a region.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="regionID"></param>
|
||||||
|
/// <param name="create">If true, then an estate is created if one is not found.</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
EstateSettings LoadEstateSettings(UUID regionID, bool create);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Load estate settings for an estate ID.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="estateID"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
EstateSettings LoadEstateSettings(int estateID);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Create a new estate.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>
|
||||||
|
/// A <see cref="EstateSettings"/>
|
||||||
|
/// </returns>
|
||||||
|
EstateSettings CreateNewEstate();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Load/Get all estate settings.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>An empty list if no estates were found.</returns>
|
||||||
|
List<EstateSettings> LoadEstateSettingsAll();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Store estate settings.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// This is also called by EstateSettings.Save()</remarks>
|
||||||
|
/// <param name="es"></param>
|
||||||
|
void StoreEstateSettings(EstateSettings es);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get estate IDs.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="search">Name of estate to search for. This is the exact name, no parttern matching is done.</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
List<int> GetEstates(string search);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the IDs of all estates owned by the given user.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>An empty list if no estates were found.</returns>
|
||||||
|
List<int> GetEstatesByOwner(UUID ownerID);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the IDs of all estates.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>An empty list if no estates were found.</returns>
|
||||||
|
List<int> GetEstatesAll();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Link a region to an estate.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="regionID"></param>
|
||||||
|
/// <param name="estateID"></param>
|
||||||
|
/// <returns>true if the link succeeded, false otherwise</returns>
|
||||||
|
bool LinkRegion(UUID regionID, int estateID);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the UUIDs of all the regions in an estate.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="estateID"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
List<UUID> GetRegions(int estateID);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Delete an estate
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="estateID"></param>
|
||||||
|
/// <returns>true if the delete succeeded, false otherwise</returns>
|
||||||
|
bool DeleteEstate(int estateID);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,47 @@
|
||||||
|
/*
|
||||||
|
* 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();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,53 @@
|
||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
using OpenSim.Framework;
|
||||||
|
|
||||||
|
namespace OpenSim.Data
|
||||||
|
{
|
||||||
|
public class FriendsData
|
||||||
|
{
|
||||||
|
public string PrincipalID;
|
||||||
|
public string Friend;
|
||||||
|
public Dictionary<string, string> Data;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// An interface for connecting to the friends datastore
|
||||||
|
/// </summary>
|
||||||
|
public interface IFriendsData
|
||||||
|
{
|
||||||
|
bool Store(FriendsData data);
|
||||||
|
bool Delete(UUID ownerID, string friend);
|
||||||
|
bool Delete(string ownerID, string friend);
|
||||||
|
FriendsData[] GetFriends(UUID principalID);
|
||||||
|
FriendsData[] GetFriends(string principalID);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,56 @@
|
||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
using OpenSim.Framework;
|
||||||
|
|
||||||
|
namespace OpenSim.Data
|
||||||
|
{
|
||||||
|
// This MUST be a ref type!
|
||||||
|
public class GridUserData
|
||||||
|
{
|
||||||
|
public string UserID;
|
||||||
|
public Dictionary<string, string> Data;
|
||||||
|
|
||||||
|
public GridUserData()
|
||||||
|
{
|
||||||
|
Data = new Dictionary<string, string>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// An interface for connecting to the user grid datastore
|
||||||
|
/// </summary>
|
||||||
|
public interface IGridUserData
|
||||||
|
{
|
||||||
|
GridUserData Get(string userID);
|
||||||
|
GridUserData[] GetAll(string query);
|
||||||
|
bool Store(GridUserData data);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,144 @@
|
||||||
|
/*
|
||||||
|
* 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 OpenSim.Data;
|
||||||
|
using OpenMetaverse;
|
||||||
|
|
||||||
|
namespace OpenSim.Data
|
||||||
|
{
|
||||||
|
public class GroupData
|
||||||
|
{
|
||||||
|
public UUID GroupID;
|
||||||
|
public Dictionary<string, string> Data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public class MembershipData
|
||||||
|
{
|
||||||
|
public UUID GroupID;
|
||||||
|
public string PrincipalID;
|
||||||
|
public Dictionary<string, string> Data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public class RoleData
|
||||||
|
{
|
||||||
|
public UUID GroupID;
|
||||||
|
public UUID RoleID;
|
||||||
|
public Dictionary<string, string> Data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public class RoleMembershipData
|
||||||
|
{
|
||||||
|
public UUID GroupID;
|
||||||
|
public UUID RoleID;
|
||||||
|
public string PrincipalID;
|
||||||
|
}
|
||||||
|
|
||||||
|
public class PrincipalData
|
||||||
|
{
|
||||||
|
public string PrincipalID;
|
||||||
|
public UUID ActiveGroupID;
|
||||||
|
}
|
||||||
|
|
||||||
|
public class InvitationData
|
||||||
|
{
|
||||||
|
public UUID InviteID;
|
||||||
|
public UUID GroupID;
|
||||||
|
public UUID RoleID;
|
||||||
|
public string PrincipalID;
|
||||||
|
public Dictionary<string, string> Data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public class NoticeData
|
||||||
|
{
|
||||||
|
public UUID GroupID;
|
||||||
|
public UUID NoticeID;
|
||||||
|
public Dictionary<string, string> Data;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public interface IGroupsData
|
||||||
|
{
|
||||||
|
// groups table
|
||||||
|
bool StoreGroup(GroupData data);
|
||||||
|
GroupData RetrieveGroup(UUID groupID);
|
||||||
|
GroupData RetrieveGroup(string name);
|
||||||
|
GroupData[] RetrieveGroups(string pattern);
|
||||||
|
bool DeleteGroup(UUID groupID);
|
||||||
|
int GroupsCount();
|
||||||
|
|
||||||
|
// membership table
|
||||||
|
MembershipData RetrieveMember(UUID groupID, string pricipalID);
|
||||||
|
MembershipData[] RetrieveMembers(UUID groupID);
|
||||||
|
MembershipData[] RetrieveMemberships(string pricipalID);
|
||||||
|
bool StoreMember(MembershipData data);
|
||||||
|
bool DeleteMember(UUID groupID, string pricipalID);
|
||||||
|
int MemberCount(UUID groupID);
|
||||||
|
|
||||||
|
// roles table
|
||||||
|
bool StoreRole(RoleData data);
|
||||||
|
RoleData RetrieveRole(UUID groupID, UUID roleID);
|
||||||
|
RoleData[] RetrieveRoles(UUID groupID);
|
||||||
|
bool DeleteRole(UUID groupID, UUID roleID);
|
||||||
|
int RoleCount(UUID groupID);
|
||||||
|
|
||||||
|
// rolememberhip table
|
||||||
|
RoleMembershipData[] RetrieveRolesMembers(UUID groupID);
|
||||||
|
RoleMembershipData[] RetrieveRoleMembers(UUID groupID, UUID roleID);
|
||||||
|
RoleMembershipData[] RetrieveMemberRoles(UUID groupID, string principalID);
|
||||||
|
RoleMembershipData RetrieveRoleMember(UUID groupID, UUID roleID, string principalID);
|
||||||
|
int RoleMemberCount(UUID groupID, UUID roleID);
|
||||||
|
bool StoreRoleMember(RoleMembershipData data);
|
||||||
|
bool DeleteRoleMember(RoleMembershipData data);
|
||||||
|
bool DeleteMemberAllRoles(UUID groupID, string principalID);
|
||||||
|
|
||||||
|
// principals table
|
||||||
|
bool StorePrincipal(PrincipalData data);
|
||||||
|
PrincipalData RetrievePrincipal(string principalID);
|
||||||
|
bool DeletePrincipal(string principalID);
|
||||||
|
|
||||||
|
// invites table
|
||||||
|
bool StoreInvitation(InvitationData data);
|
||||||
|
InvitationData RetrieveInvitation(UUID inviteID);
|
||||||
|
InvitationData RetrieveInvitation(UUID groupID, string principalID);
|
||||||
|
bool DeleteInvite(UUID inviteID);
|
||||||
|
void DeleteOldInvites();
|
||||||
|
|
||||||
|
// notices table
|
||||||
|
bool StoreNotice(NoticeData data);
|
||||||
|
NoticeData RetrieveNotice(UUID noticeID);
|
||||||
|
NoticeData[] RetrieveNotices(UUID groupID);
|
||||||
|
bool DeleteNotice(UUID noticeID);
|
||||||
|
void DeleteOldNotices();
|
||||||
|
|
||||||
|
// combinations
|
||||||
|
MembershipData RetrievePrincipalGroupMembership(string principalID, UUID groupID);
|
||||||
|
MembershipData[] RetrievePrincipalGroupMemberships(string principalID);
|
||||||
|
|
||||||
|
// Misc
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,59 @@
|
||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
using OpenSim.Framework;
|
||||||
|
|
||||||
|
namespace OpenSim.Data
|
||||||
|
{
|
||||||
|
// This MUST be a ref type!
|
||||||
|
public class HGTravelingData
|
||||||
|
{
|
||||||
|
public UUID SessionID;
|
||||||
|
public UUID UserID;
|
||||||
|
public Dictionary<string, string> Data;
|
||||||
|
|
||||||
|
public HGTravelingData()
|
||||||
|
{
|
||||||
|
Data = new Dictionary<string, string>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// An interface for connecting to the user grid datastore
|
||||||
|
/// </summary>
|
||||||
|
public interface IHGTravelingData
|
||||||
|
{
|
||||||
|
HGTravelingData Get(UUID sessionID);
|
||||||
|
HGTravelingData[] GetSessions(UUID userID);
|
||||||
|
bool Store(HGTravelingData data);
|
||||||
|
bool Delete(UUID sessionID);
|
||||||
|
void DeleteOld();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,158 @@
|
||||||
|
/*
|
||||||
|
* 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
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// An interface for accessing inventory data from a storage server
|
||||||
|
/// </summary>
|
||||||
|
public interface IInventoryDataPlugin : IPlugin
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Initialises the interface
|
||||||
|
/// </summary>
|
||||||
|
void Initialise(string connect);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns all descendent folders of this folder. Does not return the parent folder itself.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="parentID">The folder to get subfolders for</param>
|
||||||
|
/// <returns>A list of inventory folders</returns>
|
||||||
|
List<InventoryFolderBase> getFolderHierarchy(UUID parentID);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns a list of inventory items contained within the specified folder
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="folderID">The UUID of the target folder</param>
|
||||||
|
/// <returns>A List of InventoryItemBase items</returns>
|
||||||
|
List<InventoryItemBase> getInventoryInFolder(UUID folderID);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns a list of the root folders within a users inventory
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="user">The user whos inventory is to be searched</param>
|
||||||
|
/// <returns>A list of folder objects</returns>
|
||||||
|
List<InventoryFolderBase> getUserRootFolders(UUID user);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the users inventory root folder.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="user">The UUID of the user who is having inventory being returned</param>
|
||||||
|
/// <returns>Root inventory folder, null if no root inventory folder was found</returns>
|
||||||
|
InventoryFolderBase getUserRootFolder(UUID user);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns a list of inventory folders contained in the folder 'parentID'
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="parentID">The folder to get subfolders for</param>
|
||||||
|
/// <returns>A list of inventory folders</returns>
|
||||||
|
List<InventoryFolderBase> getInventoryFolders(UUID parentID);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns an inventory item by its UUID
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="item">The UUID of the item to be returned</param>
|
||||||
|
/// <returns>A class containing item information</returns>
|
||||||
|
InventoryItemBase getInventoryItem(UUID item);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns a specified inventory folder by its UUID
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="folder">The UUID of the folder to be returned</param>
|
||||||
|
/// <returns>A class containing folder information</returns>
|
||||||
|
InventoryFolderBase getInventoryFolder(UUID folder);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a new inventory item based on item
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="item">The item to be created</param>
|
||||||
|
void addInventoryItem(InventoryItemBase item);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Updates an inventory item with item (updates based on ID)
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="item">The updated item</param>
|
||||||
|
void updateInventoryItem(InventoryItemBase item);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="item"></param>
|
||||||
|
void deleteInventoryItem(UUID item);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="item"></param>
|
||||||
|
InventoryItemBase queryInventoryItem(UUID item);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="item"></param>
|
||||||
|
InventoryFolderBase queryInventoryFolder(UUID folder);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Adds a new folder specified by folder
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="folder">The inventory folder</param>
|
||||||
|
void addInventoryFolder(InventoryFolderBase folder);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Updates a folder based on its ID with folder
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="folder">The inventory folder</param>
|
||||||
|
void updateInventoryFolder(InventoryFolderBase folder);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Updates a folder based on its ID with folder
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="folder">The inventory folder</param>
|
||||||
|
void moveInventoryFolder(InventoryFolderBase folder);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Deletes a folder. Thie will delete both the folder itself and its contents (items and descendent folders)
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="folder">The id of the folder</param>
|
||||||
|
void deleteInventoryFolder(UUID folder);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns all activated gesture-items in the inventory of the specified avatar.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="avatarID">
|
||||||
|
/// The <see cref="UUID"/> of the avatar
|
||||||
|
/// </param>
|
||||||
|
/// <returns>
|
||||||
|
/// The list of gestures (<see cref="InventoryItemBase"/>s)
|
||||||
|
/// </returns>
|
||||||
|
List<InventoryItemBase> fetchActiveGestures(UUID avatarID);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,44 @@
|
||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
using OpenSim.Framework;
|
||||||
|
|
||||||
|
namespace OpenSim.Data
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// An interface for connecting to the Mute List datastore
|
||||||
|
/// </summary>
|
||||||
|
public interface IMuteListData
|
||||||
|
{
|
||||||
|
bool Store(MuteData data);
|
||||||
|
MuteData[] Get(UUID agentID);
|
||||||
|
bool Delete(UUID agentID, UUID muteID, string muteName);
|
||||||
|
}
|
||||||
|
}
|
|
@ -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 System.Collections.Generic;
|
||||||
|
using OpenSim.Data;
|
||||||
|
using OpenMetaverse;
|
||||||
|
|
||||||
|
namespace OpenSim.Data
|
||||||
|
{
|
||||||
|
public class OfflineIMData
|
||||||
|
{
|
||||||
|
public UUID PrincipalID;
|
||||||
|
public UUID FromID;
|
||||||
|
public Dictionary<string, string> Data;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public interface IOfflineIMData
|
||||||
|
{
|
||||||
|
OfflineIMData[] Get(string field, string val);
|
||||||
|
long GetCount(string field, string key);
|
||||||
|
bool Store(OfflineIMData data);
|
||||||
|
bool Delete(string field, string val);
|
||||||
|
void DeleteOld();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,58 @@
|
||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
using OpenSim.Framework;
|
||||||
|
|
||||||
|
namespace OpenSim.Data
|
||||||
|
{
|
||||||
|
// This MUST be a ref type!
|
||||||
|
public class PresenceData
|
||||||
|
{
|
||||||
|
public string UserID;
|
||||||
|
public UUID RegionID;
|
||||||
|
public UUID SessionID;
|
||||||
|
public Dictionary<string, string> Data;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// An interface for connecting to the presence datastore
|
||||||
|
/// </summary>
|
||||||
|
public interface IPresenceData
|
||||||
|
{
|
||||||
|
bool Store(PresenceData data);
|
||||||
|
|
||||||
|
PresenceData Get(UUID sessionID);
|
||||||
|
void LogoutRegionAgents(UUID regionID);
|
||||||
|
bool ReportAgent(UUID sessionID, UUID regionID);
|
||||||
|
PresenceData[] Get(string field, string data);
|
||||||
|
bool Delete(string field, string val);
|
||||||
|
bool VerifyAgent(UUID agentId, UUID secureSessionID);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,58 @@
|
||||||
|
/*
|
||||||
|
* 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 OpenMetaverse;
|
||||||
|
using OpenMetaverse.StructuredData;
|
||||||
|
using OpenSim.Framework;
|
||||||
|
|
||||||
|
namespace OpenSim.Data
|
||||||
|
{
|
||||||
|
|
||||||
|
public interface IProfilesData
|
||||||
|
{
|
||||||
|
OSDArray GetClassifiedRecords(UUID creatorId);
|
||||||
|
bool UpdateClassifiedRecord(UserClassifiedAdd ad, ref string result);
|
||||||
|
bool DeleteClassifiedRecord(UUID recordId);
|
||||||
|
OSDArray GetAvatarPicks(UUID avatarId);
|
||||||
|
UserProfilePick GetPickInfo(UUID avatarId, UUID pickId);
|
||||||
|
bool UpdatePicksRecord(UserProfilePick pick);
|
||||||
|
bool DeletePicksRecord(UUID pickId);
|
||||||
|
bool GetAvatarNotes(ref UserProfileNotes note);
|
||||||
|
bool UpdateAvatarNotes(ref UserProfileNotes note, ref string result);
|
||||||
|
bool GetAvatarProperties(ref UserProfileProperties props, ref string result);
|
||||||
|
bool UpdateAvatarProperties(ref UserProfileProperties props, ref string result);
|
||||||
|
bool UpdateAvatarInterests(UserProfileProperties up, ref string result);
|
||||||
|
bool GetClassifiedInfo(ref UserClassifiedAdd ad, ref string result);
|
||||||
|
bool UpdateUserPreferences(ref UserPreferences pref, ref string result);
|
||||||
|
bool GetUserPreferences(ref UserPreferences pref, ref string result);
|
||||||
|
bool GetUserAppData(ref UserAppData props, ref string result);
|
||||||
|
bool SetUserAppData(UserAppData props, ref string result);
|
||||||
|
OSDArray GetUserImageAssets(UUID avatarId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,112 @@
|
||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
using OpenSim.Framework;
|
||||||
|
|
||||||
|
namespace OpenSim.Data
|
||||||
|
{
|
||||||
|
public class RegionData
|
||||||
|
{
|
||||||
|
public UUID RegionID;
|
||||||
|
public UUID ScopeID;
|
||||||
|
public string RegionName;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The position in meters of this region.
|
||||||
|
/// </summary>
|
||||||
|
public int posX;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The position in meters of this region.
|
||||||
|
/// </summary>
|
||||||
|
public int posY;
|
||||||
|
|
||||||
|
public int sizeX;
|
||||||
|
public int sizeY;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Return the x-coordinate of this region in region units.
|
||||||
|
/// </summary>
|
||||||
|
public int coordX { get { return (int)Util.WorldToRegionLoc((uint)posX); } }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Return the y-coordinate of this region in region units.
|
||||||
|
/// </summary>
|
||||||
|
public int coordY { get { return (int)Util.WorldToRegionLoc((uint)posY); } }
|
||||||
|
|
||||||
|
public Dictionary<string, object> Data;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// An interface for connecting to the authentication datastore
|
||||||
|
/// </summary>
|
||||||
|
public interface IRegionData
|
||||||
|
{
|
||||||
|
RegionData Get(UUID regionID, UUID ScopeID);
|
||||||
|
List<RegionData> Get(string regionName, UUID ScopeID);
|
||||||
|
RegionData GetSpecific(string regionName, UUID ScopeID);
|
||||||
|
|
||||||
|
RegionData Get(int x, int y, UUID ScopeID);
|
||||||
|
List<RegionData> Get(int xStart, int yStart, int xEnd, int yEnd, UUID ScopeID);
|
||||||
|
|
||||||
|
bool Store(RegionData data);
|
||||||
|
|
||||||
|
bool SetDataItem(UUID principalID, string item, string value);
|
||||||
|
|
||||||
|
bool Delete(UUID regionID);
|
||||||
|
|
||||||
|
List<RegionData> GetDefaultRegions(UUID scopeID);
|
||||||
|
List<RegionData> GetDefaultHypergridRegions(UUID scopeID);
|
||||||
|
List<RegionData> GetFallbackRegions(UUID scopeID, int x, int y);
|
||||||
|
List<RegionData> GetHyperlinks(UUID scopeID);
|
||||||
|
}
|
||||||
|
|
||||||
|
public class RegionDataDistanceCompare : IComparer<RegionData>
|
||||||
|
{
|
||||||
|
private Vector2 m_origin;
|
||||||
|
|
||||||
|
public RegionDataDistanceCompare(int x, int y)
|
||||||
|
{
|
||||||
|
m_origin = new Vector2(x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int Compare(RegionData regionA, RegionData regionB)
|
||||||
|
{
|
||||||
|
Vector2 vectorA = new Vector2(regionA.posX, regionA.posY);
|
||||||
|
Vector2 vectorB = new Vector2(regionB.posX, regionB.posY);
|
||||||
|
return Math.Sign(VectorDistance(m_origin, vectorA) - VectorDistance(m_origin, vectorB));
|
||||||
|
}
|
||||||
|
|
||||||
|
private float VectorDistance(Vector2 x, Vector2 y)
|
||||||
|
{
|
||||||
|
return (x - y).Length();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,55 @@
|
||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
using OpenSim.Framework;
|
||||||
|
|
||||||
|
namespace OpenSim.Data
|
||||||
|
{
|
||||||
|
public class UserAccountData
|
||||||
|
{
|
||||||
|
public UUID PrincipalID;
|
||||||
|
public UUID ScopeID;
|
||||||
|
public string FirstName;
|
||||||
|
public string LastName;
|
||||||
|
public Dictionary<string, string> Data;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// An interface for connecting to the user accounts datastore
|
||||||
|
/// </summary>
|
||||||
|
public interface IUserAccountData
|
||||||
|
{
|
||||||
|
UserAccountData[] Get(string[] fields, string[] values);
|
||||||
|
bool Store(UserAccountData data);
|
||||||
|
bool Delete(string field, string val);
|
||||||
|
UserAccountData[] GetUsers(UUID scopeID, string query);
|
||||||
|
UserAccountData[] GetUsersWhere(UUID scopeID, string where);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,47 @@
|
||||||
|
/*
|
||||||
|
* 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
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// This interface exists to distinguish between the normal IAssetDataPlugin and the one used by XAssetService
|
||||||
|
/// for now.
|
||||||
|
/// </summary>
|
||||||
|
public interface IXAssetDataPlugin : IPlugin
|
||||||
|
{
|
||||||
|
AssetBase GetAsset(UUID uuid);
|
||||||
|
void StoreAsset(AssetBase asset);
|
||||||
|
bool[] AssetsExist(UUID[] uuids);
|
||||||
|
List<AssetMetadata> FetchAssetMetadataSet(int start, int count);
|
||||||
|
void Initialise(string connect);
|
||||||
|
bool Delete(string id);
|
||||||
|
}
|
||||||
|
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue