Merge remote-tracking branch 'os/master'

avinationmerge
UbitUmarov 2015-09-01 11:43:07 +01:00
commit fb78b18252
2291 changed files with 638148 additions and 0 deletions

113
.gitignore vendored Normal file
View File

@ -0,0 +1,113 @@
.project
.settings
*.csproj
*.csproj.user
*.build
*.mdb
*.mdp
*.mds
*.pdb
*.pidb
*.dll.build
*.dll
# 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
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
addon-modules
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

23
.hgignore Normal file
View File

@ -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)$
.+~$

274
.nant/local.include Normal file
View File

@ -0,0 +1,274 @@
<!-- -*- 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}" />
<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>
<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}" />
</target>
<target name="doxygen">
<exec program="doxygen" workingdir="doc" commandline="doxygen.conf" />
</target>

40
BUILDING.md Normal file
View File

@ -0,0 +1,40 @@
# 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
Prereqs:
* Mono >= 2.4.3
* Nant >= 0.85
* On some Linux distributions you may need to install additional packages.
See http://opensimulator.org/wiki/Dependencies for more information.
* May also use xbuild (included in mono distributions)
* May use Monodevelop, a cross-platform IDE
From the distribution type:
* ./runprebuild.sh
* nant (or !* xbuild)
* cd bin
* copy OpenSim.ini.example to OpenSim.ini and other appropriate files in bin/config-include
* run mono OpenSim.exe
!* xbuild option switches
!* clean: xbuild /target:clean
!* debug: (default) xbuild /property:Configuration=Debug
!* release: xbuild /property:Configuration=Release
# Using Monodevelop
From the distribution type:
* ./runprebuild.sh
* type monodevelop OpenSim.sln
# References
Helpful resources:
* http://opensimulator.org/wiki/Build_Instructions

239
CONTRIBUTORS.txt Normal file
View File

@ -0,0 +1,239 @@
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.
* justincc (OSVW Consulting, justincc.org)
* dahlia
* Melanie Thielker
* Diva (Crista Lopes, University of California, Irvine)
* BlueWall (James Hughes)
* Nebadon Izumi (Michael Cerquoni, OSgrid)
* Snoopy Pfeffer
* Robert Adams (MisterBlue)
* Oren Hurvitz (Kitely)
* Kevin Cozens
= 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.
* Teravus (w3z)
* Arthur Rodrigo S Valadares (IBM)
* Dan Lake
* Marck
* Mic Bowman
= 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)
= 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
* Alicia Raven
* Allen Kerensky
* BigFootAg
* 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
* 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
* Glenn Martin (MOSES)
* Gryc Ueusp
* H-H-H (ginge264)
* Hiro Lecker
* Iain Oliver
* Imaze Rhiano
* Intimidated
* Jak Daniels
* 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
* lillith_xue
* lkalif
* LuciusSirnah
* lulurun
* M.Igarashi
* Magnuz Binder
* maimedleech
* Mana Janus
* MarcelEdward
* Matt Lehmann
* Mic Bowman
* Michelle Argus
* Michael Cortez (The Flotsam Project, http://osflotsam.org/)
* Michael Heilmann (MOSES)
* Micheil Merlin
* Mike Osias (IBM)
* Mike Pitman (IBM)
* 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
* 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)
* Strawberry Fride
* Talun
* TechplexEngineer (Blake Bourque)
* TBG Renfold
* tglion
* tlaukkan/Tommil (Tommi S. E. Laukkanen, Bubble Cloud)
* tyre
* Vegaslon <vegaslon@gmail.com>
* 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)

25
LICENSE.txt Normal file
View File

@ -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.

43
Makefile Normal file
View File

@ -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)

7241
OpenSim.FxCop Normal file

File diff suppressed because it is too large Load Diff

View File

@ -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;
}
}
}

View File

@ -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;
}
}
}

View File

@ -0,0 +1,848 @@
/*
* 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.OutputFormat("{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");
// Force? open the group session dialog???
// and simultanously deliver the message, so we don't need to do a seperate client.SendInstantMessage(msg);
IEventQueue eq = activeClient.Scene.RequestModuleInterface<IEventQueue>();
eq.ChatterboxInvitation(
GroupID
, groupInfo.GroupName
, new UUID(msg.fromAgentID)
, msg.message
, AgentID
, msg.fromAgentName
, msg.dialog
, msg.timestamp
, msg.offline == 1
, (int)msg.ParentEstateID
, msg.Position
, 1
, new UUID(msg.imSessionID)
, msg.fromGroup
, OpenMetaverse.Utils.StringToBytes(groupInfo.GroupName)
);
eq.ChatterBoxSessionAgentListUpdates(
new UUID(GroupID)
, AgentID
, new UUID(msg.toAgentID)
, false //canVoiceChat
, false //isModerator
, false //text mute
);
}
}
}
#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>();
queue.ChatterBoxSessionAgentListUpdates(
GroupID
, AgentID
, new UUID(im.toAgentID)
, false //canVoiceChat
, false //isModerator
, false //text mute
);
}
}
// 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>();
if (queue != null)
{
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

View File

@ -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
}
}

View File

@ -0,0 +1,707 @@
/*
* 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 RequestingAgentID, string search)
{
return m_LocalGroupsConnector.FindGroups(AgentUUI(RequestingAgentID), 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;
try
{
AgentID = new UUID(AgentIDStr);
}
catch (FormatException)
{
return AgentID.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;
try
{
AgentID = new UUID(AgentIDStr);
}
catch (FormatException)
{
return AgentID.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
}
}

View File

@ -0,0 +1,444 @@
/*
* 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)
{
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");
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
}
}

View File

@ -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 RequestingAgentID, string search);
List<GroupMembersData> GetGroupMembers(string RequestingAgentID, UUID GroupID);
bool AddGroupRole(string RequestingAgentID, UUID groupID, UUID roleID, string name, string description, string title, ulong powers, out string reason);
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;
}
}

View File

@ -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 RequestingAgentID, string search)
{
return m_GroupsService.FindGroups(RequestingAgentID, 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
}
}

View File

@ -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("0.8.2.*")]
[assembly: Addin("OpenSim.Groups", OpenSim.VersionInfo.VersionNumber)]
[assembly: AddinDependency("OpenSim.Region.Framework", OpenSim.VersionInfo.VersionNumber)]

View File

@ -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 RequestingAgentID, 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"] = RequestingAgentID;
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
}
}

View File

@ -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 RequestingAgentID, string search)
{
// TODO!
return m_GroupsService.FindGroups(RequestingAgentID, 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
}
}

View File

@ -0,0 +1,816 @@
/*
* 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)
{
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");
// 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.", 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
}
}

View File

@ -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

View File

@ -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);
}
}
}

View File

@ -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;
}
}
}

View File

@ -0,0 +1,268 @@
/*
* 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;
client.OnMuteListRequest -= OnMuteListRequest;
});
}
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;
client.OnMuteListRequest += OnMuteListRequest;
}
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);
}
}
}
// Apparently this is needed in order for the viewer to request the IMs.
private void OnMuteListRequest(IClientAPI client, uint crc)
{
m_log.DebugFormat("[OfflineIM.V2] Got mute list request for crc {0}", crc);
string filename = "mutes" + client.AgentId.ToString();
IXfer xfer = client.Scene.RequestModuleInterface<IXfer>();
if (xfer != null)
{
xfer.AddNewFile(filename, new Byte[0]);
client.SendMuteListUpdate(filename);
}
}
private void UndeliveredMessage(GridInstantMessage im)
{
if (im.dialog != (byte)InstantMessageDialog.MessageFromObject &&
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
}
}

View File

@ -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("0.8.2.*")]
[assembly: Addin("OpenSim.OfflineIM", OpenSim.VersionInfo.VersionNumber)]
[assembly: AddinDependency("OpenSim.Region.Framework", OpenSim.VersionInfo.VersionNumber)]

View File

@ -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
}
}

View File

@ -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
}
}

View File

@ -0,0 +1,135 @@
/*
* 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());
}
}
}

View File

@ -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);
}
}
}

View File

@ -0,0 +1,210 @@
/*
* 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.Framework.RegionLoader.Filesystem;
using OpenSim.Framework.RegionLoader.Web;
using OpenSim.Region.CoreModules.Agent.AssetTransaction;
using OpenSim.Region.CoreModules.Avatar.InstantMessage;
using OpenSim.Region.CoreModules.Scripting.DynamicTexture;
using OpenSim.Region.CoreModules.Scripting.LoadImageURL;
using OpenSim.Region.CoreModules.Scripting.XMLRPC;
using OpenSim.Services.Interfaces;
using Mono.Addins;
namespace OpenSim.ApplicationPlugins.LoadRegions
{
[Extension(Path="/OpenSim/Startup", Id="LoadRegions", NodeName="Plugin")]
public class LoadRegionsPlugin : IApplicationPlugin, IRegionCreator
{
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
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;
}
}
}

View File

@ -0,0 +1,69 @@
/*
* 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("0.7.6.*")]
[assembly : AssemblyVersion("0.8.2.*")]
[assembly: Addin("OpenSim.ApplicationPlugins.LoadRegions", OpenSim.VersionInfo.VersionNumber)]
[assembly: AddinDependency("OpenSim", OpenSim.VersionInfo.VersionNumber)]

View File

@ -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("0.8.2.*")]
[assembly: Addin("OpenSim.ApplicationPlugins.RegionModulesController", OpenSim.VersionInfo.VersionNumber)]
[assembly: AddinDependency("OpenSim", OpenSim.VersionInfo.VersionNumber)]

View File

@ -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 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);
}
}
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
}
}

View File

@ -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("0.8.2.*")]
[assembly: Addin("OpenSim.ApplicationPlugins.RemoteController", OpenSim.VersionInfo.VersionNumber)]
[assembly: AddinDependency("OpenSim", OpenSim.VersionInfo.VersionNumber)]

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,259 @@
/*
* 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.Reflection;
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
{
// 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 Dictionary<string, PollServiceEventArgs> m_pollServiceHandlers
= new Dictionary<string, PollServiceEventArgs>();
private Dictionary<string, string> m_externalCapsHandlers = new Dictionary<string, string>();
private IHttpServer m_httpListener;
private UUID m_agentID;
private string m_regionName;
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; }
}
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, (httpServer == null) ? false : httpServer.UseSSL);
m_regionName = regionName;
}
/// <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 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);
m_pollServiceHandlers.Add(capName, pollServiceHandler);
m_httpListener.AddPollServiceHTTPHandler(pollServiceHandler.Url, pollServiceHandler);
// uint port = (MainServer.Instance == null) ? 0 : MainServer.Instance.Port;
// string protocol = "http";
// string hostName = m_httpListenerHostName;
//
// if (MainServer.Instance.UseSSL)
// {
// hostName = MainServer.Instance.SSLCommonName;
// 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);
}
}
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.RegisterHandler("FetchInventoryDescendents2", String.Format("{0}://{1}:{2}{3}", protocol, hostName, port, capUrl));
caps[kvp.Key] = string.Format("{0}://{1}:{2}{3}", protocol, hostName, port, kvp.Value.Url);
}
}
// Add the external too
foreach (KeyValuePair<string, string> kvp in ExternalCapsHandlers)
{
if (!requestedCaps.Contains(kvp.Key))
continue;
caps[kvp.Key] = kvp.Value;
}
return caps;
}
}
}

View File

@ -0,0 +1,200 @@
/*
* 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 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 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(BaseHttpServer httpListener, string httpListenerHostname, uint httpListenerPort)
: this(httpListener,httpListenerHostname,httpListenerPort, false)
{
}
/// <summary></summary>
/// CapsHandlers is a cap handler container but also takes
/// care of adding and removing cap handlers to and from the
/// supplied BaseHttpServer.
/// </summary>
/// <param name="httpListener">base HTTP server</param>
/// <param name="httpListenerHostname">host name of the HTTP
/// server</param>
/// <param name="httpListenerPort">HTTP port</param>
public CapsHandlers(IHttpServer httpListener, string httpListenerHostname, uint httpListenerPort, bool https)
{
m_httpListener = httpListener;
m_httpListenerHostName = httpListenerHostname;
m_httpListenerPort = httpListenerPort;
m_useSSL = https;
if (httpListener != null && m_useSSL)
{
m_httpListenerHostName = httpListener.SSLCommonName;
m_httpListenerPort = httpListener.SSLPort;
}
}
/// <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)
{
m_httpListener.RemoveStreamHandler("POST", m_capsHandlers[capsName].Path);
m_httpListener.RemoveStreamHandler("GET", m_capsHandlers[capsName].Path);
m_capsHandlers.Remove(capsName);
}
}
public bool ContainsCap(string cap)
{
lock (m_capsHandlers)
return m_capsHandlers.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_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_capsHandlers.Keys.CopyTo(__keys, 0);
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 = "http://";
if (m_useSSL)
protocol = "https://";
string baseUrl = protocol + m_httpListenerHostName + ":" + m_httpListenerPort.ToString();
lock (m_capsHandlers)
{
foreach (string capsName in m_capsHandlers.Keys)
{
if (excludeSeed && "SEED" == capsName)
continue;
if (requestedCaps != null && !requestedCaps.Contains(capsName))
continue;
caps[capsName] = baseUrl + m_capsHandlers[capsName].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);
}
}
}

View File

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

View File

@ -0,0 +1,848 @@
/*
* 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.Linq;
using System.Reflection;
using log4net;
using Nini.Config;
using OpenMetaverse;
using OpenMetaverse.StructuredData;
using OpenSim.Framework;
using OpenSim.Framework.Capabilities;
using OpenSim.Region.Framework.Interfaces;
using OpenSim.Framework.Servers.HttpServer;
using OpenSim.Services.Interfaces;
using Caps = OpenSim.Framework.Capabilities.Caps;
namespace OpenSim.Capabilities.Handlers
{
public class FetchInvDescHandler
{
private static readonly ILog m_log =
LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private IInventoryService m_InventoryService;
private ILibraryService m_LibraryService;
private IScene m_Scene;
// private object m_fetchLock = new Object();
public FetchInvDescHandler(IInventoryService invService, ILibraryService libService, IScene s)
{
m_InventoryService = invService;
m_LibraryService = libService;
m_Scene = s;
}
public string FetchInventoryDescendentsRequest(string request, string path, string param, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
{
//m_log.DebugFormat("[XXX]: FetchInventoryDescendentsRequest in {0}, {1}", (m_Scene == null) ? "none" : m_Scene.Name, request);
// nasty temporary hack here, the linden client falsely
// identifies the uuid 00000000-0000-0000-0000-000000000000
// as a string which breaks us
//
// correctly mark it as a uuid
//
request = request.Replace("<string>00000000-0000-0000-0000-000000000000</string>", "<uuid>00000000-0000-0000-0000-000000000000</uuid>");
// another hack <integer>1</integer> results in a
// System.ArgumentException: Object type System.Int32 cannot
// be converted to target type: System.Boolean
//
request = request.Replace("<key>fetch_folders</key><integer>0</integer>", "<key>fetch_folders</key><boolean>0</boolean>");
request = request.Replace("<key>fetch_folders</key><integer>1</integer>", "<key>fetch_folders</key><boolean>1</boolean>");
Hashtable hash = new Hashtable();
try
{
hash = (Hashtable)LLSD.LLSDDeserialize(Utils.StringToBytes(request));
}
catch (LLSD.LLSDParseException e)
{
m_log.ErrorFormat("[WEB FETCH INV DESC HANDLER]: Fetch error: {0}{1}" + e.Message, e.StackTrace);
m_log.Error("Request: " + request);
}
ArrayList foldersrequested = (ArrayList)hash["folders"];
string response = "";
string bad_folders_response = "";
List<LLSDFetchInventoryDescendents> folders = new List<LLSDFetchInventoryDescendents>();
for (int i = 0; i < foldersrequested.Count; i++)
{
Hashtable inventoryhash = (Hashtable)foldersrequested[i];
LLSDFetchInventoryDescendents llsdRequest = new LLSDFetchInventoryDescendents();
try
{
LLSDHelpers.DeserialiseOSDMap(inventoryhash, llsdRequest);
}
catch (Exception e)
{
m_log.Debug("[WEB FETCH INV DESC HANDLER]: caught exception doing OSD deserialize" + e);
continue;
}
// Filter duplicate folder ids that bad viewers may send
if (folders.Find(f => f.folder_id == llsdRequest.folder_id) == null)
folders.Add(llsdRequest);
}
if (folders.Count > 0)
{
List<UUID> bad_folders = new List<UUID>();
List<InventoryCollectionWithDescendents> invcollSet = Fetch(folders, bad_folders);
//m_log.DebugFormat("[XXX]: Got {0} folders from a request of {1}", invcollSet.Count, folders.Count);
if (invcollSet == null)
{
m_log.DebugFormat("[WEB FETCH INV DESC HANDLER]: Multiple folder fetch failed. Trying old protocol.");
#pragma warning disable 0612
return FetchInventoryDescendentsRequest(foldersrequested, httpRequest, httpResponse);
#pragma warning restore 0612
}
string inventoryitemstr = string.Empty;
foreach (InventoryCollectionWithDescendents icoll in invcollSet)
{
LLSDInventoryDescendents reply = ToLLSD(icoll.Collection, icoll.Descendents);
inventoryitemstr = LLSDHelpers.SerialiseLLSDReply(reply);
inventoryitemstr = inventoryitemstr.Replace("<llsd><map><key>folders</key><array>", "");
inventoryitemstr = inventoryitemstr.Replace("</array></map></llsd>", "");
response += inventoryitemstr;
}
//m_log.DebugFormat("[WEB FETCH INV DESC HANDLER]: Bad folders {0}", string.Join(", ", bad_folders));
foreach (UUID bad in bad_folders)
bad_folders_response += "<uuid>" + bad + "</uuid>";
}
if (response.Length == 0)
{
/* Viewers expect a bad_folders array when not available */
if (bad_folders_response.Length != 0)
{
response = "<llsd><map><key>bad_folders</key><array>" + bad_folders_response + "</array></map></llsd>";
}
else
{
response = "<llsd><map><key>folders</key><array /></map></llsd>";
}
}
else
{
if (bad_folders_response.Length != 0)
{
response = "<llsd><map><key>folders</key><array>" + response + "</array><key>bad_folders</key><array>" + bad_folders_response + "</array></map></llsd>";
}
else
{
response = "<llsd><map><key>folders</key><array>" + response + "</array></map></llsd>";
}
}
//m_log.DebugFormat("[WEB FETCH INV DESC HANDLER]: Replying to CAPS fetch inventory request for {0} folders. Item count {1}", folders.Count, item_count);
//m_log.Debug("[WEB FETCH INV DESC HANDLER] " + response);
return response;
}
/// <summary>
/// Construct an LLSD reply packet to a CAPS inventory request
/// </summary>
/// <param name="invFetch"></param>
/// <returns></returns>
private LLSDInventoryDescendents FetchInventoryReply(LLSDFetchInventoryDescendents invFetch)
{
LLSDInventoryDescendents reply = new LLSDInventoryDescendents();
LLSDInventoryFolderContents contents = new LLSDInventoryFolderContents();
contents.agent_id = invFetch.owner_id;
contents.owner_id = invFetch.owner_id;
contents.folder_id = invFetch.folder_id;
reply.folders.Array.Add(contents);
InventoryCollection inv = new InventoryCollection();
inv.Folders = new List<InventoryFolderBase>();
inv.Items = new List<InventoryItemBase>();
int version = 0;
int descendents = 0;
#pragma warning disable 0612
inv = Fetch(
invFetch.owner_id, invFetch.folder_id, invFetch.owner_id,
invFetch.fetch_folders, invFetch.fetch_items, invFetch.sort_order, out version, out descendents);
#pragma warning restore 0612
if (inv != null && inv.Folders != null)
{
foreach (InventoryFolderBase invFolder in inv.Folders)
{
contents.categories.Array.Add(ConvertInventoryFolder(invFolder));
}
descendents += inv.Folders.Count;
}
if (inv != null && inv.Items != null)
{
foreach (InventoryItemBase invItem in inv.Items)
{
contents.items.Array.Add(ConvertInventoryItem(invItem));
}
}
contents.descendents = descendents;
contents.version = version;
//m_log.DebugFormat(
// "[WEB FETCH INV DESC HANDLER]: Replying to request for folder {0} (fetch items {1}, fetch folders {2}) with {3} items and {4} folders for agent {5}",
// invFetch.folder_id,
// invFetch.fetch_items,
// invFetch.fetch_folders,
// contents.items.Array.Count,
// contents.categories.Array.Count,
// invFetch.owner_id);
return reply;
}
private LLSDInventoryDescendents ToLLSD(InventoryCollection inv, int descendents)
{
LLSDInventoryDescendents reply = new LLSDInventoryDescendents();
LLSDInventoryFolderContents contents = new LLSDInventoryFolderContents();
contents.agent_id = inv.OwnerID;
contents.owner_id = inv.OwnerID;
contents.folder_id = inv.FolderID;
reply.folders.Array.Add(contents);
if (inv.Folders != null)
{
foreach (InventoryFolderBase invFolder in inv.Folders)
{
contents.categories.Array.Add(ConvertInventoryFolder(invFolder));
}
descendents += inv.Folders.Count;
}
if (inv.Items != null)
{
foreach (InventoryItemBase invItem in inv.Items)
{
contents.items.Array.Add(ConvertInventoryItem(invItem));
}
}
contents.descendents = descendents;
contents.version = inv.Version;
return reply;
}
/// <summary>
/// Old style. Soon to be deprecated.
/// </summary>
/// <param name="request"></param>
/// <param name="httpRequest"></param>
/// <param name="httpResponse"></param>
/// <returns></returns>
[Obsolete]
private string FetchInventoryDescendentsRequest(ArrayList foldersrequested, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
{
//m_log.DebugFormat("[WEB FETCH INV DESC HANDLER]: Received request for {0} folders", foldersrequested.Count);
string response = "";
string bad_folders_response = "";
for (int i = 0; i < foldersrequested.Count; i++)
{
string inventoryitemstr = "";
Hashtable inventoryhash = (Hashtable)foldersrequested[i];
LLSDFetchInventoryDescendents llsdRequest = new LLSDFetchInventoryDescendents();
try
{
LLSDHelpers.DeserialiseOSDMap(inventoryhash, llsdRequest);
}
catch (Exception e)
{
m_log.Debug("[WEB FETCH INV DESC HANDLER]: caught exception doing OSD deserialize" + e);
}
LLSDInventoryDescendents reply = FetchInventoryReply(llsdRequest);
if (null == reply)
{
bad_folders_response += "<uuid>" + llsdRequest.folder_id.ToString() + "</uuid>";
}
else
{
inventoryitemstr = LLSDHelpers.SerialiseLLSDReply(reply);
inventoryitemstr = inventoryitemstr.Replace("<llsd><map><key>folders</key><array>", "");
inventoryitemstr = inventoryitemstr.Replace("</array></map></llsd>", "");
}
response += inventoryitemstr;
}
if (response.Length == 0)
{
/* Viewers expect a bad_folders array when not available */
if (bad_folders_response.Length != 0)
{
response = "<llsd><map><key>bad_folders</key><array>" + bad_folders_response + "</array></map></llsd>";
}
else
{
response = "<llsd><map><key>folders</key><array /></map></llsd>";
}
}
else
{
if (bad_folders_response.Length != 0)
{
response = "<llsd><map><key>folders</key><array>" + response + "</array><key>bad_folders</key><array>" + bad_folders_response + "</array></map></llsd>";
}
else
{
response = "<llsd><map><key>folders</key><array>" + response + "</array></map></llsd>";
}
}
// m_log.DebugFormat("[WEB FETCH INV DESC HANDLER]: Replying to CAPS fetch inventory request");
//m_log.Debug("[WEB FETCH INV DESC HANDLER] "+response);
return response;
// }
}
/// <summary>
/// Handle the caps inventory descendents fetch.
/// </summary>
/// <param name="agentID"></param>
/// <param name="folderID"></param>
/// <param name="ownerID"></param>
/// <param name="fetchFolders"></param>
/// <param name="fetchItems"></param>
/// <param name="sortOrder"></param>
/// <param name="version"></param>
/// <returns>An empty InventoryCollection if the inventory look up failed</returns>
[Obsolete]
private InventoryCollection Fetch(
UUID agentID, UUID folderID, UUID ownerID,
bool fetchFolders, bool fetchItems, int sortOrder, out int version, out int descendents)
{
//m_log.DebugFormat(
// "[WEB FETCH INV DESC HANDLER]: Fetching folders ({0}), items ({1}) from {2} for agent {3}",
// fetchFolders, fetchItems, folderID, agentID);
// FIXME MAYBE: We're not handling sortOrder!
version = 0;
descendents = 0;
InventoryFolderImpl fold;
if (m_LibraryService != null && m_LibraryService.LibraryRootFolder != null && agentID == m_LibraryService.LibraryRootFolder.Owner)
{
if ((fold = m_LibraryService.LibraryRootFolder.FindFolder(folderID)) != null)
{
InventoryCollection ret = new InventoryCollection();
ret.Folders = new List<InventoryFolderBase>();
ret.Items = fold.RequestListOfItems();
descendents = ret.Folders.Count + ret.Items.Count;
return ret;
}
}
InventoryCollection contents = new InventoryCollection();
if (folderID != UUID.Zero)
{
InventoryCollection fetchedContents = m_InventoryService.GetFolderContent(agentID, folderID);
if (fetchedContents == null)
{
m_log.WarnFormat("[WEB FETCH INV DESC HANDLER]: Could not get contents of folder {0} for user {1}", folderID, agentID);
return contents;
}
contents = fetchedContents;
InventoryFolderBase containingFolder = new InventoryFolderBase();
containingFolder.ID = folderID;
containingFolder.Owner = agentID;
containingFolder = m_InventoryService.GetFolder(containingFolder);
if (containingFolder != null)
{
//m_log.DebugFormat(
// "[WEB FETCH INV DESC HANDLER]: Retrieved folder {0} {1} for agent id {2}",
// containingFolder.Name, containingFolder.ID, agentID);
version = containingFolder.Version;
if (fetchItems)
{
List<InventoryItemBase> itemsToReturn = contents.Items;
List<InventoryItemBase> originalItems = new List<InventoryItemBase>(itemsToReturn);
// descendents must only include the links, not the linked items we add
descendents = originalItems.Count;
// Add target items for links in this folder before the links themselves.
foreach (InventoryItemBase item in originalItems)
{
if (item.AssetType == (int)AssetType.Link)
{
InventoryItemBase linkedItem = m_InventoryService.GetItem(new InventoryItemBase(item.AssetID));
// Take care of genuinely broken links where the target doesn't exist
// HACK: Also, don't follow up links that just point to other links. In theory this is legitimate,
// but no viewer has been observed to set these up and this is the lazy way of avoiding cycles
// rather than having to keep track of every folder requested in the recursion.
if (linkedItem != null && linkedItem.AssetType != (int)AssetType.Link)
itemsToReturn.Insert(0, linkedItem);
}
}
// Now scan for folder links and insert the items they target and those links at the head of the return data
foreach (InventoryItemBase item in originalItems)
{
if (item.AssetType == (int)AssetType.LinkFolder)
{
InventoryCollection linkedFolderContents = m_InventoryService.GetFolderContent(ownerID, item.AssetID);
List<InventoryItemBase> links = linkedFolderContents.Items;
itemsToReturn.InsertRange(0, links);
foreach (InventoryItemBase link in linkedFolderContents.Items)
{
// Take care of genuinely broken links where the target doesn't exist
// HACK: Also, don't follow up links that just point to other links. In theory this is legitimate,
// but no viewer has been observed to set these up and this is the lazy way of avoiding cycles
// rather than having to keep track of every folder requested in the recursion.
if (link != null)
{
// m_log.DebugFormat(
// "[WEB FETCH INV DESC HANDLER]: Adding item {0} {1} from folder {2} linked from {3}",
// link.Name, (AssetType)link.AssetType, item.AssetID, containingFolder.Name);
InventoryItemBase linkedItem
= m_InventoryService.GetItem(new InventoryItemBase(link.AssetID));
if (linkedItem != null)
itemsToReturn.Insert(0, linkedItem);
}
}
}
}
}
// foreach (InventoryItemBase item in contents.Items)
// {
// m_log.DebugFormat(
// "[WEB FETCH INV DESC HANDLER]: Returning item {0}, type {1}, parent {2} in {3} {4}",
// item.Name, (AssetType)item.AssetType, item.Folder, containingFolder.Name, containingFolder.ID);
// }
// =====
//
// foreach (InventoryItemBase linkedItem in linkedItemsToAdd)
// {
// m_log.DebugFormat(
// "[WEB FETCH INV DESC HANDLER]: Inserted linked item {0} for link in folder {1} for agent {2}",
// linkedItem.Name, folderID, agentID);
//
// contents.Items.Add(linkedItem);
// }
//
// // If the folder requested contains links, then we need to send those folders first, otherwise the links
// // will be broken in the viewer.
// HashSet<UUID> linkedItemFolderIdsToSend = new HashSet<UUID>();
// foreach (InventoryItemBase item in contents.Items)
// {
// if (item.AssetType == (int)AssetType.Link)
// {
// InventoryItemBase linkedItem = m_InventoryService.GetItem(new InventoryItemBase(item.AssetID));
//
// // Take care of genuinely broken links where the target doesn't exist
// // HACK: Also, don't follow up links that just point to other links. In theory this is legitimate,
// // but no viewer has been observed to set these up and this is the lazy way of avoiding cycles
// // rather than having to keep track of every folder requested in the recursion.
// if (linkedItem != null && linkedItem.AssetType != (int)AssetType.Link)
// {
// // We don't need to send the folder if source and destination of the link are in the same
// // folder.
// if (linkedItem.Folder != containingFolder.ID)
// linkedItemFolderIdsToSend.Add(linkedItem.Folder);
// }
// }
// }
//
// foreach (UUID linkedItemFolderId in linkedItemFolderIdsToSend)
// {
// m_log.DebugFormat(
// "[WEB FETCH INV DESC HANDLER]: Recursively fetching folder {0} linked by item in folder {1} for agent {2}",
// linkedItemFolderId, folderID, agentID);
//
// int dummyVersion;
// InventoryCollection linkedCollection
// = Fetch(
// agentID, linkedItemFolderId, ownerID, fetchFolders, fetchItems, sortOrder, out dummyVersion);
//
// InventoryFolderBase linkedFolder = new InventoryFolderBase(linkedItemFolderId);
// linkedFolder.Owner = agentID;
// linkedFolder = m_InventoryService.GetFolder(linkedFolder);
//
//// contents.Folders.AddRange(linkedCollection.Folders);
//
// contents.Folders.Add(linkedFolder);
// contents.Items.AddRange(linkedCollection.Items);
// }
// }
}
}
else
{
// Lost items don't really need a version
version = 1;
}
return contents;
}
private void AddLibraryFolders(List<LLSDFetchInventoryDescendents> fetchFolders, List<InventoryCollectionWithDescendents> result)
{
InventoryFolderImpl fold;
if (m_LibraryService != null && m_LibraryService.LibraryRootFolder != null)
{
List<LLSDFetchInventoryDescendents> libfolders = fetchFolders.FindAll(f => f.owner_id == m_LibraryService.LibraryRootFolder.Owner);
fetchFolders.RemoveAll(f => libfolders.Contains(f));
//m_log.DebugFormat("[XXX]: Found {0} library folders in request", libfolders.Count);
foreach (LLSDFetchInventoryDescendents f in libfolders)
{
if ((fold = m_LibraryService.LibraryRootFolder.FindFolder(f.folder_id)) != null)
{
InventoryCollectionWithDescendents ret = new InventoryCollectionWithDescendents();
ret.Collection = new InventoryCollection();
ret.Collection.Folders = new List<InventoryFolderBase>();
ret.Collection.Items = fold.RequestListOfItems();
ret.Collection.OwnerID = m_LibraryService.LibraryRootFolder.Owner;
ret.Collection.FolderID = f.folder_id;
ret.Collection.Version = fold.Version;
ret.Descendents = ret.Collection.Items.Count;
result.Add(ret);
//m_log.DebugFormat("[XXX]: Added libfolder {0} ({1}) {2}", ret.Collection.FolderID, ret.Collection.OwnerID);
}
}
}
}
private List<InventoryCollectionWithDescendents> Fetch(List<LLSDFetchInventoryDescendents> fetchFolders, List<UUID> bad_folders)
{
//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<InventoryCollectionWithDescendents> result = new List<InventoryCollectionWithDescendents>();
AddLibraryFolders(fetchFolders, result);
// 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)
LLSDFetchInventoryDescendents zero = fetchFolders.Find(f => f.folder_id == UUID.Zero);
if (zero != null)
{
fetchFolders.Remove(zero);
BadFolder(zero, null, bad_folders);
}
if (fetchFolders.Count > 0)
{
UUID[] fids = new UUID[fetchFolders.Count];
int i = 0;
foreach (LLSDFetchInventoryDescendents f in fetchFolders)
fids[i++] = f.folder_id;
//m_log.DebugFormat("[XXX]: {0}", string.Join(",", fids));
InventoryCollection[] fetchedContents = m_InventoryService.GetMultipleFoldersContent(fetchFolders[0].owner_id, fids);
if (fetchedContents == null || (fetchedContents != null && fetchedContents.Length == 0))
{
m_log.WarnFormat("[WEB FETCH INV DESC HANDLER]: Could not get contents of multiple folders for user {0}", fetchFolders[0].owner_id);
foreach (LLSDFetchInventoryDescendents freq in fetchFolders)
BadFolder(freq, null, bad_folders);
return null;
}
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 = fetchFolders[i++];
InventoryCollectionWithDescendents coll = new InventoryCollectionWithDescendents();
coll.Collection = contents;
if (BadFolder(freq, contents, bad_folders))
continue;
// Next: link management
ProcessLinks(freq, coll);
result.Add(coll);
}
}
return result;
}
private bool BadFolder(LLSDFetchInventoryDescendents freq, InventoryCollection contents, List<UUID> bad_folders)
{
bool bad = false;
if (contents == null)
{
bad_folders.Add(freq.folder_id);
bad = true;
}
// The inventory server isn't sending FolderID in the collection...
// Must fetch it individually
else if (contents.FolderID == UUID.Zero)
{
InventoryFolderBase containingFolder = new InventoryFolderBase();
containingFolder.ID = freq.folder_id;
containingFolder.Owner = freq.owner_id;
containingFolder = m_InventoryService.GetFolder(containingFolder);
if (containingFolder != null)
{
contents.FolderID = containingFolder.ID;
contents.OwnerID = containingFolder.Owner;
contents.Version = containingFolder.Version;
}
else
{
// Was it really a request for folder Zero?
// This is an overkill, but Firestorm really asks for folder Zero.
// I'm leaving the code here for the time being, but commented.
if (freq.folder_id == UUID.Zero)
{
//coll.Collection.OwnerID = freq.owner_id;
//coll.Collection.FolderID = contents.FolderID;
//containingFolder = m_InventoryService.GetRootFolder(freq.owner_id);
//if (containingFolder != null)
//{
// m_log.WarnFormat("[WEB FETCH INV DESC HANDLER]: Request for parent of folder {0}", containingFolder.ID);
// coll.Collection.Folders.Clear();
// coll.Collection.Folders.Add(containingFolder);
// if (m_LibraryService != null && m_LibraryService.LibraryRootFolder != null)
// {
// InventoryFolderBase lib = new InventoryFolderBase(m_LibraryService.LibraryRootFolder.ID, m_LibraryService.LibraryRootFolder.Owner);
// lib.Name = m_LibraryService.LibraryRootFolder.Name;
// lib.Type = m_LibraryService.LibraryRootFolder.Type;
// lib.Version = m_LibraryService.LibraryRootFolder.Version;
// coll.Collection.Folders.Add(lib);
// }
// coll.Collection.Items.Clear();
//}
}
else
{
m_log.WarnFormat("[WEB FETCH INV DESC HANDLER]: Unable to fetch folder {0}", freq.folder_id);
bad_folders.Add(freq.folder_id);
}
bad = true;
}
}
return bad;
}
private void ProcessLinks(LLSDFetchInventoryDescendents freq, InventoryCollectionWithDescendents coll)
{
InventoryCollection contents = coll.Collection;
if (freq.fetch_items && contents.Items != null)
{
List<InventoryItemBase> itemsToReturn = contents.Items;
// descendents must only include the links, not the linked items we add
coll.Descendents = itemsToReturn.Count;
// Add target items for links in this folder before the links themselves.
List<UUID> itemIDs = new List<UUID>();
List<UUID> folderIDs = new List<UUID>();
foreach (InventoryItemBase item in itemsToReturn)
{
//m_log.DebugFormat("[XXX]: {0} {1}", item.Name, item.AssetType);
if (item.AssetType == (int)AssetType.Link)
itemIDs.Add(item.AssetID);
else if (item.AssetType == (int)AssetType.LinkFolder)
folderIDs.Add(item.AssetID);
}
//m_log.DebugFormat("[XXX]: folder {0} has {1} links and {2} linkfolders", contents.FolderID, itemIDs.Count, folderIDs.Count);
// Scan for folder links and insert the items they target and those links at the head of the return data
if (folderIDs.Count > 0)
{
InventoryCollection[] linkedFolders = m_InventoryService.GetMultipleFoldersContent(coll.Collection.OwnerID, folderIDs.ToArray());
foreach (InventoryCollection linkedFolderContents in linkedFolders)
{
if (linkedFolderContents == null)
continue;
List<InventoryItemBase> links = linkedFolderContents.Items;
itemsToReturn.InsertRange(0, links);
}
}
if (itemIDs.Count > 0)
{
InventoryItemBase[] linked = m_InventoryService.GetMultipleItems(freq.owner_id, itemIDs.ToArray());
if (linked == null)
{
// OMG!!! One by one!!! This is fallback code, in case the backend isn't updated
m_log.WarnFormat("[WEB FETCH INV DESC HANDLER]: GetMultipleItems failed. Falling back to fetching inventory items one by one.");
linked = new InventoryItemBase[itemIDs.Count];
int i = 0;
InventoryItemBase item = new InventoryItemBase();
item.Owner = freq.owner_id;
foreach (UUID id in itemIDs)
{
item.ID = id;
linked[i++] = m_InventoryService.GetItem(item);
}
}
//m_log.DebugFormat("[WEB FETCH INV DESC HANDLER]: Processing folder {0}. Existing items:", freq.folder_id);
//foreach (InventoryItemBase item in itemsToReturn)
// m_log.DebugFormat("[XXX]: {0} {1} {2}", item.Name, item.AssetType, item.Folder);
if (linked != null)
{
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)
{
itemsToReturn.Insert(0, linkedItem);
//m_log.DebugFormat("[WEB FETCH INV DESC HANDLER]: Added {0} {1} {2}", linkedItem.Name, linkedItem.AssetType, linkedItem.Folder);
}
}
}
}
}
}
/// <summary>
/// Convert an internal inventory folder object into an LLSD object.
/// </summary>
/// <param name="invFolder"></param>
/// <returns></returns>
private LLSDInventoryFolder ConvertInventoryFolder(InventoryFolderBase invFolder)
{
LLSDInventoryFolder llsdFolder = new LLSDInventoryFolder();
llsdFolder.folder_id = invFolder.ID;
llsdFolder.parent_id = invFolder.ParentID;
llsdFolder.name = invFolder.Name;
llsdFolder.type = invFolder.Type;
llsdFolder.preferred_type = -1;
return llsdFolder;
}
/// <summary>
/// Convert an internal inventory item object into an LLSD object.
/// </summary>
/// <param name="invItem"></param>
/// <returns></returns>
private LLSDInventoryItem ConvertInventoryItem(InventoryItemBase invItem)
{
LLSDInventoryItem llsdItem = new LLSDInventoryItem();
llsdItem.asset_id = invItem.AssetID;
llsdItem.created_at = invItem.CreationDate;
llsdItem.desc = invItem.Description;
llsdItem.flags = (int)invItem.Flags;
llsdItem.item_id = invItem.ID;
llsdItem.name = invItem.Name;
llsdItem.parent_id = invItem.Folder;
llsdItem.type = invItem.AssetType;
llsdItem.inv_type = invItem.InvType;
llsdItem.permissions = new LLSDPermissions();
llsdItem.permissions.creator_id = invItem.CreatorIdAsUuid;
llsdItem.permissions.base_mask = (int)invItem.CurrentPermissions;
llsdItem.permissions.everyone_mask = (int)invItem.EveryOnePermissions;
llsdItem.permissions.group_id = invItem.GroupID;
llsdItem.permissions.group_mask = (int)invItem.GroupPermissions;
llsdItem.permissions.is_owner_group = invItem.GroupOwned;
llsdItem.permissions.next_owner_mask = (int)invItem.NextPermissions;
llsdItem.permissions.owner_id = invItem.Owner;
llsdItem.permissions.owner_mask = (int)invItem.CurrentPermissions;
llsdItem.sale_info = new LLSDSaleInfo();
llsdItem.sale_info.sale_price = invItem.SalePrice;
llsdItem.sale_info.sale_type = invItem.SaleType;
return llsdItem;
}
}
class InventoryCollectionWithDescendents
{
public InventoryCollection Collection;
public int Descendents;
}
}

View File

@ -0,0 +1,82 @@
/*
* 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 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);
FetchInvDescHandler webFetchHandler = new FetchInvDescHandler(m_InventoryService, m_LibraryService, null);
IRequestHandler reqHandler
= new RestStreamHandler(
"POST",
"/CAPS/WebFetchInvDesc/" /*+ UUID.Random()*/,
webFetchHandler.FetchInventoryDescendentsRequest,
"FetchInvDescendents",
null);
server.AddStreamHandler(reqHandler);
}
}
}

View File

@ -0,0 +1,141 @@
/*
* 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 OpenMetaverse;
using OpenMetaverse.StructuredData;
using OpenSim.Framework;
using OpenSim.Framework.Capabilities;
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"];
string reply;
LLSDFetchInventory llsdReply = new LLSDFetchInventory();
UUID[] itemIDs = new UUID[itemsRequested.Count];
int i = 0;
foreach (OSDMap osdItemId in itemsRequested)
{
itemIDs[i++] = osdItemId["item_id"].AsUUID();
}
InventoryItemBase[] items = m_inventoryService.GetMultipleItems(m_agentID, itemIDs);
if (items == null)
{
// OMG!!! One by one!!! This is fallback code, in case the backend isn't updated
m_log.WarnFormat("[FETCH INVENTORY HANDLER]: GetMultipleItems failed. Falling back to fetching inventory items one by one.");
items = new InventoryItemBase[itemsRequested.Count];
i = 0;
InventoryItemBase item = new InventoryItemBase();
item.Owner = m_agentID;
foreach (UUID id in itemIDs)
{
item.ID = id;
items[i++] = m_inventoryService.GetItem(item);
}
}
foreach (InventoryItemBase item in items)
{
if (item != null)
{
// We don't know the agent that this request belongs to so we'll use the agent id of the item
// which will be the same for all items.
llsdReply.agent_id = item.Owner;
llsdReply.items.Array.Add(ConvertInventoryItem(item));
}
}
reply = LLSDHelpers.SerialiseLLSDReply(llsdReply);
return reply;
}
/// <summary>
/// Convert an internal inventory item object into an LLSD object.
/// </summary>
/// <param name="invItem"></param>
/// <returns></returns>
private LLSDInventoryItem ConvertInventoryItem(InventoryItemBase invItem)
{
LLSDInventoryItem llsdItem = new LLSDInventoryItem();
llsdItem.asset_id = invItem.AssetID;
llsdItem.created_at = invItem.CreationDate;
llsdItem.desc = invItem.Description;
llsdItem.flags = (int)invItem.Flags;
llsdItem.item_id = invItem.ID;
llsdItem.name = invItem.Name;
llsdItem.parent_id = invItem.Folder;
llsdItem.type = invItem.AssetType;
llsdItem.inv_type = invItem.InvType;
llsdItem.permissions = new LLSDPermissions();
llsdItem.permissions.creator_id = invItem.CreatorIdAsUuid;
llsdItem.permissions.base_mask = (int)invItem.CurrentPermissions;
llsdItem.permissions.everyone_mask = (int)invItem.EveryOnePermissions;
llsdItem.permissions.group_id = invItem.GroupID;
llsdItem.permissions.group_mask = (int)invItem.GroupPermissions;
llsdItem.permissions.is_owner_group = invItem.GroupOwned;
llsdItem.permissions.next_owner_mask = (int)invItem.NextPermissions;
llsdItem.permissions.owner_id = invItem.Owner;
llsdItem.permissions.owner_mask = (int)invItem.CurrentPermissions;
llsdItem.sale_info = new LLSDSaleInfo();
llsdItem.sale_info.sale_price = invItem.SalePrice;
llsdItem.sale_info.sale_type = invItem.SaleType;
return llsdItem;
}
}
}

View File

@ -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");
}
}
}

View File

@ -0,0 +1,292 @@
/*
* 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 FetchInventoryDescendents2HandlerTests : OpenSimTestCase
{
private UUID m_userID = UUID.Zero;
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);
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);
}
[Test]
public void Test_001_SimpleFolder()
{
TestHelpers.InMethod();
Init();
FetchInvDescHandler handler = new FetchInvDescHandler(m_scene.InventoryService, null, m_scene);
TestOSHttpRequest req = new TestOSHttpRequest();
TestOSHttpResponse resp = new TestOSHttpResponse();
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>00000000-0000-0000-0000-000000000000</uuid><key>sort_order</key><integer>1</integer></map></array></map></llsd>";
string llsdresponse = handler.FetchInventoryDescendentsRequest(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("00000000-0000-0000-0000-000000000000"), 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);
TestOSHttpRequest req = new TestOSHttpRequest();
TestOSHttpResponse resp = new TestOSHttpResponse();
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 += "</array></map></llsd>";
string llsdresponse = handler.FetchInventoryDescendentsRequest(request, "/FETCH", string.Empty, req, resp);
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);
TestOSHttpRequest req = new TestOSHttpRequest();
TestOSHttpResponse resp = new TestOSHttpResponse();
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-000000000000</uuid><key>sort_order</key><integer>1</integer></map></array></map></llsd>";
string llsdresponse = handler.FetchInventoryDescendentsRequest(request, "/FETCH", string.Empty, req, resp);
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");
// 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);
TestOSHttpRequest req = new TestOSHttpRequest();
TestOSHttpResponse resp = new TestOSHttpResponse();
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 = handler.FetchInventoryDescendentsRequest(request, "/FETCH", string.Empty, req, resp);
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);
TestOSHttpRequest req = new TestOSHttpRequest();
TestOSHttpResponse resp = new TestOSHttpResponse();
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 = handler.FetchInventoryDescendentsRequest(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("bad_folders</key><array><uuid>00000000-0000-0000-0000-000000000000"), Is.True, "Folder Zero should be a bad folder");
Console.WriteLine(llsdresponse);
}
}
}

View File

@ -0,0 +1,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;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Drawing;
using System.Drawing.Imaging;
using System.Reflection;
using System.IO;
using System.Web;
using log4net;
using Nini.Config;
using OpenMetaverse;
using OpenMetaverse.StructuredData;
using OpenMetaverse.Imaging;
using OpenSim.Framework;
using OpenSim.Framework.Capabilities;
using OpenSim.Framework.Servers;
using OpenSim.Framework.Servers.HttpServer;
using OpenSim.Region.Framework.Interfaces;
using OpenSim.Services.Interfaces;
using Caps = OpenSim.Framework.Capabilities.Caps;
using OSDMap = OpenMetaverse.StructuredData.OSDMap;
using OSDArray = OpenMetaverse.StructuredData.OSDArray;
namespace OpenSim.Capabilities.Handlers
{
public class GetDisplayNamesHandler : BaseStreamHandler
{
private static readonly ILog m_log =
LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private IUserManagement m_UserManagement;
public GetDisplayNamesHandler(string path, IUserManagement umService, string name, string description)
: base("GET", path, name, description)
{
m_UserManagement = umService;
}
protected override byte[] ProcessRequest(string path, Stream request, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
{
m_log.DebugFormat("[GET_DISPLAY_NAMES]: called {0}", httpRequest.Url.Query);
NameValueCollection query = HttpUtility.ParseQueryString(httpRequest.Url.Query);
string[] ids = query.GetValues("ids");
if (m_UserManagement == null)
{
m_log.Error("[GET_DISPLAY_NAMES]: Cannot fetch display names without a user management component");
httpResponse.StatusCode = (int)System.Net.HttpStatusCode.InternalServerError;
return new byte[0];
}
OSDMap osdReply = new OSDMap();
OSDArray agents = new OSDArray();
osdReply["agents"] = agents;
foreach (string id in ids)
{
UUID uuid = UUID.Zero;
if (UUID.TryParse(id, out uuid))
{
string name = m_UserManagement.GetUserName(uuid);
if (!string.IsNullOrEmpty(name))
{
string[] parts = name.Split(new char[] {' '});
OSDMap osdname = new OSDMap();
osdname["display_name_next_update"] = OSD.FromDate(DateTime.MinValue);
osdname["display_name_expires"] = OSD.FromDate(DateTime.Now.AddMonths(1));
osdname["display_name"] = OSD.FromString(name);
osdname["legacy_first_name"] = parts[0];
osdname["legacy_last_name"] = parts[1];
osdname["username"] = OSD.FromString(name);
osdname["id"] = OSD.FromUUID(uuid);
osdname["is_display_name_default"] = OSD.FromBoolean(true);
agents.Add(osdname);
}
}
}
// Full content request
httpResponse.StatusCode = (int)System.Net.HttpStatusCode.OK;
//httpResponse.ContentLength = ??;
httpResponse.ContentType = "application/llsd+xml";
string reply = OSDParser.SerializeLLSDXmlString(osdReply);
return System.Text.Encoding.UTF8.GetBytes(reply);
}
}
}

View File

@ -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 GetDisplayNamesServerConnector : ServiceConnector
{
private IUserManagement m_UserManagement;
private string m_ConfigName = "CapsService";
public GetDisplayNamesServerConnector(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 umService = serverConfig.GetString("AssetService", String.Empty);
if (umService == String.Empty)
throw new Exception("No AssetService in config file");
Object[] args = new Object[] { config };
m_UserManagement =
ServerUtils.LoadPlugin<IUserManagement>(umService, args);
if (m_UserManagement == null)
throw new Exception(String.Format("Failed to load UserManagement from {0}; config is {1}", umService, m_ConfigName));
string rurl = serverConfig.GetString("GetTextureRedirectURL");
server.AddStreamHandler(
new GetDisplayNamesHandler("/CAPS/agents/", m_UserManagement, "GetDisplayNames", null));
}
}
}

View File

@ -0,0 +1,253 @@
/*
* 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 OpenMetaverse;
using OpenMetaverse.Imaging;
using OpenSim.Framework;
using OpenSim.Framework.Servers.HttpServer;
using OpenSim.Services.Interfaces;
using System;
using System.Collections.Specialized;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Reflection;
using System.Web;
namespace OpenSim.Capabilities.Handlers
{
public class GetMeshHandler : BaseStreamHandler
{
private static readonly ILog m_log =
LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private IAssetService m_assetService;
// TODO: Change this to a config option
private string m_RedirectURL = null;
public GetMeshHandler(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("mesh_id");
if (m_assetService == null)
{
m_log.Error("[GETMESH]: Cannot fetch mesh " + textureStr + " without an asset service");
httpResponse.StatusCode = (int)System.Net.HttpStatusCode.NotFound;
}
UUID meshID;
if (!String.IsNullOrEmpty(textureStr) && UUID.TryParse(textureStr, out meshID))
{
// OK, we have an array with preferred formats, possibly with only one entry
httpResponse.StatusCode = (int)System.Net.HttpStatusCode.NotFound;
AssetBase mesh;
if (!String.IsNullOrEmpty(m_RedirectURL))
{
// Only try to fetch locally cached meshes. Misses are redirected
mesh = m_assetService.GetCached(meshID.ToString());
if (mesh != null)
{
if (mesh.Type != (sbyte)AssetType.Mesh)
{
httpResponse.StatusCode = (int)System.Net.HttpStatusCode.NotFound;
}
WriteMeshData(httpRequest, httpResponse, mesh);
}
else
{
string textureUrl = m_RedirectURL + "?mesh_id="+ meshID.ToString();
m_log.Debug("[GETMESH]: Redirecting mesh request to " + textureUrl);
httpResponse.StatusCode = (int)OSHttpStatusCode.RedirectMovedPermanently;
httpResponse.RedirectLocation = textureUrl;
return null;
}
}
else // no redirect
{
// try the cache
mesh = m_assetService.GetCached(meshID.ToString());
if (mesh == null)
{
// Fetch locally or remotely. Misses return a 404
mesh = m_assetService.Get(meshID.ToString());
if (mesh != null)
{
if (mesh.Type != (sbyte)AssetType.Mesh)
{
httpResponse.StatusCode = (int)System.Net.HttpStatusCode.NotFound;
return null;
}
WriteMeshData(httpRequest, httpResponse, mesh);
return null;
}
}
else // it was on the cache
{
if (mesh.Type != (sbyte)AssetType.Mesh)
{
httpResponse.StatusCode = (int)System.Net.HttpStatusCode.NotFound;
return null;
}
WriteMeshData(httpRequest, httpResponse, mesh);
return null;
}
}
// not found
httpResponse.StatusCode = (int)System.Net.HttpStatusCode.NotFound;
return null;
}
else
{
m_log.Warn("[GETTEXTURE]: Failed to parse a mesh_id from GetMesh request: " + httpRequest.Url);
}
return null;
}
private void WriteMeshData(IOSHttpRequest request, IOSHttpResponse response, AssetBase texture)
{
string range = request.Headers.GetOne("Range");
if (!String.IsNullOrEmpty(range))
{
// 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)
{
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;
if (0 == start && len == texture.Data.Length)
{
response.StatusCode = (int)System.Net.HttpStatusCode.OK;
}
else
{
response.StatusCode = (int)System.Net.HttpStatusCode.PartialContent;
response.AddHeader("Content-Range", String.Format("bytes {0}-{1}/{2}", start, end, texture.Data.Length));
}
response.ContentLength = len;
response.ContentType = "application/vnd.ll.mesh";
response.Body.Write(texture.Data, start, len);
}
}
else
{
m_log.Warn("[GETMESH]: Malformed Range header: " + range);
response.StatusCode = (int)System.Net.HttpStatusCode.BadRequest;
}
}
else
{
// Full content request
response.StatusCode = (int)System.Net.HttpStatusCode.OK;
response.ContentLength = texture.Data.Length;
response.ContentType = "application/vnd.ll.mesh";
response.Body.Write(texture.Data, 0, 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;
}
}
}

View File

@ -0,0 +1,76 @@
/*
* 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");
server.AddStreamHandler(
new GetTextureHandler("/CAPS/GetMesh/" /*+ UUID.Random() */, m_AssetService, "GetMesh", null, rurl));
rurl = serverConfig.GetString("GetMesh2RedirectURL");
server.AddStreamHandler(
new GetTextureHandler("/CAPS/GetMesh2/" /*+ UUID.Random() */, m_AssetService, "GetMesh2", null, rurl));
}
}
}

View File

@ -0,0 +1,431 @@
/*
* 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 : 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 GetTextureHandler(string path, IAssetService assService, string name, string description, string redirectURL)
: base("GET", path, name, description)
{
m_assetService = assService;
m_RedirectURL = redirectURL;
if (m_RedirectURL != null && !m_RedirectURL.EndsWith("/"))
m_RedirectURL += "/";
}
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;
}
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);
AssetBase texture;
string fullID = textureID.ToString();
if (format != DefaultFormat)
fullID = fullID + "-" + format;
if (!String.IsNullOrEmpty(m_RedirectURL))
{
// Only try to fetch locally cached textures. Misses are redirected
texture = m_assetService.GetCached(fullID);
if (texture != null)
{
if (texture.Type != (sbyte)AssetType.Texture)
{
httpResponse.StatusCode = (int)System.Net.HttpStatusCode.NotFound;
return true;
}
WriteTextureData(httpRequest, httpResponse, texture, format);
}
else
{
string textureUrl = m_RedirectURL + "?texture_id="+ textureID.ToString();
m_log.Debug("[GETTEXTURE]: Redirecting texture request to " + textureUrl);
httpResponse.StatusCode = (int)OSHttpStatusCode.RedirectMovedPermanently;
httpResponse.RedirectLocation = textureUrl;
return true;
}
}
else // no redirect
{
// try the cache
texture = m_assetService.GetCached(fullID);
if (texture == null)
{
// m_log.DebugFormat("[GETTEXTURE]: texture was not in the cache");
// Fetch locally or remotely. Misses return a 404
texture = m_assetService.Get(textureID.ToString());
if (texture != null)
{
if (texture.Type != (sbyte)AssetType.Texture)
{
httpResponse.StatusCode = (int)System.Net.HttpStatusCode.NotFound;
return true;
}
if (format == DefaultFormat)
{
WriteTextureData(httpRequest, httpResponse, texture, format);
return true;
}
else
{
AssetBase newTexture = new AssetBase(texture.ID + "-" + format, texture.Name, (sbyte)AssetType.Texture, texture.Metadata.CreatorID);
newTexture.Data = ConvertTextureData(texture, format);
if (newTexture.Data.Length == 0)
return false; // !!! Caller try another codec, please!
newTexture.Flags = AssetFlags.Collectable;
newTexture.Temporary = true;
newTexture.Local = true;
m_assetService.Store(newTexture);
WriteTextureData(httpRequest, httpResponse, newTexture, format);
return true;
}
}
}
else // it was on the cache
{
// m_log.DebugFormat("[GETTEXTURE]: texture was in the cache");
WriteTextureData(httpRequest, httpResponse, texture, format);
return true;
}
}
// 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.Body.Write(texture.Data, start, 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.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);
}
/// <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 = new Bitmap(1, 1);
ManagedImage managedImage;
Image image = (Image)mTexture;
try
{
// Taking our jpeg2000 data, decoding it, then saving it to a byte array with regular data
imgstream = new MemoryStream();
// Decode image to System.Drawing.Image
if (OpenJPEG.DecodeToImage(texture.Data, out managedImage, out image))
{
// Save to bitmap
mTexture = new Bitmap(image);
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 (imgstream != null)
{
imgstream.Close();
imgstream.Dispose();
}
}
return data;
}
// From msdn
private static ImageCodecInfo GetEncoderInfo(String mimeType)
{
ImageCodecInfo[] encoders;
encoders = ImageCodecInfo.GetImageEncoders();
for (int j = 0; j < encoders.Length; ++j)
{
if (encoders[j].MimeType == mimeType)
return encoders[j];
}
return null;
}
}
}

View File

@ -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 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 GetTextureHandler("/CAPS/GetTexture/" /*+ UUID.Random() */, m_AssetService, "GetTexture", null, rurl));
}
}
}

View File

@ -0,0 +1,62 @@
/*
* 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));
}
}
}

View File

@ -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("0.8.2.*")]

View File

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

View File

@ -0,0 +1,76 @@
/*
* 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 UploadBakedTextureServerConnector : ServiceConnector
{
private IAssetService m_AssetService;
private string m_ConfigName = "CapsService";
public UploadBakedTextureServerConnector(IConfigSource config, IHttpServer server, string configName) :
base(config, server, configName)
{
if (configName != String.Empty)
m_ConfigName = configName;
IConfig serverConfig = config.Configs[m_ConfigName];
if (serverConfig == null)
throw new Exception(String.Format("No section '{0}' in config file", m_ConfigName));
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));
// NEED TO FIX THIS
OpenSim.Framework.Capabilities.Caps caps = new OpenSim.Framework.Capabilities.Caps(server, "", server.Port, "", UUID.Zero, "");
server.AddStreamHandler(new RestStreamHandler(
"POST",
"/CAPS/UploadBakedTexture/",
new UploadBakedTextureHandler(caps, m_AssetService, true).UploadBakedTexture,
"UploadBakedTexture",
"Upload Baked Texture Capability"));
}
}
}

View File

@ -0,0 +1,684 @@
/*
* 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.Globalization;
using System.IO;
using System.Security.Cryptography;
using System.Text;
using System.Xml;
using OpenMetaverse;
namespace OpenSim.Framework.Capabilities
{
/// <summary>
/// Borrowed from (a older version of) libsl for now, as their new llsd code doesn't work we our decoding code.
/// </summary>
public static class LLSD
{
/// <summary>
///
/// </summary>
public class LLSDParseException : Exception
{
public LLSDParseException(string message) : base(message)
{
}
}
/// <summary>
///
/// </summary>
public class LLSDSerializeException : Exception
{
public LLSDSerializeException(string message) : base(message)
{
}
}
/// <summary>
///
/// </summary>
/// <param name="b"></param>
/// <returns></returns>
public static object LLSDDeserialize(byte[] b)
{
using (MemoryStream ms = new MemoryStream(b, false))
{
return LLSDDeserialize(ms);
}
}
/// <summary>
///
/// </summary>
/// <param name="st"></param>
/// <returns></returns>
public static object LLSDDeserialize(Stream st)
{
using (XmlTextReader reader = new XmlTextReader(st))
{
reader.Read();
SkipWS(reader);
if (reader.NodeType != XmlNodeType.Element || reader.LocalName != "llsd")
throw new LLSDParseException("Expected <llsd>");
reader.Read();
object ret = LLSDParseOne(reader);
SkipWS(reader);
if (reader.NodeType != XmlNodeType.EndElement || reader.LocalName != "llsd")
throw new LLSDParseException("Expected </llsd>");
return ret;
}
}
/// <summary>
///
/// </summary>
/// <param name="obj"></param>
/// <returns></returns>
public static byte[] LLSDSerialize(object obj)
{
StringWriter sw = new StringWriter();
XmlTextWriter writer = new XmlTextWriter(sw);
writer.Formatting = Formatting.None;
writer.WriteStartElement(String.Empty, "llsd", String.Empty);
LLSDWriteOne(writer, obj);
writer.WriteEndElement();
writer.Close();
return Util.UTF8.GetBytes(sw.ToString());
}
/// <summary>
///
/// </summary>
/// <param name="writer"></param>
/// <param name="obj"></param>
public static void LLSDWriteOne(XmlTextWriter writer, object obj)
{
if (obj == null)
{
writer.WriteStartElement(String.Empty, "undef", String.Empty);
writer.WriteEndElement();
return;
}
if (obj is string)
{
writer.WriteStartElement(String.Empty, "string", String.Empty);
writer.WriteString((string) obj);
writer.WriteEndElement();
}
else if (obj is int)
{
writer.WriteStartElement(String.Empty, "integer", String.Empty);
writer.WriteString(obj.ToString());
writer.WriteEndElement();
}
else if (obj is double)
{
writer.WriteStartElement(String.Empty, "real", String.Empty);
writer.WriteString(obj.ToString());
writer.WriteEndElement();
}
else if (obj is bool)
{
bool b = (bool) obj;
writer.WriteStartElement(String.Empty, "boolean", String.Empty);
writer.WriteString(b ? "1" : "0");
writer.WriteEndElement();
}
else if (obj is ulong)
{
throw new Exception("ulong in LLSD is currently not implemented, fix me!");
}
else if (obj is UUID)
{
UUID u = (UUID) obj;
writer.WriteStartElement(String.Empty, "uuid", String.Empty);
writer.WriteString(u.ToString());
writer.WriteEndElement();
}
else if (obj is Hashtable)
{
Hashtable h = obj as Hashtable;
writer.WriteStartElement(String.Empty, "map", String.Empty);
foreach (string key in h.Keys)
{
writer.WriteStartElement(String.Empty, "key", String.Empty);
writer.WriteString(key);
writer.WriteEndElement();
LLSDWriteOne(writer, h[key]);
}
writer.WriteEndElement();
}
else if (obj is ArrayList)
{
ArrayList a = obj as ArrayList;
writer.WriteStartElement(String.Empty, "array", String.Empty);
foreach (object item in a)
{
LLSDWriteOne(writer, item);
}
writer.WriteEndElement();
}
else if (obj is byte[])
{
byte[] b = obj as byte[];
writer.WriteStartElement(String.Empty, "binary", String.Empty);
writer.WriteStartAttribute(String.Empty, "encoding", String.Empty);
writer.WriteString("base64");
writer.WriteEndAttribute();
//// Calculate the length of the base64 output
//long length = (long)(4.0d * b.Length / 3.0d);
//if (length % 4 != 0) length += 4 - (length % 4);
//// Create the char[] for base64 output and fill it
//char[] tmp = new char[length];
//int i = Convert.ToBase64CharArray(b, 0, b.Length, tmp, 0);
//writer.WriteString(new String(tmp));
writer.WriteString(Convert.ToBase64String(b));
writer.WriteEndElement();
}
else
{
throw new LLSDSerializeException("Unknown type " + obj.GetType().Name);
}
}
/// <summary>
///
/// </summary>
/// <param name="reader"></param>
/// <returns></returns>
public static object LLSDParseOne(XmlTextReader reader)
{
SkipWS(reader);
if (reader.NodeType != XmlNodeType.Element)
throw new LLSDParseException("Expected an element");
string dtype = reader.LocalName;
object ret = null;
switch (dtype)
{
case "undef":
{
if (reader.IsEmptyElement)
{
reader.Read();
return null;
}
reader.Read();
SkipWS(reader);
ret = null;
break;
}
case "boolean":
{
if (reader.IsEmptyElement)
{
reader.Read();
return false;
}
reader.Read();
string s = reader.ReadString().Trim();
if (s == String.Empty || s == "false" || s == "0")
ret = false;
else if (s == "true" || s == "1")
ret = true;
else
throw new LLSDParseException("Bad boolean value " + s);
break;
}
case "integer":
{
if (reader.IsEmptyElement)
{
reader.Read();
return 0;
}
reader.Read();
ret = Convert.ToInt32(reader.ReadString().Trim());
break;
}
case "real":
{
if (reader.IsEmptyElement)
{
reader.Read();
return 0.0f;
}
reader.Read();
ret = Convert.ToDouble(reader.ReadString().Trim());
break;
}
case "uuid":
{
if (reader.IsEmptyElement)
{
reader.Read();
return UUID.Zero;
}
reader.Read();
ret = new UUID(reader.ReadString().Trim());
break;
}
case "string":
{
if (reader.IsEmptyElement)
{
reader.Read();
return String.Empty;
}
reader.Read();
ret = reader.ReadString();
break;
}
case "binary":
{
if (reader.IsEmptyElement)
{
reader.Read();
return new byte[0];
}
if (reader.GetAttribute("encoding") != null &&
reader.GetAttribute("encoding") != "base64")
{
throw new LLSDParseException("Unknown encoding: " + reader.GetAttribute("encoding"));
}
reader.Read();
FromBase64Transform b64 = new FromBase64Transform(FromBase64TransformMode.IgnoreWhiteSpaces);
byte[] inp = Util.UTF8.GetBytes(reader.ReadString());
ret = b64.TransformFinalBlock(inp, 0, inp.Length);
break;
}
case "date":
{
reader.Read();
throw new Exception("LLSD TODO: date");
}
case "map":
{
return LLSDParseMap(reader);
}
case "array":
{
return LLSDParseArray(reader);
}
default:
throw new LLSDParseException("Unknown element <" + dtype + ">");
}
if (reader.NodeType != XmlNodeType.EndElement || reader.LocalName != dtype)
{
throw new LLSDParseException("Expected </" + dtype + ">");
}
reader.Read();
return ret;
}
/// <summary>
///
/// </summary>
/// <param name="reader"></param>
/// <returns></returns>
public static Hashtable LLSDParseMap(XmlTextReader reader)
{
Hashtable ret = new Hashtable();
if (reader.NodeType != XmlNodeType.Element || reader.LocalName != "map")
throw new LLSDParseException("Expected <map>");
if (reader.IsEmptyElement)
{
reader.Read();
return ret;
}
reader.Read();
while (true)
{
SkipWS(reader);
if (reader.NodeType == XmlNodeType.EndElement && reader.LocalName == "map")
{
reader.Read();
break;
}
if (reader.NodeType != XmlNodeType.Element || reader.LocalName != "key")
throw new LLSDParseException("Expected <key>");
string key = reader.ReadString();
if (reader.NodeType != XmlNodeType.EndElement || reader.LocalName != "key")
throw new LLSDParseException("Expected </key>");
reader.Read();
object val = LLSDParseOne(reader);
ret[key] = val;
}
return ret; // TODO
}
/// <summary>
///
/// </summary>
/// <param name="reader"></param>
/// <returns></returns>
public static ArrayList LLSDParseArray(XmlTextReader reader)
{
ArrayList ret = new ArrayList();
if (reader.NodeType != XmlNodeType.Element || reader.LocalName != "array")
throw new LLSDParseException("Expected <array>");
if (reader.IsEmptyElement)
{
reader.Read();
return ret;
}
reader.Read();
while (true)
{
SkipWS(reader);
if (reader.NodeType == XmlNodeType.EndElement && reader.LocalName == "array")
{
reader.Read();
break;
}
ret.Insert(ret.Count, LLSDParseOne(reader));
}
return ret; // TODO
}
/// <summary>
///
/// </summary>
/// <param name="count"></param>
/// <returns></returns>
private static string GetSpaces(int count)
{
StringBuilder b = new StringBuilder();
for (int i = 0; i < count; i++) b.Append(" ");
return b.ToString();
}
/// <summary>
///
/// </summary>
/// <param name="obj"></param>
/// <param name="indent"></param>
/// <returns></returns>
public static String LLSDDump(object obj, int indent)
{
if (obj == null)
{
return GetSpaces(indent) + "- undef\n";
}
else if (obj is string)
{
return GetSpaces(indent) + "- string \"" + (string) obj + "\"\n";
}
else if (obj is int)
{
return GetSpaces(indent) + "- integer " + obj.ToString() + "\n";
}
else if (obj is double)
{
return GetSpaces(indent) + "- float " + obj.ToString() + "\n";
}
else if (obj is UUID)
{
return GetSpaces(indent) + "- uuid " + ((UUID) obj).ToString() + Environment.NewLine;
}
else if (obj is Hashtable)
{
StringBuilder ret = new StringBuilder();
ret.Append(GetSpaces(indent) + "- map" + Environment.NewLine);
Hashtable map = (Hashtable) obj;
foreach (string key in map.Keys)
{
ret.Append(GetSpaces(indent + 2) + "- key \"" + key + "\"" + Environment.NewLine);
ret.Append(LLSDDump(map[key], indent + 3));
}
return ret.ToString();
}
else if (obj is ArrayList)
{
StringBuilder ret = new StringBuilder();
ret.Append(GetSpaces(indent) + "- array\n");
ArrayList list = (ArrayList) obj;
foreach (object item in list)
{
ret.Append(LLSDDump(item, indent + 2));
}
return ret.ToString();
}
else if (obj is byte[])
{
return GetSpaces(indent) + "- binary\n" + Utils.BytesToHexString((byte[]) obj, GetSpaces(indent)) +
Environment.NewLine;
}
else
{
return GetSpaces(indent) + "- unknown type " + obj.GetType().Name + Environment.NewLine;
}
}
public static object ParseTerseLLSD(string llsd)
{
int notused;
return ParseTerseLLSD(llsd, out notused);
}
public static object ParseTerseLLSD(string llsd, out int endPos)
{
if (llsd.Length == 0)
{
endPos = 0;
return null;
}
// Identify what type of object this is
switch (llsd[0])
{
case '!':
throw new LLSDParseException("Undefined value type encountered");
case '1':
endPos = 1;
return true;
case '0':
endPos = 1;
return false;
case 'i':
{
if (llsd.Length < 2) throw new LLSDParseException("Integer value type with no value");
int value;
endPos = FindEnd(llsd, 1);
if (Int32.TryParse(llsd.Substring(1, endPos - 1), out value))
return value;
else
throw new LLSDParseException("Failed to parse integer value type");
}
case 'r':
{
if (llsd.Length < 2) throw new LLSDParseException("Real value type with no value");
double value;
endPos = FindEnd(llsd, 1);
if (Double.TryParse(llsd.Substring(1, endPos - 1), NumberStyles.Float,
Utils.EnUsCulture.NumberFormat, out value))
return value;
else
throw new LLSDParseException("Failed to parse double value type");
}
case 'u':
{
if (llsd.Length < 17) throw new LLSDParseException("UUID value type with no value");
UUID value;
endPos = FindEnd(llsd, 1);
if (UUID.TryParse(llsd.Substring(1, endPos - 1), out value))
return value;
else
throw new LLSDParseException("Failed to parse UUID value type");
}
case 'b':
//byte[] value = new byte[llsd.Length - 1];
// This isn't the actual binary LLSD format, just the terse format sent
// at login so I don't even know if there is a binary type
throw new LLSDParseException("Binary value type is unimplemented");
case 's':
case 'l':
if (llsd.Length < 2) throw new LLSDParseException("String value type with no value");
endPos = FindEnd(llsd, 1);
return llsd.Substring(1, endPos - 1);
case 'd':
// Never seen one before, don't know what the format is
throw new LLSDParseException("Date value type is unimplemented");
case '[':
{
if (llsd.IndexOf(']') == -1) throw new LLSDParseException("Invalid array");
int pos = 0;
ArrayList array = new ArrayList();
while (llsd[pos] != ']')
{
++pos;
// Advance past comma if need be
if (llsd[pos] == ',') ++pos;
// Allow a single whitespace character
if (pos < llsd.Length && llsd[pos] == ' ') ++pos;
int end;
array.Add(ParseTerseLLSD(llsd.Substring(pos), out end));
pos += end;
}
endPos = pos + 1;
return array;
}
case '{':
{
if (llsd.IndexOf('}') == -1) throw new LLSDParseException("Invalid map");
int pos = 0;
Hashtable hashtable = new Hashtable();
while (llsd[pos] != '}')
{
++pos;
// Advance past comma if need be
if (llsd[pos] == ',') ++pos;
// Allow a single whitespace character
if (pos < llsd.Length && llsd[pos] == ' ') ++pos;
if (llsd[pos] != '\'') throw new LLSDParseException("Expected a map key");
int endquote = llsd.IndexOf('\'', pos + 1);
if (endquote == -1 || (endquote + 1) >= llsd.Length || llsd[endquote + 1] != ':')
throw new LLSDParseException("Invalid map format");
string key = llsd.Substring(pos, endquote - pos);
key = key.Replace("'", String.Empty);
pos += (endquote - pos) + 2;
int end;
hashtable.Add(key, ParseTerseLLSD(llsd.Substring(pos), out end));
pos += end;
}
endPos = pos + 1;
return hashtable;
}
default:
throw new Exception("Unknown value type");
}
}
private static int FindEnd(string llsd, int start)
{
int end = llsd.IndexOfAny(new char[] {',', ']', '}'});
if (end == -1) end = llsd.Length - 1;
return end;
}
/// <summary>
///
/// </summary>
/// <param name="reader"></param>
private static void SkipWS(XmlTextReader reader)
{
while (
reader.NodeType == XmlNodeType.Comment ||
reader.NodeType == XmlNodeType.Whitespace ||
reader.NodeType == XmlNodeType.SignificantWhitespace ||
reader.NodeType == XmlNodeType.XmlDeclaration)
{
reader.Read();
}
}
}
}

View File

@ -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()
{
}
}
}

View File

@ -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 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 string state = String.Empty;
//public bool success = false;
public LLSDAssetUploadComplete()
{
}
}
}

View File

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

View File

@ -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;
namespace OpenSim.Framework.Capabilities
{
[OSDMap]
public class LLSDAssetUploadResponse
{
public string uploader = String.Empty;
public string state = String.Empty;
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";
}
}
}

View File

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

View File

@ -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()
{
}
}
}

View File

@ -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()
{
}
}
}

View File

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

View File

@ -0,0 +1,172 @@
/*
* 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;
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)
{
StringWriter sw = new StringWriter();
XmlTextWriter writer = new XmlTextWriter(sw);
writer.Formatting = Formatting.None;
writer.WriteStartElement(String.Empty, "llsd", String.Empty);
SerializeOSDType(writer, obj);
writer.WriteEndElement();
writer.Close();
//m_log.DebugFormat("[LLSD Helpers]: Generated serialized LLSD reply {0}", sw.ToString());
return sw.ToString();
}
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
{
field.SetValue(obj, enumerator.Value);
}
}
}
break;
}
}
return obj;
}
}
}

View File

@ -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 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;
}
}

View File

@ -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();
}
}

View File

@ -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 OpenMetaverse;
namespace OpenSim.Framework.Capabilities
{
[OSDMap]
public class LLSDItemUpdate
{
public UUID item_id;
public LLSDItemUpdate()
{
}
}
}

View File

@ -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()
{
}
}
}

View File

@ -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()
{
}
}
}

View File

@ -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()
{
}
}
}

View File

@ -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);
}

View File

@ -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);
}

View File

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

View File

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

View File

@ -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.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);
TRequest llsdRequest = new TRequest();
LLSDHelpers.DeserialiseOSDMap(hash, llsdRequest);
TResponse response = m_method(llsdRequest);
return Util.UTF8NoBomEncoding.GetBytes(LLSDHelpers.SerialiseLLSDReply(response));
}
}
}

View File

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

View File

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

View File

@ -0,0 +1,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;
}
}

View File

@ -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()
{
}
}
}

View File

@ -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")
{
}
}
}

View File

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

View File

@ -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")]

View File

@ -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)
{
}
}
}

View File

@ -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")]

View File

@ -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);
}
}
}

View File

@ -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 void 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);
}
}

71
OpenSim/Data/DBGuids.cs Normal file
View File

@ -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 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;
if (id.GetType() == typeof(Guid))
return new UUID((Guid)id);
if (id.GetType() == typeof(byte[]))
{
if (((byte[])id).Length == 0)
return UUID.Zero;
else if (((byte[])id).Length == 16)
return new UUID((byte[])id, 0);
}
else if (id.GetType() == typeof(string))
{
if (((string)id).Length == 0)
return UUID.Zero;
else if (((string)id).Length == 36)
return new UUID((string)id);
}
throw new Exception("Failed to convert db value to UUID: " + id.ToString());
}
}
}

View File

@ -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);
}
}

View File

@ -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);
void StoreAsset(AssetBase asset);
bool[] AssetsExist(UUID[] uuids);
List<AssetMetadata> FetchAssetMetadataSet(int start, int count);
void Initialise(string connect);
bool Delete(string id);
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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();
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

144
OpenSim/Data/IGroupsData.cs Normal file
View File

@ -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
}
}

View File

@ -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();
}
}

View File

@ -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);
}
}

View File

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

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