Compare commits
	
		
			No commits in common. "master" and "mb-throttle-test" have entirely different histories. 
		
	
	
		
			master
			...
			mb-throttl
		
	
		|  | @ -1,6 +1,5 @@ | |||
| .project | ||||
| .settings | ||||
| .gitignore | ||||
| *.csproj | ||||
| *.csproj.user | ||||
| *.build | ||||
|  | @ -11,7 +10,6 @@ | |||
| *.pidb | ||||
| *.dll.build | ||||
| *.dll | ||||
| *.log | ||||
| 
 | ||||
| # Ignore .user and .suo files as these are user preference specific | ||||
| # http://stackoverflow.com/questions/72298/should-i-add-the-visual-studio-suo-and-user-files-to-source-control | ||||
|  | @ -31,8 +29,6 @@ | |||
| */*/*/*/*/bin | ||||
| */*/*/*/*/*/bin | ||||
| */*/*/*/*/*/*/bin | ||||
| .vs/ | ||||
| addon-modules/ | ||||
| bin/Debug/*.dll | ||||
| bin/*.dll.mdb | ||||
| bin/*.db | ||||
|  | @ -71,12 +67,6 @@ bin/OpenSim.Grid.InventoryServer.log | |||
| bin/OpenSim.Grid.MessagingServer.log | ||||
| bin/OpenSim.Grid.UserServer.log | ||||
| bin/OpenSim.log | ||||
| bin/OpenSimStats.log | ||||
| bin/Robust.log | ||||
| bin/RobustStats.log | ||||
| bin/OpenSimConsoleHistory.txt | ||||
| bin/RobustConsoleHistory.txt | ||||
| bin/*.Tests.log | ||||
| bin/*.manifest | ||||
| bin/crashes/ | ||||
| Examples/*.dll | ||||
|  | @ -94,6 +84,7 @@ TAGS | |||
| Makefile.local | ||||
| bin/.version | ||||
| compile.bat | ||||
| addon-modules | ||||
| OpenSim/Data/Tests/test-results/ | ||||
| OpenSim/Framework/Serialization/Tests/test-results/ | ||||
| OpenSim/Framework/Servers/Tests/test-results/ | ||||
|  | @ -112,5 +103,3 @@ OpenSim/Tests/test-results/ | |||
| test-results/ | ||||
| doc/html | ||||
| doc/doxygen.error.log | ||||
| 
 | ||||
| *.patch | ||||
|  |  | |||
|  | @ -113,12 +113,10 @@ | |||
|   </exec> | ||||
|   <fail message="Failures reported in unit tests." unless="${int::parse(testresult.opensim.region.coremodules.tests)==0}" />  | ||||
| 
 | ||||
| <!-- | ||||
|   <exec program="${nunitcmd}" failonerror="true" resultproperty="testresult.opensim.region.optionalmodules.tests"> | ||||
|     <arg value="./bin/OpenSim.Region.OptionalModules.Tests.dll" /> | ||||
|   </exec> | ||||
|   <fail message="Failures reported in unit tests." unless="${int::parse(testresult.opensim.region.optionalmodules.tests)==0}" />  | ||||
| --> | ||||
| 
 | ||||
|   <exec program="${nunitcmd}" failonerror="true" resultproperty="testresult.opensim.region.framework.tests"> | ||||
|     <arg value="./bin/OpenSim.Region.Framework.Tests.dll" /> | ||||
|  | @ -145,12 +143,7 @@ | |||
|   </exec> | ||||
|   <fail message="Failures reported in unit tests." unless="${int::parse(testresult.opensim.services.inventoryservice.tests)==0}" />  | ||||
| 
 | ||||
|   <exec program="${nunitcmd}" failonerror="true" resultproperty="testresult.opensim.tests.permissions"> | ||||
|     <arg value="./bin/OpenSim.Tests.Permissions.dll" /> | ||||
|   </exec> | ||||
|   <fail message="Failures reported in unit tests." unless="${int::parse(testresult.opensim.tests.permissions)==0}" />  | ||||
|    | ||||
| <delete dir="%temp%"/> | ||||
|   <delete dir="%temp%"/> | ||||
| </target> | ||||
| 
 | ||||
| <target name="test-stress" depends="build, find-nunit"> | ||||
|  | @ -233,12 +226,10 @@ | |||
|     <arg value="-xml=test-results/OpenSim.Region.CoreModules.Tests.dll-Results.xml" /> | ||||
|   </exec> | ||||
| 
 | ||||
| <!-- | ||||
|  <exec program="${nunitcmd}" failonerror="false" resultproperty="testresult.opensim.region.optionalmodules.tests"> | ||||
|     <arg value="./bin/OpenSim.Region.OptionalModules.Tests.dll" /> | ||||
|     <arg value="-xml=test-results/OpenSim.Region.OptionalModules.Tests.dll-Results.xml" /> | ||||
|   </exec> | ||||
| --> | ||||
| 
 | ||||
|  <exec program="${nunitcmd}" failonerror="false" resultproperty="testresult.opensim.region.framework.tests"> | ||||
|     <arg value="./bin/OpenSim.Region.Framework.Tests.dll" /> | ||||
|  | @ -265,23 +256,17 @@ | |||
|     <arg value="-xml=test-results/OpenSim.Services.InventoryService.Tests.dll-Results.xml" /> | ||||
|   </exec> | ||||
| 
 | ||||
|  <exec program="${nunitcmd}" failonerror="false" resultproperty="testresult.opensim.tests.permissions"> | ||||
|     <arg value="./bin/OpenSim.Tests.Permissions.dll" /> | ||||
|     <arg value="-xml=test-results/OpenSim.Tests.Permissions.dll-Results.xml" /> | ||||
|   </exec> | ||||
|    | ||||
|  <fail message="Failures reported in unit tests." unless="${int::parse(testresult.opensim.tests)==0}" />  | ||||
|  <fail message="Failures reported in unit tests." unless="${int::parse(testresult.opensim.framework.tests)==0}" />  | ||||
|  <fail message="Failures reported in unit tests." unless="${int::parse(testresult.opensim.framework.servers.tests)==0}" />  | ||||
|  <fail message="Failures reported in unit tests." unless="${int::parse(testresult.opensim.region.clientstack.lindenudp.tests)==0}" /> | ||||
|  <fail message="Failures reported in unit tests." unless="${int::parse(testresult.opensim.region.scriptengine.tests)==0}" />  | ||||
|  <fail message="Failures reported in unit tests." unless="${int::parse(testresult.opensim.region.coremodules.tests)==0}" />  | ||||
| <!--  <fail message="Failures reported in unit tests." unless="${int::parse(testresult.opensim.region.optionalmodules.tests)==0}" /> --> | ||||
|  <fail message="Failures reported in unit tests." unless="${int::parse(testresult.opensim.region.optionalmodules.tests)==0}" />  | ||||
|  <fail message="Failures reported in unit tests." unless="${int::parse(testresult.opensim.region.framework.tests)==0}" />  | ||||
|  <fail message="Failures reported in unit tests." unless="${int::parse(testresult.opensim.data.tests)==0}" />  | ||||
|  <fail message="Failures reported in unit tests." unless="${int::parse(testresult.opensim.capabilities.handlers.tests)==0}" />  | ||||
|  <fail message="Failures reported in unit tests." unless="${int::parse(testresult.opensim.services.inventoryservice.tests)==0}" />  | ||||
|  <fail message="Failures reported in unit tests." unless="${int::parse(testresult.opensim.tests.permissions)==0}" />  | ||||
| </target> | ||||
| 
 | ||||
| <target name="doxygen"> | ||||
|  |  | |||
							
								
								
									
										35
									
								
								BUILDING.md
								
								
								
								
							
							
						
						
									
										35
									
								
								BUILDING.md
								
								
								
								
							|  | @ -1,35 +1,38 @@ | |||
| # Building on Windows | ||||
| 
 | ||||
| Steps: | ||||
| 
 | ||||
|  * runprebuild.bat | ||||
|  * Load OpenSim.sln into Visual Studio .NET and build the solution. | ||||
|  * chdir bin  | ||||
|  * copy OpenSim.ini.example to OpenSim.ini and other appropriate files in bin/config-include | ||||
|  * run OpenSim.exe | ||||
| 
 | ||||
| # Building on Linux / Mac | ||||
| # Building on Linux | ||||
| 
 | ||||
| Prereqs: | ||||
| 
 | ||||
|  *	Mono > 5.0 | ||||
|  *	On some Linux distributions you may need to install additional packages. | ||||
|  *	msbuild or xbuild if still supported by the mono version | ||||
|  *   See http://opensimulator.org/wiki/Dependencies for more information. | ||||
| *	Mono >= 2.4.3 | ||||
| *	Nant >= 0.85 | ||||
| *	On some Linux distributions you may need to install additional packages. | ||||
| 	See http://opensimulator.org/wiki/Dependencies for more information. | ||||
| *	May also use xbuild (included in mono distributions) | ||||
| *	May use Monodevelop, a cross-platform IDE | ||||
| 
 | ||||
| From the distribution type: | ||||
| 
 | ||||
|  * ./runprebuild.sh | ||||
|  * type msbuild or xbuild | ||||
|  * nant (or !* xbuild) | ||||
|  * cd bin  | ||||
|  * copy OpenSim.ini.example to OpenSim.ini and other appropriate files in bin/config-include | ||||
|  * review and change those ini files according to your needs | ||||
|  * windows: execute opensim.exe or opensim32.exe for small regions | ||||
|  * linux: run ./opensim.sh | ||||
|  * msbuild (xbuild) option switches | ||||
|    *  clean:  msbuild /target:clean | ||||
|    *  debug: (default) msbuild /property:Configuration=Debug | ||||
|    *  release: msbuild /property:Configuration=Release | ||||
|  * run mono OpenSim.exe | ||||
|  !* xbuild option switches | ||||
|  !*          clean:  xbuild /target:clean | ||||
|  !*          debug: (default) xbuild /property:Configuration=Debug | ||||
|  !*          release: xbuild /property:Configuration=Release | ||||
| 
 | ||||
| # Using Monodevelop | ||||
| 
 | ||||
| From the distribution type: | ||||
|  * ./runprebuild.sh | ||||
|  * type monodevelop OpenSim.sln | ||||
| 
 | ||||
| # References | ||||
|   | ||||
|  |  | |||
|  | @ -4,19 +4,37 @@ The following people have contributed to OpenSim (Thank you for your effort!) | |||
| These folks represent the current core team for OpenSim, and are the | ||||
| people that make the day to day of OpenSim happen. | ||||
| 
 | ||||
| * justincc (OSVW Consulting, justincc.org) | ||||
| * chi11ken (Genkii) | ||||
| * dahlia  | ||||
| * Melanie Thielker | ||||
| * Diva (Crista Lopes, University of California, Irvine) | ||||
| * Robert Adams (MisterBlue) | ||||
| * Dan Lake  | ||||
| * Marck | ||||
| * Mic Bowman | ||||
| * BlueWall (James Hughes) | ||||
| * Nebadon Izumi (Michael Cerquoni, OSgrid) | ||||
| * Snoopy Pfeffer | ||||
| * Robert Adams | ||||
| * Oren Hurvitz (Kitely) | ||||
| * Kevin Cozens | ||||
| * Leal Duarte (Ubit Umarov) | ||||
| 
 | ||||
| = Core Developers Following the White Rabbit = | ||||
| Core developers who have temporarily (we hope) gone chasing the white rabbit.  | ||||
| They are in all similar to the active core developers, except that they haven't | ||||
| been that active lately, so their voting rights are awaiting their come back.  | ||||
| 
 | ||||
| * Nebadon Izumi (Michael Cerquoni, OSgrid) | ||||
| * Alicia Raven | ||||
| * MW (Tribal Media AB) | ||||
| * Adam Frisby 	(DeepThink Pty Ltd) | ||||
| * lbsa71 (Tribal Media AB) | ||||
| * Teravus (w3z) | ||||
| * Ckrinke (Charles Krinke) | ||||
| * Dr Scofield aka Dirk Husemann (IBM Research - Zurich) | ||||
| * mikem (3Di) | ||||
| * Homer_Horwitz | ||||
| * nlin (3Di) | ||||
| * Arthur Rodrigo S Valadares (IBM) | ||||
| * John Hurliman | ||||
| 
 | ||||
| = Past Open Sim Developers = | ||||
| These folks are alumns of the OpenSim core group, but are now | ||||
|  | @ -38,26 +56,7 @@ where we are today. | |||
| * adjohn (Genkii) | ||||
| * idb (Ian Brown) | ||||
| * Johan Berntsson (3Di) | ||||
| * MW (Tribal Media AB) | ||||
| * Adam Frisby 	(DeepThink Pty Ltd) | ||||
| * lbsa71 (Tribal Media AB) | ||||
| * Ckrinke (Charles Krinke) | ||||
| * Dr Scofield aka Dirk Husemann (IBM Research - Zurich) | ||||
| * mikem (3Di) | ||||
| * Homer_Horwitz | ||||
| * nlin (3Di) | ||||
| * John Hurliman | ||||
| * chi11ken (Genkii) | ||||
| * dahlia | ||||
| * justincc (OSVW Consulting, justincc.org) | ||||
| * Arthur Rodrigo S Valadares (IBM) | ||||
| * BlueWall (James Hughes) | ||||
| * Dan Lake  | ||||
| * Marck | ||||
| * Mic Bowman | ||||
| * Oren Hurvitz (Kitely) | ||||
| * Snoopy Pfeffer | ||||
| * Teravus (w3z) | ||||
| 
 | ||||
| 
 | ||||
| = Additional OpenSim Contributors = | ||||
| These folks have contributed code patches or content to OpenSimulator to help make it | ||||
|  | @ -69,9 +68,9 @@ what it is today. | |||
| * alex_carnell | ||||
| * Alan Webb (IBM) | ||||
| * Aleric | ||||
| * Alicia Raven | ||||
| * Allen Kerensky | ||||
| * BigFootAg | ||||
| * Bill Blight | ||||
| * BlueWall Slade | ||||
| * bobshaffer2 | ||||
| * brianw/Sir_Ahzz | ||||
|  | @ -89,14 +88,11 @@ what it is today. | |||
| * dmiles (Daxtron Labs) | ||||
| * Dong Jun Lan (IBM) | ||||
| * DoranZemlja | ||||
| * Drake Arconis | ||||
| * dr0b3rts | ||||
| * dslake | ||||
| * eeyore | ||||
| * FredoChaplin | ||||
| * FreakyTech | ||||
| * Garmin Kawaguichi | ||||
| * Gavin Hird | ||||
| * Gerhard | ||||
| * Godfrey | ||||
| * Greg C. | ||||
|  | @ -106,10 +102,7 @@ what it is today. | |||
| * Fernando Oliveira | ||||
| * Fly-Man | ||||
| * Flyte Xevious | ||||
| * Freaky Tech | ||||
| * Garmin Kawaguichi | ||||
| * Geir Noklebye | ||||
| * Glenn Martin (MOSES) | ||||
| * Gryc Ueusp | ||||
| * H-H-H (ginge264) | ||||
| * Hiro Lecker | ||||
|  | @ -117,7 +110,6 @@ what it is today. | |||
| * Imaze Rhiano | ||||
| * Intimidated | ||||
| * Jak Daniels | ||||
| * Jeff Kelly | ||||
| * Jeremy Bongio (IBM) | ||||
| * jhurliman | ||||
| * John R Sohn (XenReborn) | ||||
|  | @ -131,27 +123,21 @@ what it is today. | |||
| * KittyLiu | ||||
| * Kurt Taylor (IBM) | ||||
| * Lani Global | ||||
| * lickx | ||||
| * lillith_xue | ||||
| * lkalif | ||||
| * LuciusSirnah | ||||
| * lulurun  | ||||
| * M.Igarashi | ||||
| * Magnuz Binder | ||||
| * maimedleech | ||||
| * Mana Janus | ||||
| * Mandarinka Tasty | ||||
| * MarcelEdward | ||||
| * Matt Lehmann | ||||
| * mewtwo0641 | ||||
| * Mic Bowman | ||||
| * Michelle Argus | ||||
| * Michael Cortez (The Flotsam Project, http://osflotsam.org/) | ||||
| * Michael Heilmann (MOSES) | ||||
| * Micheil Merlin | ||||
| * Mike Osias (IBM) | ||||
| * Mike Pitman (IBM) | ||||
| * Mike Rieker (Dreamnation) | ||||
| * mikemig | ||||
| * mikkopa/_someone - RealXtend | ||||
| * Misterblue | ||||
|  | @ -165,14 +151,12 @@ what it is today. | |||
| * openlifegrid.com | ||||
| * otakup0pe | ||||
| * Pixel Tomsen | ||||
| * Quill Littlefeather | ||||
| * ralphos | ||||
| * RemedyTomm | ||||
| * Revolution | ||||
| * Richard Alimi (IBM) | ||||
| * Rick Alther (IBM) | ||||
| * Rob Smart (IBM) | ||||
| * Robert Louden (MOSES) | ||||
| * Roger Kirkman (zadark) | ||||
| * rtomita | ||||
| * Ruud Lathorp | ||||
|  | @ -180,25 +164,17 @@ what it is today. | |||
| * Salahzar Stenvaag | ||||
| * satguru p srivastava | ||||
| * sempuki | ||||
| * Shy Robbiani | ||||
| * SignpostMarv | ||||
| * SpotOn3D | ||||
| * Stefan_Boom / stoehr | ||||
| * Steven Zielinski (MOSES) | ||||
| * Stolen Ruby  | ||||
| * Strawberry Fride | ||||
| * Talun | ||||
| * TechplexEngineer (Blake Bourque) | ||||
| * TBG Renfold | ||||
| * Terry Ford | ||||
| * tglion | ||||
| * tlaukkan/Tommil (Tommi S. E. Laukkanen, Bubble Cloud) | ||||
| * TomDataWorks | ||||
| * TomTheDragon (muckwaddle) | ||||
| * tyre | ||||
| * uriesk | ||||
| * Vegaslon <vegaslon@gmail.com> | ||||
| * Vincent Sylvester | ||||
| * VikingErik | ||||
| * Vytek | ||||
| * webmage (IBM) | ||||
|  |  | |||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							|  | @ -30,7 +30,6 @@ using System.Collections.Generic; | |||
| 
 | ||||
| using OpenSim.Framework; | ||||
| using OpenSim.Region.Framework.Interfaces; | ||||
| using OpenSim.Services.Interfaces; | ||||
| 
 | ||||
| namespace OpenSim.Groups | ||||
| { | ||||
|  |  | |||
|  | @ -46,7 +46,7 @@ namespace OpenSim.Groups | |||
|         public string AccessToken; | ||||
|     } | ||||
| 
 | ||||
|     public class ExtendedGroupMembersData | ||||
|     public class ExtendedGroupMembersData  | ||||
|     { | ||||
|         // This is the only difference: this is a string | ||||
|         public string AgentID; | ||||
|  | @ -65,7 +65,7 @@ namespace OpenSim.Groups | |||
|         public UUID RoleID; | ||||
|         // This is the only difference: this is a string | ||||
|         public string MemberID; | ||||
| 
 | ||||
|      | ||||
|     } | ||||
| 
 | ||||
|     public struct ExtendedGroupNoticeData | ||||
|  |  | |||
|  | @ -131,7 +131,7 @@ namespace OpenSim.Groups | |||
|         { | ||||
|             if (!m_groupMessagingEnabled) | ||||
|                 return; | ||||
| 
 | ||||
|              | ||||
|             scene.RegisterModuleInterface<IGroupsMessagingModule>(this); | ||||
|             m_sceneList.Add(scene); | ||||
| 
 | ||||
|  | @ -163,7 +163,7 @@ namespace OpenSim.Groups | |||
|             if (m_groupData == null) | ||||
|             { | ||||
|                 m_log.Error("[Groups.Messaging]: Could not get IGroupsServicesConnector, GroupsMessagingModule is now disabled."); | ||||
|                 RemoveRegion(scene); | ||||
|                 RemoveRegion(scene);  | ||||
|                 return; | ||||
|             } | ||||
| 
 | ||||
|  | @ -218,7 +218,7 @@ namespace OpenSim.Groups | |||
|             m_msgTransferModule = null; | ||||
|         } | ||||
| 
 | ||||
|         public Type ReplaceableInterface | ||||
|         public Type ReplaceableInterface  | ||||
|         { | ||||
|             get { return null; } | ||||
|         } | ||||
|  | @ -252,7 +252,7 @@ namespace OpenSim.Groups | |||
| 
 | ||||
|             m_debugEnabled = verbose; | ||||
| 
 | ||||
|             MainConsole.Instance.Output("{0} verbose logging set to {1}", Name, m_debugEnabled); | ||||
|             MainConsole.Instance.OutputFormat("{0} verbose logging set to {1}", Name, m_debugEnabled); | ||||
|         } | ||||
| 
 | ||||
|         /// <summary> | ||||
|  | @ -262,7 +262,7 @@ namespace OpenSim.Groups | |||
|         { | ||||
|             if (m_debugEnabled) | ||||
|                 m_log.DebugFormat("[Groups.Messaging]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); | ||||
| 
 | ||||
|                  | ||||
|             GroupRecord groupInfo = m_groupData.GetGroupRecord(agentID.ToString(), groupID, null); | ||||
| 
 | ||||
|             if (groupInfo != null) | ||||
|  | @ -279,7 +279,7 @@ namespace OpenSim.Groups | |||
|         { | ||||
|             SendMessageToGroup(im, groupID, UUID.Zero, null); | ||||
|         } | ||||
| 
 | ||||
|          | ||||
|         public void SendMessageToGroup( | ||||
|             GridInstantMessage im, UUID groupID, UUID sendingAgentForGroupCalls, Func<GroupMembersData, bool> sendCondition) | ||||
|         { | ||||
|  | @ -355,9 +355,9 @@ namespace OpenSim.Groups | |||
|                 { | ||||
|                     if (!sendCondition(member)) | ||||
|                     { | ||||
|                         if (m_debugEnabled) | ||||
|                         if (m_debugEnabled)  | ||||
|                             m_log.DebugFormat( | ||||
|                                 "[Groups.Messaging]: Not sending to {0} as they do not fulfill send condition", | ||||
|                                 "[Groups.Messaging]: Not sending to {0} as they do not fulfill send condition",  | ||||
|                                  member.AgentID); | ||||
| 
 | ||||
|                         continue; | ||||
|  | @ -366,7 +366,7 @@ namespace OpenSim.Groups | |||
|                 else if (hasAgentDroppedGroupChatSession(member.AgentID.ToString(), groupID)) | ||||
|                 { | ||||
|                     // Don't deliver messages to people who have dropped this session | ||||
|                     if (m_debugEnabled) | ||||
|                     if (m_debugEnabled)  | ||||
|                         m_log.DebugFormat("[Groups.Messaging]: {0} has dropped session, not delivering to them", member.AgentID); | ||||
| 
 | ||||
|                     continue; | ||||
|  | @ -414,7 +414,7 @@ namespace OpenSim.Groups | |||
|                     "[Groups.Messaging]: SendMessageToGroup for group {0} with {1} visible members, {2} online took {3}ms", | ||||
|                     groupID, groupMembersCount, groupMembers.Count(), Environment.TickCount - requestStartTick); | ||||
|         } | ||||
| 
 | ||||
|          | ||||
|         #region SimGridEventHandlers | ||||
| 
 | ||||
|         void OnClientLogin(IClientAPI client) | ||||
|  | @ -445,13 +445,13 @@ namespace OpenSim.Groups | |||
|             // The instant message module will only deliver messages of dialog types: | ||||
|             // MessageFromAgent, StartTyping, StopTyping, MessageFromObject | ||||
|             // | ||||
|             // Any other message type will not be delivered to a client by the | ||||
|             // Any other message type will not be delivered to a client by the  | ||||
|             // Instant Message Module | ||||
| 
 | ||||
|             UUID regionID = new UUID(msg.RegionID); | ||||
|             if (m_debugEnabled) | ||||
|             { | ||||
|                 m_log.DebugFormat("[Groups.Messaging]: {0} called, IM from region {1}", | ||||
|                 m_log.DebugFormat("[Groups.Messaging]: {0} called, IM from region {1}",  | ||||
|                     System.Reflection.MethodBase.GetCurrentMethod().Name, regionID); | ||||
| 
 | ||||
|                 DebugGridInstantMessage(msg); | ||||
|  | @ -508,7 +508,7 @@ namespace OpenSim.Groups | |||
|                                             m_log.DebugFormat("[Groups.Messaging]: skipping agent {0} because he has an agent in region of origin", sp.UUID); | ||||
|                                         return; | ||||
|                                     } | ||||
|                                     else | ||||
|                                     else                                 | ||||
|                                     { | ||||
|                                         if (m_debugEnabled) | ||||
|                                             m_log.DebugFormat("[Groups.Messaging]: not skipping agent {0}", sp.UUID); | ||||
|  | @ -531,7 +531,7 @@ namespace OpenSim.Groups | |||
|                                 } | ||||
|                             } | ||||
|                         }); | ||||
| 
 | ||||
|                          | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | @ -555,7 +555,7 @@ namespace OpenSim.Groups | |||
|                     break; | ||||
| 
 | ||||
|                 case (byte)InstantMessageDialog.SessionSend: | ||||
|                     // User hasn't dropped, so they're in the session, | ||||
|                     // User hasn't dropped, so they're in the session,  | ||||
|                     // maybe we should deliver it. | ||||
|                     IClientAPI client = GetActiveClient(new UUID(msg.toAgentID)); | ||||
|                     if (client != null) | ||||
|  | @ -599,34 +599,35 @@ namespace OpenSim.Groups | |||
|                 { | ||||
|                     if (m_debugEnabled) m_log.DebugFormat("[Groups.Messaging]: Sending chatterbox invite instant message"); | ||||
| 
 | ||||
|                     UUID fromAgent = new UUID(msg.fromAgentID); | ||||
|                     // Force? open the group session dialog??? | ||||
|                     // and simultanously deliver the message, so we don't need to do a seperate client.SendInstantMessage(msg); | ||||
|                     IEventQueue eq = activeClient.Scene.RequestModuleInterface<IEventQueue>(); | ||||
|                     if (eq != null) | ||||
|                     { | ||||
|                         eq.ChatterboxInvitation( | ||||
|                             GroupID | ||||
|                             , groupInfo.GroupName | ||||
|                             , fromAgent | ||||
|                             , msg.message | ||||
|                             , AgentID | ||||
|                             , msg.fromAgentName | ||||
|                             , msg.dialog | ||||
|                             , msg.timestamp | ||||
|                             , msg.offline == 1 | ||||
|                             , (int)msg.ParentEstateID | ||||
|                             , msg.Position | ||||
|                             , 1 | ||||
|                             , new UUID(msg.imSessionID) | ||||
|                             , msg.fromGroup | ||||
|                             , OpenMetaverse.Utils.StringToBytes(groupInfo.GroupName) | ||||
|                             ); | ||||
|                     eq.ChatterboxInvitation( | ||||
|                         GroupID | ||||
|                         , groupInfo.GroupName | ||||
|                         , new UUID(msg.fromAgentID) | ||||
|                         , msg.message | ||||
|                         , AgentID | ||||
|                         , msg.fromAgentName | ||||
|                         , msg.dialog | ||||
|                         , msg.timestamp | ||||
|                         , msg.offline == 1 | ||||
|                         , (int)msg.ParentEstateID | ||||
|                         , msg.Position | ||||
|                         , 1 | ||||
|                         , new UUID(msg.imSessionID) | ||||
|                         , msg.fromGroup | ||||
|                         , OpenMetaverse.Utils.StringToBytes(groupInfo.GroupName) | ||||
|                         ); | ||||
| 
 | ||||
|                         var update = new GroupChatListAgentUpdateData(AgentID); | ||||
|                         var updates = new List<GroupChatListAgentUpdateData> { update }; | ||||
|                         eq.ChatterBoxSessionAgentListUpdates(GroupID, new UUID(msg.toAgentID), updates); | ||||
|                     } | ||||
|                     eq.ChatterBoxSessionAgentListUpdates( | ||||
|                         new UUID(GroupID) | ||||
|                         , AgentID | ||||
|                         , new UUID(msg.toAgentID) | ||||
|                         , false //canVoiceChat | ||||
|                         , false //isModerator | ||||
|                         , false //text mute | ||||
|                         ); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | @ -653,7 +654,7 @@ namespace OpenSim.Groups | |||
|                 UUID AgentID = new UUID(im.fromAgentID); | ||||
| 
 | ||||
|                 GroupRecord groupInfo = m_groupData.GetGroupRecord(UUID.Zero.ToString(), GroupID, null); | ||||
| 
 | ||||
|      | ||||
|                 if (groupInfo != null) | ||||
|                 { | ||||
|                     AgentInvitedToGroupChatSession(AgentID.ToString(), GroupID); | ||||
|  | @ -661,12 +662,14 @@ namespace OpenSim.Groups | |||
|                     ChatterBoxSessionStartReplyViaCaps(remoteClient, groupInfo.GroupName, GroupID); | ||||
| 
 | ||||
|                     IEventQueue queue = remoteClient.Scene.RequestModuleInterface<IEventQueue>(); | ||||
|                     if (queue != null) | ||||
|                     { | ||||
|                         var update = new GroupChatListAgentUpdateData(AgentID); | ||||
|                         var updates = new List<GroupChatListAgentUpdateData> { update }; | ||||
|                         queue.ChatterBoxSessionAgentListUpdates(GroupID, remoteClient.AgentId, updates); | ||||
|                     } | ||||
|                     queue.ChatterBoxSessionAgentListUpdates( | ||||
|                         GroupID | ||||
|                         , AgentID | ||||
|                         , new UUID(im.toAgentID) | ||||
|                         , false //canVoiceChat | ||||
|                         , false //isModerator | ||||
|                         , false //text mute | ||||
|                         ); | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|  | @ -676,7 +679,7 @@ namespace OpenSim.Groups | |||
|                 UUID GroupID = new UUID(im.imSessionID); | ||||
|                 UUID AgentID = new UUID(im.fromAgentID); | ||||
| 
 | ||||
|                 if (m_debugEnabled) | ||||
|                 if (m_debugEnabled)  | ||||
|                     m_log.DebugFormat("[Groups.Messaging]: Send message to session for group {0} with session ID {1}", GroupID, im.imSessionID.ToString()); | ||||
| 
 | ||||
|                 //If this agent is sending a message, then they want to be in the session | ||||
|  | @ -708,7 +711,11 @@ namespace OpenSim.Groups | |||
|             bodyMap.Add("session_info", sessionMap); | ||||
| 
 | ||||
|             IEventQueue queue = remoteClient.Scene.RequestModuleInterface<IEventQueue>(); | ||||
|             queue?.Enqueue(queue.BuildEvent("ChatterBoxSessionStartReply", bodyMap), remoteClient.AgentId); | ||||
| 
 | ||||
|             if (queue != null) | ||||
|             { | ||||
|                 queue.Enqueue(queue.BuildEvent("ChatterBoxSessionStartReply", bodyMap), remoteClient.AgentId); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         private void DebugGridInstantMessage(GridInstantMessage im) | ||||
|  |  | |||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							|  | @ -103,7 +103,7 @@ namespace OpenSim.Groups | |||
|             if (!m_Enabled) | ||||
|                 return; | ||||
| 
 | ||||
|             m_log.DebugFormat("[Groups]: Registering {0} with {1}", this.Name, scene.RegionInfo.RegionName); | ||||
|             m_log.DebugFormat("[Groups]: Registering {0} with {1}", this.Name, scene.RegionInfo.RegionName);  | ||||
|             scene.RegisterModuleInterface<IGroupsServicesConnector>(this); | ||||
|             m_Scenes.Add(scene); | ||||
| 
 | ||||
|  | @ -135,7 +135,7 @@ namespace OpenSim.Groups | |||
|                 { | ||||
|                     m_LocalGroupsConnector = new GroupsServiceLocalConnectorModule(m_Config, m_UserManagement); | ||||
|                     // Also, if local, create the endpoint for the HGGroupsService | ||||
|                     new HGGroupsServiceRobustConnector(m_Config, MainServer.Instance, string.Empty, | ||||
|                     new HGGroupsServiceRobustConnector(m_Config, MainServer.Instance, string.Empty,  | ||||
|                         scene.RequestModuleInterface<IOfflineIMService>(), scene.RequestModuleInterface<IUserAccountService>()); | ||||
| 
 | ||||
|                 } | ||||
|  | @ -170,7 +170,7 @@ namespace OpenSim.Groups | |||
|                 if (sp is ScenePresence && ((ScenePresence)sp).PresenceType != PresenceType.Npc) | ||||
|                 { | ||||
|                     AgentCircuitData aCircuit = ((ScenePresence)sp).Scene.AuthenticateHandler.GetAgentCircuitData(client.AgentId); | ||||
|                     if (aCircuit != null && (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaHGLogin) != 0 && | ||||
|                     if (aCircuit != null && (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaHGLogin) != 0 &&  | ||||
|                         m_OfflineIM != null && m_Messaging != null) | ||||
|                     { | ||||
|                         List<GridInstantMessage> ims = m_OfflineIM.GetMessages(aCircuit.AgentID); | ||||
|  | @ -184,12 +184,12 @@ namespace OpenSim.Groups | |||
| 
 | ||||
|         #region IGroupsServicesConnector | ||||
| 
 | ||||
|         public UUID CreateGroup(UUID RequestingAgentID, string name, string charter, bool showInList, UUID insigniaID, int membershipFee, bool openEnrollment, | ||||
|         public UUID CreateGroup(UUID RequestingAgentID, string name, string charter, bool showInList, UUID insigniaID, int membershipFee, bool openEnrollment,  | ||||
|             bool allowPublish, bool maturePublish, UUID founderID, out string reason) | ||||
|         { | ||||
|             reason = string.Empty; | ||||
|             if (m_UserManagement.IsLocalGridUser(RequestingAgentID)) | ||||
|                 return m_LocalGroupsConnector.CreateGroup(RequestingAgentID, name, charter, showInList, insigniaID, | ||||
|                 return m_LocalGroupsConnector.CreateGroup(RequestingAgentID, name, charter, showInList, insigniaID,  | ||||
|                     membershipFee, openEnrollment, allowPublish, maturePublish, founderID, out reason); | ||||
|             else | ||||
|             { | ||||
|  | @ -198,14 +198,14 @@ namespace OpenSim.Groups | |||
|             } | ||||
|         } | ||||
| 
 | ||||
|         public bool UpdateGroup(string RequestingAgentID, UUID groupID, string charter, bool showInList, UUID insigniaID, int membershipFee, | ||||
|         public bool UpdateGroup(string RequestingAgentID, UUID groupID, string charter, bool showInList, UUID insigniaID, int membershipFee,  | ||||
|             bool openEnrollment, bool allowPublish, bool maturePublish, out string reason) | ||||
|         { | ||||
|             reason = string.Empty; | ||||
|             string url = string.Empty; | ||||
|             string name = string.Empty; | ||||
|             if (IsLocal(groupID, out url, out name)) | ||||
|                 return m_LocalGroupsConnector.UpdateGroup(AgentUUI(RequestingAgentID), groupID, charter, showInList, insigniaID, membershipFee, | ||||
|                 return m_LocalGroupsConnector.UpdateGroup(AgentUUI(RequestingAgentID), groupID, charter, showInList, insigniaID, membershipFee,  | ||||
|                     openEnrollment, allowPublish, maturePublish, out reason); | ||||
|             else | ||||
|             { | ||||
|  | @ -246,9 +246,9 @@ namespace OpenSim.Groups | |||
|             return null; | ||||
|         } | ||||
| 
 | ||||
|         public List<DirGroupsReplyData> FindGroups(string RequestingAgentIDstr, string search) | ||||
|         public List<DirGroupsReplyData> FindGroups(string RequestingAgentID, string search) | ||||
|         { | ||||
|             return m_LocalGroupsConnector.FindGroups(RequestingAgentIDstr, search); | ||||
|             return m_LocalGroupsConnector.FindGroups(AgentUUI(RequestingAgentID), search); | ||||
|         } | ||||
| 
 | ||||
|         public List<GroupMembersData> GetGroupMembers(string RequestingAgentID, UUID GroupID) | ||||
|  | @ -374,7 +374,7 @@ namespace OpenSim.Groups | |||
| 
 | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|              | ||||
|             return new List<GroupRoleMembersData>(); | ||||
|         } | ||||
| 
 | ||||
|  | @ -605,8 +605,14 @@ namespace OpenSim.Groups | |||
|         private string AgentUUI(string AgentIDStr) | ||||
|         { | ||||
|             UUID AgentID = UUID.Zero; | ||||
|             if (!UUID.TryParse(AgentIDStr, out AgentID) || AgentID == UUID.Zero) | ||||
|                 return UUID.Zero.ToString(); | ||||
|             try | ||||
|             { | ||||
|                 AgentID = new UUID(AgentIDStr); | ||||
|             } | ||||
|             catch (FormatException) | ||||
|             { | ||||
|                 return AgentID.ToString(); | ||||
|             } | ||||
| 
 | ||||
|             if (m_UserManagement.IsLocalGridUser(AgentID)) | ||||
|                 return AgentID.ToString(); | ||||
|  | @ -620,7 +626,7 @@ namespace OpenSim.Groups | |||
|             } | ||||
|             if (agent != null) | ||||
|                 return Util.ProduceUserUniversalIdentifier(agent); | ||||
| 
 | ||||
|              | ||||
|             // we don't know anything about this foreign user | ||||
|             // try asking the user management module, which may know more | ||||
|             return m_UserManagement.GetUserUUI(AgentID); | ||||
|  | @ -630,8 +636,14 @@ namespace OpenSim.Groups | |||
|         private string AgentUUIForOutside(string AgentIDStr) | ||||
|         { | ||||
|             UUID AgentID = UUID.Zero; | ||||
|             if (!UUID.TryParse(AgentIDStr, out AgentID) || AgentID == UUID.Zero) | ||||
|                 return UUID.Zero.ToString(); | ||||
|             try | ||||
|             { | ||||
|                 AgentID = new UUID(AgentIDStr); | ||||
|             } | ||||
|             catch (FormatException) | ||||
|             { | ||||
|                 return AgentID.ToString(); | ||||
|             } | ||||
| 
 | ||||
|             AgentCircuitData agent = null; | ||||
|             foreach (Scene scene in m_Scenes) | ||||
|  | @ -652,7 +664,7 @@ namespace OpenSim.Groups | |||
|             string url = string.Empty, first = string.Empty, last = string.Empty, tmp = string.Empty; | ||||
|             if (Util.ParseUniversalUserIdentifier(uID, out userID, out url, out first, out last, out tmp)) | ||||
|                 m_UserManagement.AddUser(userID, first, last, url); | ||||
| 
 | ||||
|              | ||||
|             return userID; | ||||
|         } | ||||
| 
 | ||||
|  |  | |||
|  | @ -64,8 +64,8 @@ namespace OpenSim.Groups | |||
| 
 | ||||
|             m_log.DebugFormat("[Groups.RobustHGConnector]: Starting with config name {0}", m_ConfigName); | ||||
| 
 | ||||
|             string homeURI = Util.GetConfigVarFromSections<string>(config, "HomeURI", | ||||
|                 new string[] { "Startup", "Hypergrid", m_ConfigName}, string.Empty); | ||||
|             string homeURI = Util.GetConfigVarFromSections<string>(config, "HomeURI",  | ||||
|                 new string[] { "Startup", "Hypergrid", m_ConfigName}, string.Empty);  | ||||
|             if (homeURI == string.Empty) | ||||
|                 throw new Exception(String.Format("[Groups.RobustHGConnector]: please provide the HomeURI [Startup] or in section {0}", m_ConfigName)); | ||||
| 
 | ||||
|  | @ -115,10 +115,9 @@ namespace OpenSim.Groups | |||
|         protected override byte[] ProcessRequest(string path, Stream requestData, | ||||
|                 IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) | ||||
|         { | ||||
|             string body; | ||||
|             using(StreamReader sr = new StreamReader(requestData)) | ||||
|                 body = sr.ReadToEnd(); | ||||
| 
 | ||||
|             StreamReader sr = new StreamReader(requestData); | ||||
|             string body = sr.ReadToEnd(); | ||||
|             sr.Close(); | ||||
|             body = body.Trim(); | ||||
| 
 | ||||
|             //m_log.DebugFormat("[XXX]: query String: {0}", body); | ||||
|  |  | |||
|  | @ -34,12 +34,12 @@ namespace OpenSim.Groups | |||
| { | ||||
|     public interface IGroupsServicesConnector | ||||
|     { | ||||
|         UUID CreateGroup(UUID RequestingAgentID, string name, string charter, bool showInList, UUID insigniaID, int membershipFee, | ||||
|         UUID CreateGroup(UUID RequestingAgentID, string name, string charter, bool showInList, UUID insigniaID, int membershipFee,  | ||||
|             bool openEnrollment, bool allowPublish, bool maturePublish, UUID founderID, out string reason); | ||||
|         bool UpdateGroup(string RequestingAgentID, UUID groupID, string charter, bool showInList, UUID insigniaID, int membershipFee, | ||||
|         bool UpdateGroup(string RequestingAgentID, UUID groupID, string charter, bool showInList, UUID insigniaID, int membershipFee,  | ||||
|             bool openEnrollment, bool allowPublish, bool maturePublish, out string reason); | ||||
|         ExtendedGroupRecord GetGroupRecord(string RequestingAgentID, UUID GroupID, string GroupName); | ||||
|         List<DirGroupsReplyData> FindGroups(string RequestingAgentIDstr, string search); | ||||
|         List<DirGroupsReplyData> FindGroups(string RequestingAgentID, string search); | ||||
|         List<GroupMembersData> GetGroupMembers(string RequestingAgentID, UUID GroupID); | ||||
| 
 | ||||
|         bool AddGroupRole(string RequestingAgentID, UUID groupID, UUID roleID, string name, string description, string title, ulong powers, out string reason); | ||||
|  | @ -75,7 +75,7 @@ namespace OpenSim.Groups | |||
|         /// If the user is a member of the group then the data structure is returned.  If not, then null is returned. | ||||
|         /// </returns> | ||||
|         ExtendedGroupMembershipData GetAgentGroupMembership(string RequestingAgentID, string AgentID, UUID GroupID); | ||||
| 
 | ||||
|          | ||||
|         /// <summary> | ||||
|         /// Get information about the groups to which a user belongs. | ||||
|         /// </summary> | ||||
|  | @ -87,7 +87,7 @@ namespace OpenSim.Groups | |||
|         /// </returns> | ||||
|         List<GroupMembershipData> GetAgentGroupMemberships(string RequestingAgentID, string AgentID); | ||||
| 
 | ||||
|         bool AddGroupNotice(string RequestingAgentID, UUID groupID, UUID noticeID, string fromName, string subject, string message, | ||||
|         bool AddGroupNotice(string RequestingAgentID, UUID groupID, UUID noticeID, string fromName, string subject, string message,  | ||||
|             bool hasAttachment, byte attType, string attName, UUID attItemID, string attOwnerID); | ||||
|         GroupNoticeInfo GetGroupNotice(string RequestingAgentID, UUID noticeID); | ||||
|         List<ExtendedGroupNoticeData> GetGroupNotices(string RequestingAgentID, UUID GroupID); | ||||
|  |  | |||
|  | @ -34,7 +34,6 @@ using System.Text; | |||
| using OpenSim.Framework; | ||||
| using OpenSim.Region.Framework.Scenes; | ||||
| using OpenSim.Region.Framework.Interfaces; | ||||
| using OpenSim.Services.Interfaces; | ||||
| 
 | ||||
| using OpenMetaverse; | ||||
| using Mono.Addins; | ||||
|  | @ -108,7 +107,7 @@ namespace OpenSim.Groups | |||
|             if (!m_Enabled) | ||||
|                 return; | ||||
| 
 | ||||
|             m_log.DebugFormat("[Groups]: Registering {0} with {1}", this.Name, scene.RegionInfo.RegionName); | ||||
|             m_log.DebugFormat("[Groups]: Registering {0} with {1}", this.Name, scene.RegionInfo.RegionName);  | ||||
|             scene.RegisterModuleInterface<IGroupsServicesConnector>(this); | ||||
|             m_Scenes.Add(scene); | ||||
|         } | ||||
|  | @ -146,16 +145,16 @@ namespace OpenSim.Groups | |||
| 
 | ||||
|         #region IGroupsServicesConnector | ||||
| 
 | ||||
|         public UUID CreateGroup(UUID RequestingAgentID, string name, string charter, bool showInList, UUID insigniaID, int membershipFee, bool openEnrollment, | ||||
|         public UUID CreateGroup(UUID RequestingAgentID, string name, string charter, bool showInList, UUID insigniaID, int membershipFee, bool openEnrollment,  | ||||
|             bool allowPublish, bool maturePublish, UUID founderID, out string reason) | ||||
|         { | ||||
|             m_log.DebugFormat("[Groups]: Creating group {0}", name); | ||||
|             reason = string.Empty; | ||||
|             return m_GroupsService.CreateGroup(RequestingAgentID.ToString(), name, charter, showInList, insigniaID, | ||||
|             return m_GroupsService.CreateGroup(RequestingAgentID.ToString(), name, charter, showInList, insigniaID,  | ||||
|                     membershipFee, openEnrollment, allowPublish, maturePublish, founderID, out reason); | ||||
|         } | ||||
| 
 | ||||
|         public bool UpdateGroup(string RequestingAgentID, UUID groupID, string charter, bool showInList, UUID insigniaID, int membershipFee, | ||||
|         public bool UpdateGroup(string RequestingAgentID, UUID groupID, string charter, bool showInList, UUID insigniaID, int membershipFee,  | ||||
|             bool openEnrollment, bool allowPublish, bool maturePublish, out string reason) | ||||
|         { | ||||
|             reason = string.Empty; | ||||
|  | @ -173,9 +172,9 @@ namespace OpenSim.Groups | |||
|             return null; | ||||
|         } | ||||
| 
 | ||||
|         public List<DirGroupsReplyData> FindGroups(string RequestingAgentIDstr, string search) | ||||
|         public List<DirGroupsReplyData> FindGroups(string RequestingAgentID, string search) | ||||
|         { | ||||
|             return m_GroupsService.FindGroups(RequestingAgentIDstr, search); | ||||
|             return m_GroupsService.FindGroups(RequestingAgentID, search); | ||||
|         } | ||||
| 
 | ||||
|         public List<GroupMembersData> GetGroupMembers(string RequestingAgentID, UUID GroupID) | ||||
|  | @ -296,7 +295,7 @@ namespace OpenSim.Groups | |||
|         public bool AddGroupNotice(string RequestingAgentID, UUID groupID, UUID noticeID, string fromName, string subject, string message, | ||||
|             bool hasAttachment, byte attType, string attName, UUID attItemID, string attOwnerID) | ||||
|         { | ||||
|             return m_GroupsService.AddGroupNotice(RequestingAgentID, groupID, noticeID, fromName, subject, message, | ||||
|             return m_GroupsService.AddGroupNotice(RequestingAgentID, groupID, noticeID, fromName, subject, message,  | ||||
|                 hasAttachment, attType, attName, attItemID, attOwnerID); | ||||
|         } | ||||
| 
 | ||||
|  |  | |||
|  | @ -3,7 +3,7 @@ using System.Runtime.CompilerServices; | |||
| using System.Runtime.InteropServices; | ||||
| using Mono.Addins; | ||||
| 
 | ||||
| // General Information about an assembly is controlled through the following | ||||
| // General Information about an assembly is controlled through the following  | ||||
| // set of attributes. Change these attribute values to modify the information | ||||
| // associated with an assembly. | ||||
| [assembly: AssemblyTitle("OpenSim.Addons.Groups")] | ||||
|  | @ -15,8 +15,8 @@ using Mono.Addins; | |||
| [assembly: AssemblyTrademark("")] | ||||
| [assembly: AssemblyCulture("")] | ||||
| 
 | ||||
| // Setting ComVisible to false makes the types in this assembly not visible | ||||
| // to COM components.  If you need to access a type in this assembly from | ||||
| // Setting ComVisible to false makes the types in this assembly not visible  | ||||
| // to COM components.  If you need to access a type in this assembly from  | ||||
| // COM, set the ComVisible attribute to true on that type. | ||||
| [assembly: ComVisible(false)] | ||||
| 
 | ||||
|  | @ -26,11 +26,11 @@ using Mono.Addins; | |||
| // Version information for an assembly consists of the following four values: | ||||
| // | ||||
| //      Major Version | ||||
| //      Minor Version | ||||
| //      Minor Version  | ||||
| //      Build Number | ||||
| //      Revision | ||||
| // | ||||
| [assembly: AssemblyVersion(OpenSim.VersionInfo.AssemblyVersionNumber)] | ||||
| [assembly: AssemblyVersion("0.8.1.*")] | ||||
| 
 | ||||
| [assembly: Addin("OpenSim.Groups", OpenSim.VersionInfo.VersionNumber)] | ||||
| [assembly: AddinDependency("OpenSim.Region.Framework", OpenSim.VersionInfo.VersionNumber)] | ||||
| [assembly: Addin("OpenSim.Groups", "0.1")] | ||||
| [assembly: AddinDependency("OpenSim", "0.5")] | ||||
|  |  | |||
|  | @ -41,7 +41,7 @@ using Nini.Config; | |||
| 
 | ||||
| namespace OpenSim.Groups | ||||
| { | ||||
|     public class GroupsServiceRemoteConnector | ||||
|     public class GroupsServiceRemoteConnector  | ||||
|     { | ||||
|         private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | ||||
| 
 | ||||
|  | @ -71,7 +71,7 @@ namespace OpenSim.Groups | |||
|             } | ||||
|             /// | ||||
| 
 | ||||
|             m_log.DebugFormat("[Groups.RemoteConnector]: Groups server at {0}, authentication {1}", | ||||
|             m_log.DebugFormat("[Groups.RemoteConnector]: Groups server at {0}, authentication {1}",  | ||||
|                 m_ServerURI, (m_Auth == null ? "None" : m_Auth.GetType().ToString())); | ||||
|         } | ||||
| 
 | ||||
|  | @ -153,7 +153,7 @@ namespace OpenSim.Groups | |||
|             return GroupsDataUtils.GroupRecord((Dictionary<string, object>)ret["RESULT"]); | ||||
|         } | ||||
| 
 | ||||
|         public List<DirGroupsReplyData> FindGroups(string RequestingAgentIDstr, string query) | ||||
|         public List<DirGroupsReplyData> FindGroups(string RequestingAgentID, string query) | ||||
|         { | ||||
|             List<DirGroupsReplyData> hits = new List<DirGroupsReplyData>(); | ||||
|             if (string.IsNullOrEmpty(query)) | ||||
|  | @ -161,7 +161,7 @@ namespace OpenSim.Groups | |||
| 
 | ||||
|             Dictionary<string, object> sendData = new Dictionary<string, object>(); | ||||
|             sendData["Query"] = query; | ||||
|             sendData["RequestingAgentID"] = RequestingAgentIDstr; | ||||
|             sendData["RequestingAgentID"] = RequestingAgentID; | ||||
| 
 | ||||
|             Dictionary<string, object> ret = MakeRequest("FINDGROUPS", sendData); | ||||
| 
 | ||||
|  |  | |||
|  | @ -36,7 +36,6 @@ using OpenSim.Framework; | |||
| using OpenSim.Region.Framework.Scenes; | ||||
| using OpenSim.Region.Framework.Interfaces; | ||||
| using OpenSim.Server.Base; | ||||
| using OpenSim.Services.Interfaces; | ||||
| 
 | ||||
| using OpenMetaverse; | ||||
| using Mono.Addins; | ||||
|  | @ -113,7 +112,7 @@ namespace OpenSim.Groups | |||
|             if (!m_Enabled) | ||||
|                 return; | ||||
| 
 | ||||
|             m_log.DebugFormat("[Groups.RemoteConnector]: Registering {0} with {1}", this.Name, scene.RegionInfo.RegionName); | ||||
|             m_log.DebugFormat("[Groups.RemoteConnector]: Registering {0} with {1}", this.Name, scene.RegionInfo.RegionName);  | ||||
|             scene.RegisterModuleInterface<IGroupsServicesConnector>(this); | ||||
|             m_Scenes.Add(scene); | ||||
|         } | ||||
|  | @ -151,7 +150,7 @@ namespace OpenSim.Groups | |||
| 
 | ||||
|         #region IGroupsServicesConnector | ||||
| 
 | ||||
|         public UUID CreateGroup(UUID RequestingAgentID, string name, string charter, bool showInList, UUID insigniaID, int membershipFee, bool openEnrollment, | ||||
|         public UUID CreateGroup(UUID RequestingAgentID, string name, string charter, bool showInList, UUID insigniaID, int membershipFee, bool openEnrollment,  | ||||
|             bool allowPublish, bool maturePublish, UUID founderID, out string reason) | ||||
|         { | ||||
|             m_log.DebugFormat("[Groups.RemoteConnector]: Creating group {0}", name); | ||||
|  | @ -167,7 +166,7 @@ namespace OpenSim.Groups | |||
|             return groupID; | ||||
|         } | ||||
| 
 | ||||
|         public bool UpdateGroup(string RequestingAgentID, UUID groupID, string charter, bool showInList, UUID insigniaID, int membershipFee, | ||||
|         public bool UpdateGroup(string RequestingAgentID, UUID groupID, string charter, bool showInList, UUID insigniaID, int membershipFee,  | ||||
|             bool openEnrollment, bool allowPublish, bool maturePublish, out string reason) | ||||
|         { | ||||
|             string r = string.Empty; | ||||
|  | @ -186,16 +185,16 @@ namespace OpenSim.Groups | |||
|             if (GroupID == UUID.Zero && (GroupName == null || GroupName != null && GroupName == string.Empty)) | ||||
|                 return null; | ||||
| 
 | ||||
|             return m_CacheWrapper.GetGroupRecord(RequestingAgentID,GroupID,GroupName, delegate | ||||
|             { | ||||
|                 return m_GroupsService.GetGroupRecord(RequestingAgentID, GroupID, GroupName); | ||||
|             return m_CacheWrapper.GetGroupRecord(RequestingAgentID,GroupID,GroupName, delegate  | ||||
|             {  | ||||
|                 return m_GroupsService.GetGroupRecord(RequestingAgentID, GroupID, GroupName);  | ||||
|             }); | ||||
|         } | ||||
| 
 | ||||
|         public List<DirGroupsReplyData> FindGroups(string RequestingAgentIDstr, string search) | ||||
|         public List<DirGroupsReplyData> FindGroups(string RequestingAgentID, string search) | ||||
|         { | ||||
|             // TODO! | ||||
|             return m_GroupsService.FindGroups(RequestingAgentIDstr, search); | ||||
|             return m_GroupsService.FindGroups(RequestingAgentID, search); | ||||
|         } | ||||
| 
 | ||||
|         public bool AddAgentToGroup(string RequestingAgentID, string AgentID, UUID GroupID, UUID RoleID, string token, out string reason) | ||||
|  | @ -362,7 +361,7 @@ namespace OpenSim.Groups | |||
|             m_GroupsService.RemoveAgentToGroupInvite(RequestingAgentID, inviteID); | ||||
|         } | ||||
| 
 | ||||
|         public bool AddGroupNotice(string RequestingAgentID, UUID groupID, UUID noticeID, string fromName, string subject, string message, | ||||
|         public bool AddGroupNotice(string RequestingAgentID, UUID groupID, UUID noticeID, string fromName, string subject, string message,  | ||||
|             bool hasAttachment, byte attType, string attName, UUID attItemID, string attOwnerID) | ||||
|         { | ||||
|             GroupNoticeInfo notice = new GroupNoticeInfo(); | ||||
|  |  | |||
|  | @ -91,10 +91,9 @@ namespace OpenSim.Groups | |||
|         protected override byte[] ProcessRequest(string path, Stream requestData, | ||||
|                 IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) | ||||
|         { | ||||
|             string body; | ||||
|             using(StreamReader sr = new StreamReader(requestData)) | ||||
|                 body = sr.ReadToEnd(); | ||||
| 
 | ||||
|             StreamReader sr = new StreamReader(requestData); | ||||
|             string body = sr.ReadToEnd(); | ||||
|             sr.Close(); | ||||
|             body = body.Trim(); | ||||
| 
 | ||||
|             //m_log.DebugFormat("[XXX]: query String: {0}", body); | ||||
|  | @ -287,7 +286,7 @@ namespace OpenSim.Groups | |||
|                 string requestingAgentID = request["RequestingAgentID"].ToString(); | ||||
| 
 | ||||
|                 if (!m_GroupsService.RemoveAgentFromGroup(requestingAgentID, agentID, groupID)) | ||||
|                     NullResult(result, string.Format("Insufficient permissions. {0}", agentID)); | ||||
|                     NullResult(result, string.Format("Insufficient permissions.", agentID)); | ||||
|                 else | ||||
|                     result["RESULT"] = "true"; | ||||
|             } | ||||
|  | @ -394,7 +393,7 @@ namespace OpenSim.Groups | |||
| 
 | ||||
|             if (!request.ContainsKey("RequestingAgentID") || !request.ContainsKey("GroupID") || !request.ContainsKey("RoleID") || | ||||
|                 !request.ContainsKey("Name") || !request.ContainsKey("Description") || !request.ContainsKey("Title") || | ||||
|                 !request.ContainsKey("Powers") || !request.ContainsKey("OP")) | ||||
|                 !request.ContainsKey("Powers") || !request.ContainsKey("OP"))  | ||||
|                 NullResult(result, "Bad network data"); | ||||
| 
 | ||||
|             else | ||||
|  | @ -520,11 +519,11 @@ namespace OpenSim.Groups | |||
| 
 | ||||
|                 bool success = false; | ||||
|                 if (op == "ADD") | ||||
|                     success = m_GroupsService.AddAgentToGroupRole(request["RequestingAgentID"].ToString(), request["AgentID"].ToString(), | ||||
|                     success = m_GroupsService.AddAgentToGroupRole(request["RequestingAgentID"].ToString(), request["AgentID"].ToString(),  | ||||
|                         new UUID(request["GroupID"].ToString()), new UUID(request["RoleID"].ToString())); | ||||
| 
 | ||||
|                 else if (op == "DELETE") | ||||
|                     success = m_GroupsService.RemoveAgentFromGroupRole(request["RequestingAgentID"].ToString(), request["AgentID"].ToString(), | ||||
|                     success = m_GroupsService.RemoveAgentFromGroupRole(request["RequestingAgentID"].ToString(), request["AgentID"].ToString(),  | ||||
|                         new UUID(request["GroupID"].ToString()), new UUID(request["RoleID"].ToString())); | ||||
| 
 | ||||
|                 result["RESULT"] = success.ToString(); | ||||
|  | @ -648,8 +647,8 @@ namespace OpenSim.Groups | |||
|                 string op = request["OP"].ToString(); | ||||
| 
 | ||||
|                 if (op == "ADD" && request.ContainsKey("GroupID") && request.ContainsKey("RoleID") && request.ContainsKey("AgentID")) | ||||
|                 { | ||||
|                     bool success = m_GroupsService.AddAgentToGroupInvite(request["RequestingAgentID"].ToString(), | ||||
|                 {    | ||||
|                     bool success = m_GroupsService.AddAgentToGroupInvite(request["RequestingAgentID"].ToString(),  | ||||
|                         new UUID(request["InviteID"].ToString()), new UUID(request["GroupID"].ToString()), | ||||
|                         new UUID(request["RoleID"].ToString()), request["AgentID"].ToString()); | ||||
| 
 | ||||
|  | @ -665,7 +664,7 @@ namespace OpenSim.Groups | |||
|                 } | ||||
|                 else if (op == "GET") | ||||
|                 { | ||||
|                     GroupInviteInfo invite = m_GroupsService.GetAgentToGroupInvite(request["RequestingAgentID"].ToString(), | ||||
|                     GroupInviteInfo invite = m_GroupsService.GetAgentToGroupInvite(request["RequestingAgentID"].ToString(),  | ||||
|                         new UUID(request["InviteID"].ToString())); | ||||
| 
 | ||||
|                     if (invite != null) | ||||
|  |  | |||
|  | @ -31,8 +31,7 @@ using System.Reflection; | |||
| using System.Threading; | ||||
| 
 | ||||
| using OpenSim.Framework; | ||||
| //using OpenSim.Region.Framework.Interfaces; | ||||
| using OpenSim.Services.Interfaces; | ||||
| using OpenSim.Region.Framework.Interfaces; | ||||
| 
 | ||||
| using OpenMetaverse; | ||||
| 
 | ||||
|  | @ -145,20 +144,14 @@ namespace OpenSim.Groups | |||
| 
 | ||||
|                 if (firstCall) | ||||
|                 { | ||||
|                     try | ||||
|                     { | ||||
|                         //group = m_GroupsService.GetGroupRecord(RequestingAgentID, GroupID, GroupName); | ||||
|                         group = d(); | ||||
|                     //group = m_GroupsService.GetGroupRecord(RequestingAgentID, GroupID, GroupName); | ||||
|                     group = d(); | ||||
| 
 | ||||
|                         lock (m_Cache) | ||||
|                         { | ||||
|                             m_Cache.AddOrUpdate(cacheKey, group, GROUPS_CACHE_TIMEOUT); | ||||
|                             return (ExtendedGroupRecord)group; | ||||
|                         } | ||||
|                     } | ||||
|                     finally | ||||
|                     lock (m_Cache) | ||||
|                     { | ||||
|                         m_Cache.AddOrUpdate(cacheKey, group, GROUPS_CACHE_TIMEOUT); | ||||
|                         m_ActiveRequests.Remove(cacheKey); | ||||
|                         return (ExtendedGroupRecord)group; | ||||
|                     } | ||||
|                 } | ||||
|                 else | ||||
|  | @ -250,19 +243,13 @@ namespace OpenSim.Groups | |||
| 
 | ||||
|                 if (firstCall) | ||||
|                 { | ||||
|                     try | ||||
|                     { | ||||
|                         membership = d(); | ||||
|                     membership = d(); | ||||
| 
 | ||||
|                         lock (m_Cache) | ||||
|                         { | ||||
|                             m_Cache.AddOrUpdate(cacheKey, membership, GROUPS_CACHE_TIMEOUT); | ||||
|                             return (ExtendedGroupMembershipData)membership; | ||||
|                         } | ||||
|                     } | ||||
|                     finally | ||||
|                     lock (m_Cache) | ||||
|                     { | ||||
|                         m_Cache.AddOrUpdate(cacheKey, membership, GROUPS_CACHE_TIMEOUT); | ||||
|                         m_ActiveRequests.Remove(cacheKey); | ||||
|                         return (ExtendedGroupMembershipData)membership; | ||||
|                     } | ||||
|                 } | ||||
|                 else | ||||
|  | @ -299,18 +286,12 @@ namespace OpenSim.Groups | |||
| 
 | ||||
|                 if (firstCall) | ||||
|                 { | ||||
|                     try | ||||
|                     { | ||||
|                         membership = d(); | ||||
|                         lock (m_Cache) | ||||
|                         { | ||||
|                             m_Cache.AddOrUpdate(cacheKey, membership, GROUPS_CACHE_TIMEOUT); | ||||
|                             return (ExtendedGroupMembershipData)membership; | ||||
|                         } | ||||
|                     } | ||||
|                     finally | ||||
|                     membership = d(); | ||||
|                     lock (m_Cache) | ||||
|                     { | ||||
|                         m_Cache.AddOrUpdate(cacheKey, membership, GROUPS_CACHE_TIMEOUT); | ||||
|                         m_ActiveRequests.Remove(cacheKey); | ||||
|                         return (ExtendedGroupMembershipData)membership; | ||||
|                     } | ||||
|                 } | ||||
|                 else | ||||
|  | @ -346,18 +327,12 @@ namespace OpenSim.Groups | |||
| 
 | ||||
|                 if (firstCall) | ||||
|                 { | ||||
|                     try | ||||
|                     { | ||||
|                         memberships = d(); | ||||
|                         lock (m_Cache) | ||||
|                         { | ||||
|                             m_Cache.AddOrUpdate(cacheKey, memberships, GROUPS_CACHE_TIMEOUT); | ||||
|                             return (List<GroupMembershipData>)memberships; | ||||
|                         } | ||||
|                     } | ||||
|                     finally | ||||
|                     memberships = d(); | ||||
|                     lock (m_Cache) | ||||
|                     { | ||||
|                         m_Cache.AddOrUpdate(cacheKey, memberships, GROUPS_CACHE_TIMEOUT); | ||||
|                         m_ActiveRequests.Remove(cacheKey); | ||||
|                         return (List<GroupMembershipData>)memberships; | ||||
|                     } | ||||
|                 } | ||||
|                 else | ||||
|  | @ -394,26 +369,20 @@ namespace OpenSim.Groups | |||
| 
 | ||||
|                 if (firstCall) | ||||
|                 { | ||||
|                     try | ||||
|                     { | ||||
|                         List<ExtendedGroupMembersData> _members = d(); | ||||
| 
 | ||||
|                         if (_members != null && _members.Count > 0) | ||||
|                             members = _members.ConvertAll<GroupMembersData>(new Converter<ExtendedGroupMembersData, GroupMembersData>(m_ForeignImporter.ConvertGroupMembersData)); | ||||
|                         else | ||||
|                             members = new List<GroupMembersData>(); | ||||
| 
 | ||||
|                         lock (m_Cache) | ||||
|                         { | ||||
|                             //m_Cache.AddOrUpdate(cacheKey, members, GROUPS_CACHE_TIMEOUT); | ||||
|                             m_Cache.AddOrUpdate(cacheKey, _members, GROUPS_CACHE_TIMEOUT); | ||||
| 
 | ||||
|                             return (List<GroupMembersData>)members; | ||||
|                         } | ||||
|                     } | ||||
|                     finally | ||||
|                     List<ExtendedGroupMembersData> _members = d(); | ||||
| 
 | ||||
|                     if (_members != null && _members.Count > 0) | ||||
|                         members = _members.ConvertAll<GroupMembersData>(new Converter<ExtendedGroupMembersData, GroupMembersData>(m_ForeignImporter.ConvertGroupMembersData)); | ||||
|                     else | ||||
|                         members = new List<GroupMembersData>(); | ||||
| 
 | ||||
|                     lock (m_Cache) | ||||
|                     { | ||||
|                         //m_Cache.AddOrUpdate(cacheKey, members, GROUPS_CACHE_TIMEOUT); | ||||
|                         m_Cache.AddOrUpdate(cacheKey, _members, GROUPS_CACHE_TIMEOUT); | ||||
|                         m_ActiveRequests.Remove(cacheKey); | ||||
| 
 | ||||
|                         return (List<GroupMembersData>)members; | ||||
|                     } | ||||
|                 } | ||||
|                 else | ||||
|  | @ -528,22 +497,16 @@ namespace OpenSim.Groups | |||
| 
 | ||||
|                 if (firstCall) | ||||
|                 { | ||||
|                     try | ||||
|                     roles = d(); | ||||
|                     if (roles != null) | ||||
|                     { | ||||
|                         roles = d(); | ||||
|                         if (roles != null) | ||||
|                         lock (m_Cache) | ||||
|                         { | ||||
|                             lock (m_Cache) | ||||
|                             { | ||||
|                                 m_Cache.AddOrUpdate(cacheKey, roles, GROUPS_CACHE_TIMEOUT); | ||||
|                                 return (List<GroupRolesData>)roles; | ||||
|                             } | ||||
|                             m_Cache.AddOrUpdate(cacheKey, roles, GROUPS_CACHE_TIMEOUT); | ||||
|                             m_ActiveRequests.Remove(cacheKey); | ||||
|                             return (List<GroupRolesData>)roles; | ||||
|                         } | ||||
|                     } | ||||
|                     finally | ||||
|                     { | ||||
|                         m_ActiveRequests.Remove(cacheKey); | ||||
|                     } | ||||
|                 } | ||||
|                 else | ||||
|                     Thread.Sleep(50); | ||||
|  | @ -578,29 +541,23 @@ namespace OpenSim.Groups | |||
| 
 | ||||
|                 if (firstCall) | ||||
|                 { | ||||
|                     try | ||||
|                     { | ||||
|                         List<ExtendedGroupRoleMembersData> _rmembers = d(); | ||||
|                     List<ExtendedGroupRoleMembersData> _rmembers = d(); | ||||
| 
 | ||||
|                         if (_rmembers != null && _rmembers.Count > 0) | ||||
|                             rmembers = _rmembers.ConvertAll<GroupRoleMembersData>(new Converter<ExtendedGroupRoleMembersData, GroupRoleMembersData>(m_ForeignImporter.ConvertGroupRoleMembersData)); | ||||
|                         else | ||||
|                             rmembers = new List<GroupRoleMembersData>(); | ||||
|                     if (_rmembers != null && _rmembers.Count > 0) | ||||
|                         rmembers = _rmembers.ConvertAll<GroupRoleMembersData>(new Converter<ExtendedGroupRoleMembersData, GroupRoleMembersData>(m_ForeignImporter.ConvertGroupRoleMembersData)); | ||||
|                     else | ||||
|                         rmembers = new List<GroupRoleMembersData>(); | ||||
| 
 | ||||
|                         lock (m_Cache) | ||||
|                         { | ||||
|                             // For some strange reason, when I cache the list of GroupRoleMembersData, | ||||
|                             // it gets emptied out. The TryGet gets an empty list... | ||||
|                             //m_Cache.AddOrUpdate(cacheKey, rmembers, GROUPS_CACHE_TIMEOUT); | ||||
|                             // Caching the list of ExtendedGroupRoleMembersData doesn't show that issue | ||||
|                             // I don't get it. | ||||
|                             m_Cache.AddOrUpdate(cacheKey, _rmembers, GROUPS_CACHE_TIMEOUT); | ||||
|                             return (List<GroupRoleMembersData>)rmembers; | ||||
|                         } | ||||
|                     } | ||||
|                     finally | ||||
|                     lock (m_Cache) | ||||
|                     { | ||||
|                         // For some strange reason, when I cache the list of GroupRoleMembersData, | ||||
|                         // it gets emptied out. The TryGet gets an empty list... | ||||
|                         //m_Cache.AddOrUpdate(cacheKey, rmembers, GROUPS_CACHE_TIMEOUT); | ||||
|                         // Caching the list of ExtendedGroupRoleMembersData doesn't show that issue | ||||
|                         // I don't get it. | ||||
|                         m_Cache.AddOrUpdate(cacheKey, _rmembers, GROUPS_CACHE_TIMEOUT); | ||||
|                         m_ActiveRequests.Remove(cacheKey); | ||||
|                         return (List<GroupRoleMembersData>)rmembers; | ||||
|                     } | ||||
|                 } | ||||
|                 else | ||||
|  | @ -709,19 +666,12 @@ namespace OpenSim.Groups | |||
| 
 | ||||
|                 if (firstCall) | ||||
|                 { | ||||
|                     try | ||||
|                     { | ||||
|                         roles = d(); | ||||
|                         lock (m_Cache) | ||||
|                         { | ||||
|                             m_Cache.AddOrUpdate(cacheKey, roles, GROUPS_CACHE_TIMEOUT); | ||||
|                             m_ActiveRequests.Remove(cacheKey); | ||||
|                             return (List<GroupRolesData>)roles; | ||||
|                         } | ||||
|                     } | ||||
|                     finally | ||||
|                     roles = d(); | ||||
|                     lock (m_Cache) | ||||
|                     { | ||||
|                         m_Cache.AddOrUpdate(cacheKey, roles, GROUPS_CACHE_TIMEOUT); | ||||
|                         m_ActiveRequests.Remove(cacheKey); | ||||
|                         return (List<GroupRolesData>)roles; | ||||
|                     } | ||||
|                 } | ||||
|                 else | ||||
|  | @ -817,19 +767,13 @@ namespace OpenSim.Groups | |||
| 
 | ||||
|                 if (firstCall) | ||||
|                 { | ||||
|                     try | ||||
|                     { | ||||
|                         GroupNoticeInfo _notice = d(); | ||||
|                     GroupNoticeInfo _notice = d(); | ||||
| 
 | ||||
|                         lock (m_Cache) | ||||
|                         { | ||||
|                             m_Cache.AddOrUpdate(cacheKey, _notice, GROUPS_CACHE_TIMEOUT); | ||||
|                             return _notice; | ||||
|                         } | ||||
|                     } | ||||
|                     finally | ||||
|                     lock (m_Cache) | ||||
|                     { | ||||
|                         m_Cache.AddOrUpdate(cacheKey, _notice, GROUPS_CACHE_TIMEOUT); | ||||
|                         m_ActiveRequests.Remove(cacheKey); | ||||
|                         return _notice; | ||||
|                     } | ||||
|                 } | ||||
|                 else | ||||
|  | @ -865,24 +809,20 @@ namespace OpenSim.Groups | |||
| 
 | ||||
|                 if (firstCall) | ||||
|                 { | ||||
|                     try | ||||
|                     { | ||||
|                         notices = d(); | ||||
|                     notices = d(); | ||||
| 
 | ||||
|                         lock (m_Cache) | ||||
|                         { | ||||
|                             m_Cache.AddOrUpdate(cacheKey, notices, GROUPS_CACHE_TIMEOUT); | ||||
|                             return (List<ExtendedGroupNoticeData>)notices; | ||||
|                         } | ||||
|                     } | ||||
|                     finally | ||||
|                     lock (m_Cache) | ||||
|                     { | ||||
|                         m_Cache.AddOrUpdate(cacheKey, notices, GROUPS_CACHE_TIMEOUT); | ||||
|                         m_ActiveRequests.Remove(cacheKey); | ||||
|                         return (List<ExtendedGroupNoticeData>)notices; | ||||
|                     } | ||||
|                 } | ||||
|                 else | ||||
|                     Thread.Sleep(50); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
| 
 | ||||
|     } | ||||
| } | ||||
| } | ||||
|  |  | |||
|  | @ -43,63 +43,60 @@ namespace OpenSim.Groups | |||
|     { | ||||
|         private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | ||||
| 
 | ||||
|         public const GroupPowers DefaultEveryonePowers = | ||||
|             GroupPowers.AllowSetHome | | ||||
|             GroupPowers.Accountable | | ||||
|             GroupPowers.JoinChat | | ||||
|             GroupPowers.AllowVoiceChat | | ||||
|             GroupPowers.ReceiveNotices | | ||||
|             GroupPowers.StartProposal | | ||||
|             GroupPowers.VoteOnProposal; | ||||
|         public const GroupPowers DefaultEveryonePowers = GroupPowers.AllowSetHome | | ||||
|                                                          GroupPowers.Accountable | | ||||
|                                                          GroupPowers.JoinChat | | ||||
|                                                          GroupPowers.AllowVoiceChat | | ||||
|                                                          GroupPowers.ReceiveNotices | | ||||
|                                                          GroupPowers.StartProposal | | ||||
|                                                          GroupPowers.VoteOnProposal; | ||||
| 
 | ||||
|         public const GroupPowers OfficersPowers = DefaultEveryonePowers | | ||||
|             GroupPowers.AllowFly | | ||||
|             GroupPowers.AllowLandmark | | ||||
|             GroupPowers.AllowRez | | ||||
|             GroupPowers.AssignMemberLimited | | ||||
|             GroupPowers.ChangeIdentity | | ||||
|             GroupPowers.ChangeMedia | | ||||
|             GroupPowers.ChangeOptions | | ||||
|             GroupPowers.DeedObject | | ||||
|             GroupPowers.Eject | | ||||
|             GroupPowers.FindPlaces | | ||||
|             GroupPowers.Invite | | ||||
|             GroupPowers.LandChangeIdentity | | ||||
|             GroupPowers.LandDeed | | ||||
|             GroupPowers.LandDivideJoin | | ||||
|             GroupPowers.LandEdit | | ||||
|             GroupPowers.AllowEnvironment | | ||||
|             GroupPowers.LandEjectAndFreeze | | ||||
|             GroupPowers.LandGardening | | ||||
|             GroupPowers.LandManageAllowed | | ||||
|             GroupPowers.LandManageBanned | | ||||
|             GroupPowers.LandManagePasses | | ||||
|             GroupPowers.LandOptions | | ||||
|             GroupPowers.LandRelease | | ||||
|             GroupPowers.LandSetSale | | ||||
|             GroupPowers.MemberVisible | | ||||
|             GroupPowers.ModerateChat | | ||||
|             GroupPowers.ObjectManipulate | | ||||
|             GroupPowers.ObjectSetForSale | | ||||
|             GroupPowers.ReturnGroupOwned | | ||||
|             GroupPowers.ReturnGroupSet | | ||||
|             GroupPowers.ReturnNonGroup | | ||||
|             GroupPowers.RoleProperties | | ||||
|             GroupPowers.SendNotices | | ||||
|             GroupPowers.SetLandingPoint; | ||||
| 
 | ||||
|         public const GroupPowers OwnerPowers = OfficersPowers |  | ||||
|             GroupPowers.Accountable | | ||||
|             GroupPowers.AllowEditLand | | ||||
|             GroupPowers.AssignMember | | ||||
|             GroupPowers.ChangeActions | | ||||
|             GroupPowers.CreateRole | | ||||
|             GroupPowers.DeleteRole | | ||||
|             GroupPowers.ExperienceAdmin | | ||||
|             GroupPowers.ExperienceCreator | | ||||
|             GroupPowers.GroupBanAccess | | ||||
|             GroupPowers.HostEvent | | ||||
|             GroupPowers.RemoveMember; | ||||
|         public const GroupPowers OwnerPowers = GroupPowers.Accountable | | ||||
|                                                 GroupPowers.AllowEditLand | | ||||
|                                                 GroupPowers.AllowFly | | ||||
|                                                 GroupPowers.AllowLandmark | | ||||
|                                                 GroupPowers.AllowRez | | ||||
|                                                 GroupPowers.AllowSetHome | | ||||
|                                                 GroupPowers.AllowVoiceChat | | ||||
|                                                 GroupPowers.AssignMember | | ||||
|                                                 GroupPowers.AssignMemberLimited | | ||||
|                                                 GroupPowers.ChangeActions | | ||||
|                                                 GroupPowers.ChangeIdentity | | ||||
|                                                 GroupPowers.ChangeMedia | | ||||
|                                                 GroupPowers.ChangeOptions | | ||||
|                                                 GroupPowers.CreateRole | | ||||
|                                                 GroupPowers.DeedObject | | ||||
|                                                 GroupPowers.DeleteRole | | ||||
|                                                 GroupPowers.Eject | | ||||
|                                                 GroupPowers.FindPlaces | | ||||
|                                                 GroupPowers.HostEvent | | ||||
|                                                 GroupPowers.Invite | | ||||
|                                                 GroupPowers.JoinChat | | ||||
|                                                 GroupPowers.LandChangeIdentity | | ||||
|                                                 GroupPowers.LandDeed | | ||||
|                                                 GroupPowers.LandDivideJoin | | ||||
|                                                 GroupPowers.LandEdit | | ||||
|                                                 GroupPowers.LandEjectAndFreeze | | ||||
|                                                 GroupPowers.LandGardening | | ||||
|                                                 GroupPowers.LandManageAllowed | | ||||
|                                                 GroupPowers.LandManageBanned | | ||||
|                                                 GroupPowers.LandManagePasses | | ||||
|                                                 GroupPowers.LandOptions | | ||||
|                                                 GroupPowers.LandRelease | | ||||
|                                                 GroupPowers.LandSetSale | | ||||
|                                                 GroupPowers.ModerateChat | | ||||
|                                                 GroupPowers.ObjectManipulate | | ||||
|                                                 GroupPowers.ObjectSetForSale | | ||||
|                                                 GroupPowers.ReceiveNotices | | ||||
|                                                 GroupPowers.RemoveMember | | ||||
|                                                 GroupPowers.ReturnGroupOwned | | ||||
|                                                 GroupPowers.ReturnGroupSet | | ||||
|                                                 GroupPowers.ReturnNonGroup | | ||||
|                                                 GroupPowers.RoleProperties | | ||||
|                                                 GroupPowers.SendNotices | | ||||
|                                                 GroupPowers.SetLandingPoint | | ||||
|                                                 GroupPowers.StartProposal | | ||||
|                                                 GroupPowers.VoteOnProposal; | ||||
| 
 | ||||
|         #region Daily Cleanup | ||||
| 
 | ||||
|  | @ -129,7 +126,7 @@ namespace OpenSim.Groups | |||
| 
 | ||||
|         #endregion | ||||
| 
 | ||||
|         public UUID CreateGroup(string RequestingAgentID, string name, string charter, bool showInList, UUID insigniaID, int membershipFee, bool openEnrollment, | ||||
|         public UUID CreateGroup(string RequestingAgentID, string name, string charter, bool showInList, UUID insigniaID, int membershipFee, bool openEnrollment,  | ||||
|             bool allowPublish, bool maturePublish, UUID founderID, out string reason) | ||||
|         { | ||||
|             reason = string.Empty; | ||||
|  | @ -154,25 +151,20 @@ namespace OpenSim.Groups | |||
|             data.Data["ShowInList"] = showInList ? "1" : "0"; | ||||
|             data.Data["AllowPublish"] = allowPublish ? "1" : "0"; | ||||
|             data.Data["MaturePublish"] = maturePublish ? "1" : "0"; | ||||
|             UUID ownerRoleID = UUID.Random(); | ||||
|             data.Data["OwnerRoleID"] = ownerRoleID.ToString(); | ||||
|             UUID roleID = UUID.Random(); | ||||
|             data.Data["OwnerRoleID"] = roleID.ToString(); | ||||
| 
 | ||||
|             if (!m_Database.StoreGroup(data)) | ||||
|                 return UUID.Zero; | ||||
| 
 | ||||
|             // Create Everyone role | ||||
|             _AddOrUpdateGroupRole(RequestingAgentID, data.GroupID, UUID.Zero, "Everyone", "Everyone in the group is in the everyone role.", "Member of " + name, (ulong)DefaultEveryonePowers, true); | ||||
| 
 | ||||
|             // Create Officers role | ||||
|             UUID officersRoleID = UUID.Random(); | ||||
|             _AddOrUpdateGroupRole(RequestingAgentID, data.GroupID, officersRoleID, "Officers", "The officers of the group, with more powers than regular members.", "Officer of " + name, (ulong)OfficersPowers, true); | ||||
|             _AddOrUpdateGroupRole(RequestingAgentID, data.GroupID, UUID.Zero, "Everyone", "Everyone in the group", "Member of " + name, (ulong)DefaultEveryonePowers, true); | ||||
| 
 | ||||
|             // Create Owner role | ||||
|             _AddOrUpdateGroupRole(RequestingAgentID, data.GroupID, ownerRoleID, "Owners", "Owners of the group", "Owner of " + name, (ulong)OwnerPowers, true); | ||||
|             _AddOrUpdateGroupRole(RequestingAgentID, data.GroupID, roleID, "Owners", "Owners of the group", "Owner of " + name, (ulong)OwnerPowers, true); | ||||
| 
 | ||||
|             // Add founder to group | ||||
|             _AddAgentToGroup(RequestingAgentID, founderID.ToString(), data.GroupID, ownerRoleID); | ||||
|             _AddAgentToGroup(RequestingAgentID, founderID.ToString(), data.GroupID, officersRoleID); | ||||
|             _AddAgentToGroup(RequestingAgentID, founderID.ToString(), data.GroupID, roleID); | ||||
| 
 | ||||
|             return data.GroupID; | ||||
|         } | ||||
|  | @ -231,22 +223,15 @@ namespace OpenSim.Groups | |||
|                     if (d.Data.ContainsKey("Location") && d.Data["Location"] != string.Empty) | ||||
|                         continue; | ||||
| 
 | ||||
|                     int nmembers = m_Database.MemberCount(d.GroupID); | ||||
|                     if(nmembers == 0) | ||||
|                         continue; | ||||
| 
 | ||||
|                     DirGroupsReplyData g = new DirGroupsReplyData(); | ||||
|                     g.groupID = d.GroupID; | ||||
| 
 | ||||
|                     if (d.Data.ContainsKey("Name")) | ||||
|                         g.groupName = d.Data["Name"]; | ||||
|                     else | ||||
|                     { | ||||
|                         m_log.DebugFormat("[Groups]: Key Name not found"); | ||||
|                         continue; | ||||
|                     } | ||||
| 
 | ||||
|                     g.groupID = d.GroupID; | ||||
|                     g.members = nmembers; | ||||
|                     g.members = m_Database.MemberCount(d.GroupID); | ||||
| 
 | ||||
|                     groups.Add(g); | ||||
|                 } | ||||
|  | @ -279,7 +264,7 @@ namespace OpenSim.Groups | |||
|             if (ownerRole != null) | ||||
|                 ownerRoleID = ownerRole.RoleID; | ||||
| 
 | ||||
|             // Check visibility? | ||||
|             // Check visibility?  | ||||
|             // When we don't want to check visibility, we pass it "all" as the requestingAgentID | ||||
|             bool checkVisibility = !RequestingAgentID.Equals(UUID.Zero.ToString()); | ||||
| 
 | ||||
|  | @ -322,21 +307,6 @@ namespace OpenSim.Groups | |||
|                 m.Contribution = Int32.Parse(d.Data["Contribution"]); | ||||
|                 m.ListInProfile = d.Data["ListInProfile"] == "1" ? true : false; | ||||
| 
 | ||||
|                 GridUserData gud = m_GridUserService.Get(d.PrincipalID); | ||||
|                 if (gud != null) | ||||
|                 { | ||||
|                     if (bool.Parse(gud.Data["Online"])) | ||||
|                     { | ||||
|                         m.OnlineStatus = @"Online"; | ||||
|                     } | ||||
|                     else | ||||
|                     { | ||||
|                         int unixtime = int.Parse(gud.Data["Login"]); | ||||
|                         // The viewer is very picky about how these strings are formed. Eg. it will crash on malformed dates! | ||||
|                         m.OnlineStatus = (unixtime == 0) ? @"unknown" : Util.ToDateTime(unixtime).ToString("MM/dd/yyyy"); | ||||
|                     } | ||||
|                 } | ||||
| 
 | ||||
|                 // Is this person an owner of the group? | ||||
|                 m.IsOwner = (rolemembershipsList.Find(r => r.RoleID == ownerRoleID) != null) ? true : false; | ||||
| 
 | ||||
|  | @ -500,8 +470,8 @@ namespace OpenSim.Groups | |||
| 
 | ||||
|             // check permissions | ||||
|             bool limited = HasPower(RequestingAgentID, GroupID, GroupPowers.AssignMemberLimited); | ||||
|             bool unlimited = HasPower(RequestingAgentID, GroupID, GroupPowers.AssignMember) || IsOwner(RequestingAgentID, GroupID); | ||||
|             if (!limited && !unlimited) | ||||
|             bool unlimited = HasPower(RequestingAgentID, GroupID, GroupPowers.AssignMember) | IsOwner(RequestingAgentID, GroupID); | ||||
|             if (!limited || !unlimited) | ||||
|             { | ||||
|                 m_log.DebugFormat("[Groups]: ({0}) Attempt at assigning {1} to role {2} denied because of lack of permission", RequestingAgentID, AgentID, RoleID); | ||||
|                 return false; | ||||
|  | @ -511,7 +481,7 @@ namespace OpenSim.Groups | |||
|             if (!unlimited && limited) | ||||
|             { | ||||
|                 // check whether person's has this role | ||||
|                 RoleMembershipData rolemembership = m_Database.RetrieveRoleMember(GroupID, RoleID, RequestingAgentID); | ||||
|                 RoleMembershipData rolemembership = m_Database.RetrieveRoleMember(GroupID, RoleID, AgentID); | ||||
|                 if (rolemembership == null) | ||||
|                 { | ||||
|                     m_log.DebugFormat("[Groups]: ({0}) Attempt at assigning {1} to role {2} denied because of limited permission", RequestingAgentID, AgentID, RoleID); | ||||
|  | @ -531,26 +501,13 @@ namespace OpenSim.Groups | |||
|                 return false; | ||||
| 
 | ||||
|             // check permissions | ||||
|             bool limited = HasPower(RequestingAgentID, GroupID, GroupPowers.AssignMemberLimited); | ||||
|             bool unlimited = HasPower(RequestingAgentID, GroupID, GroupPowers.AssignMember) || IsOwner(RequestingAgentID, GroupID); | ||||
|             if (!limited && !unlimited) | ||||
|             if (!unlimited) | ||||
|             { | ||||
|                 m_log.DebugFormat("[Groups]: ({0}) Attempt at removing {1} from role {2} denied because of lack of permission", RequestingAgentID, AgentID, RoleID); | ||||
|                 return false; | ||||
|             } | ||||
| 
 | ||||
|             // AssignMemberLimited means that the person can assign another person to the same roles that she has in the group | ||||
|             if (!unlimited && limited) | ||||
|             { | ||||
|                 // check whether person's has this role | ||||
|                 RoleMembershipData rolemembership = m_Database.RetrieveRoleMember(GroupID, RoleID, RequestingAgentID); | ||||
|                 if (rolemembership == null) | ||||
|                 { | ||||
|                     m_log.DebugFormat("[Groups]: ({0}) Attempt at removing {1} from role {2} denied because of limited permission", RequestingAgentID, AgentID, RoleID); | ||||
|                     return false; | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|             RoleMembershipData rolemember = m_Database.RetrieveRoleMember(GroupID, RoleID, AgentID); | ||||
| 
 | ||||
|             if (rolemember == null) | ||||
|  | @ -568,8 +525,8 @@ namespace OpenSim.Groups | |||
|                     { | ||||
|                         newRoleID = r.RoleID; | ||||
|                         break; | ||||
|                     } | ||||
|                 } | ||||
|                     }    | ||||
|                 }    | ||||
| 
 | ||||
|             MembershipData member = m_Database.RetrieveMember(GroupID, AgentID); | ||||
|             if (member != null) | ||||
|  | @ -727,7 +684,7 @@ namespace OpenSim.Groups | |||
|             m_Database.StoreMember(membership); | ||||
|         } | ||||
| 
 | ||||
|         public bool AddGroupNotice(string RequestingAgentID, UUID groupID, UUID noticeID, string fromName, string subject, string message, | ||||
|         public bool AddGroupNotice(string RequestingAgentID, UUID groupID, UUID noticeID, string fromName, string subject, string message,  | ||||
|             bool hasAttachment, byte attType, string attName, UUID attItemID, string attOwnerID) | ||||
|         { | ||||
|             // Check perms | ||||
|  | @ -840,7 +797,7 @@ namespace OpenSim.Groups | |||
|             if (RoleID != UUID.Zero) | ||||
|                 _AddAgentToGroupRole(RequestingAgentID, AgentID, GroupID, RoleID); | ||||
| 
 | ||||
|             // Make this the active group | ||||
|             // Make thit this active group | ||||
|             PrincipalData pdata = new PrincipalData(); | ||||
|             pdata.PrincipalID = AgentID; | ||||
|             pdata.ActiveGroupID = GroupID; | ||||
|  | @ -858,7 +815,7 @@ namespace OpenSim.Groups | |||
|                 return false; | ||||
|             } | ||||
| 
 | ||||
|             if (!add && data == null) // it doesn't exist, can't update | ||||
|             if (!add && data == null) // it deosn't exist, can't update | ||||
|             { | ||||
|                 m_log.DebugFormat("[Groups]: Group {0} doesn't exist. Can't update it", groupID); | ||||
|                 return false; | ||||
|  |  | |||
|  | @ -1,4 +1,4 @@ | |||
| /* | ||||
| /* | ||||
|  * Copyright (c) Contributors, http://opensimulator.org/ | ||||
|  * See CONTRIBUTORS.TXT for a full list of copyright holders. | ||||
|  * | ||||
|  | @ -38,7 +38,6 @@ namespace OpenSim.Groups | |||
|     public class GroupsServiceBase : ServiceBase | ||||
|     { | ||||
|         protected IGroupsData m_Database = null; | ||||
|         protected IGridUserData m_GridUserService = null; | ||||
| 
 | ||||
|         public GroupsServiceBase(IConfigSource config, string cName) | ||||
|             : base(config) | ||||
|  | @ -46,7 +45,6 @@ namespace OpenSim.Groups | |||
|             string dllName = String.Empty; | ||||
|             string connString = String.Empty; | ||||
|             string realm = "os_groups"; | ||||
|             string usersRealm = "GridUser"; | ||||
|             string configName = (cName == string.Empty) ? "Groups" : cName; | ||||
| 
 | ||||
|             // | ||||
|  | @ -81,21 +79,6 @@ namespace OpenSim.Groups | |||
|             m_Database = LoadPlugin<IGroupsData>(dllName, new Object[] { connString, realm }); | ||||
|             if (m_Database == null) | ||||
|                 throw new Exception("Could not find a storage interface in the given module " + dllName); | ||||
| 
 | ||||
|             // | ||||
|             // [GridUserService] section overrides [DatabaseService], if it exists | ||||
|             // | ||||
|             IConfig usersConfig = config.Configs["GridUserService"]; | ||||
|             if (usersConfig != null) | ||||
|             { | ||||
|                 dllName = usersConfig.GetString("StorageProvider", dllName); | ||||
|                 connString = usersConfig.GetString("ConnectionString", connString); | ||||
|                 usersRealm = usersConfig.GetString("Realm", usersRealm); | ||||
|             } | ||||
| 
 | ||||
|             m_GridUserService = LoadPlugin<IGridUserData>(dllName, new Object[] { connString, usersRealm }); | ||||
|             if (m_GridUserService == null) | ||||
|                 throw new Exception("Could not find a storage inferface for the given users module " + dllName); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| } | ||||
|  | @ -76,7 +76,7 @@ namespace OpenSim.Groups | |||
| 
 | ||||
|             // Check if it already exists | ||||
|             GroupData grec = m_Database.RetrieveGroup(groupID); | ||||
|             if (grec == null || | ||||
|             if (grec == null ||  | ||||
|                 (grec != null && grec.Data["Location"] != string.Empty && grec.Data["Location"].ToLower() != serviceLocation.ToLower())) | ||||
|             { | ||||
|                 // Create the group | ||||
|  |  | |||
|  | @ -114,6 +114,7 @@ namespace OpenSim.OfflineIM | |||
|             scene.ForEachClient(delegate(IClientAPI client) | ||||
|             { | ||||
|                 client.OnRetrieveInstantMessages -= RetrieveInstantMessages; | ||||
|                 client.OnMuteListRequest -= OnMuteListRequest; | ||||
|             }); | ||||
|         } | ||||
| 
 | ||||
|  | @ -161,6 +162,7 @@ namespace OpenSim.OfflineIM | |||
|         private void OnNewClient(IClientAPI client) | ||||
|         { | ||||
|             client.OnRetrieveInstantMessages += RetrieveInstantMessages; | ||||
|             client.OnMuteListRequest += OnMuteListRequest; | ||||
|         } | ||||
| 
 | ||||
|         private void RetrieveInstantMessages(IClientAPI client) | ||||
|  | @ -192,6 +194,20 @@ namespace OpenSim.OfflineIM | |||
|             } | ||||
|         } | ||||
| 
 | ||||
|         // Apparently this is needed in order for the viewer to request the IMs. | ||||
|         private void OnMuteListRequest(IClientAPI client, uint crc) | ||||
|         { | ||||
|             m_log.DebugFormat("[OfflineIM.V2] Got mute list request for crc {0}", crc); | ||||
|             string filename = "mutes" + client.AgentId.ToString(); | ||||
| 
 | ||||
|             IXfer xfer = client.Scene.RequestModuleInterface<IXfer>(); | ||||
|             if (xfer != null) | ||||
|             { | ||||
|                 xfer.AddNewFile(filename, new Byte[0]); | ||||
|                 client.SendMuteListUpdate(filename); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         private void UndeliveredMessage(GridInstantMessage im) | ||||
|         { | ||||
|             if (im.dialog != (byte)InstantMessageDialog.MessageFromObject && | ||||
|  |  | |||
|  | @ -3,7 +3,7 @@ using System.Runtime.CompilerServices; | |||
| using System.Runtime.InteropServices; | ||||
| using Mono.Addins; | ||||
| 
 | ||||
| // General Information about an assembly is controlled through the following | ||||
| // General Information about an assembly is controlled through the following  | ||||
| // set of attributes. Change these attribute values to modify the information | ||||
| // associated with an assembly. | ||||
| [assembly: AssemblyTitle("OpenSim.Addons.OfflineIM")] | ||||
|  | @ -15,8 +15,8 @@ using Mono.Addins; | |||
| [assembly: AssemblyTrademark("")] | ||||
| [assembly: AssemblyCulture("")] | ||||
| 
 | ||||
| // Setting ComVisible to false makes the types in this assembly not visible | ||||
| // to COM components.  If you need to access a type in this assembly from | ||||
| // Setting ComVisible to false makes the types in this assembly not visible  | ||||
| // to COM components.  If you need to access a type in this assembly from  | ||||
| // COM, set the ComVisible attribute to true on that type. | ||||
| [assembly: ComVisible(false)] | ||||
| 
 | ||||
|  | @ -26,11 +26,11 @@ using Mono.Addins; | |||
| // Version information for an assembly consists of the following four values: | ||||
| // | ||||
| //      Major Version | ||||
| //      Minor Version | ||||
| //      Minor Version  | ||||
| //      Build Number | ||||
| //      Revision | ||||
| // | ||||
| [assembly: AssemblyVersion(OpenSim.VersionInfo.AssemblyVersionNumber)] | ||||
| [assembly: AssemblyVersion("0.8.1.*")] | ||||
| 
 | ||||
| [assembly: Addin("OpenSim.OfflineIM", OpenSim.VersionInfo.VersionNumber)] | ||||
| [assembly: AddinDependency("OpenSim.Region.Framework", OpenSim.VersionInfo.VersionNumber)] | ||||
| [assembly: Addin("OpenSim.OfflineIM", "0.1")] | ||||
| [assembly: AddinDependency("OpenSim", "0.5")] | ||||
|  |  | |||
|  | @ -77,7 +77,7 @@ namespace OpenSim.OfflineIM | |||
|                     break; | ||||
|             } | ||||
|             /// | ||||
|             m_log.DebugFormat("[OfflineIM.V2.RemoteConnector]: Offline IM server at {0} with auth {1}", | ||||
|             m_log.DebugFormat("[OfflineIM.V2.RemoteConnector]: Offline IM server at {0} with auth {1}",  | ||||
|                 m_ServerURI, (m_Auth == null ? "None" : m_Auth.GetType().ToString())); | ||||
|         } | ||||
| 
 | ||||
|  | @ -140,7 +140,7 @@ namespace OpenSim.OfflineIM | |||
|         { | ||||
|             Dictionary<string, object> sendData = new Dictionary<string, object>(); | ||||
|             sendData["UserID"] = userID; | ||||
| 
 | ||||
|              | ||||
|             MakeRequest("DELETE", sendData); | ||||
|         } | ||||
| 
 | ||||
|  |  | |||
|  | @ -90,7 +90,7 @@ namespace OpenSim.OfflineIM | |||
|         public bool StoreMessage(GridInstantMessage im, out string reason) | ||||
|         { | ||||
|             reason = string.Empty; | ||||
| 
 | ||||
|              | ||||
|             // Check limits | ||||
|             UUID principalID = new UUID(im.toAgentID); | ||||
|             long count = m_Database.GetCount("PrincipalID", principalID.ToString()); | ||||
|  | @ -110,8 +110,9 @@ namespace OpenSim.OfflineIM | |||
|                 { | ||||
|                     m_serializer.Serialize(writer, im); | ||||
|                     writer.Flush(); | ||||
|                     imXml = Util.UTF8NoBomEncoding.GetString(mstream.ToArray()); | ||||
|                 } | ||||
| 
 | ||||
|                 imXml = Util.UTF8NoBomEncoding.GetString(mstream.ToArray()); | ||||
|             } | ||||
| 
 | ||||
|             OfflineIMData data = new OfflineIMData(); | ||||
|  |  | |||
|  | @ -32,17 +32,17 @@ using System.Threading; | |||
| using log4net; | ||||
| using OpenMetaverse; | ||||
| using OpenSim.Framework; | ||||
| using OpenSim.Framework.RegionLoader.Filesystem; | ||||
| using OpenSim.Framework.RegionLoader.Web; | ||||
| using OpenSim.Region.CoreModules.Agent.AssetTransaction; | ||||
| using OpenSim.Region.CoreModules.Avatar.InstantMessage; | ||||
| using OpenSim.Region.CoreModules.Scripting.DynamicTexture; | ||||
| using OpenSim.Region.CoreModules.Scripting.LoadImageURL; | ||||
| using OpenSim.Region.CoreModules.Scripting.XMLRPC; | ||||
| using OpenSim.Services.Interfaces; | ||||
| using Mono.Addins; | ||||
| 
 | ||||
| namespace OpenSim.ApplicationPlugins.LoadRegions | ||||
| { | ||||
|     [Extension(Path="/OpenSim/Startup", Id="LoadRegions", NodeName="Plugin")] | ||||
|     public class LoadRegionsPlugin : IApplicationPlugin, IRegionCreator | ||||
|     { | ||||
|         private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | ||||
|  | @ -124,7 +124,7 @@ namespace OpenSim.ApplicationPlugins.LoadRegions | |||
|                 m_log.Debug("[LOAD REGIONS PLUGIN]: Creating Region: " + regionsToLoad[i].RegionName + " (ThreadID: " + | ||||
|                             Thread.CurrentThread.ManagedThreadId.ToString() + | ||||
|                             ")"); | ||||
| 
 | ||||
|                  | ||||
|                 bool changed = m_openSim.PopulateRegionEstateInfo(regionsToLoad[i]); | ||||
| 
 | ||||
|                 m_openSim.CreateRegion(regionsToLoad[i], true, out scene); | ||||
|  |  | |||
|  | @ -27,17 +27,16 @@ | |||
| 
 | ||||
| using System.Reflection; | ||||
| using System.Runtime.InteropServices; | ||||
| using Mono.Addins; | ||||
| 
 | ||||
| // General information about an assembly is controlled through the following | ||||
| // set of attributes. Change these attribute values to modify the information | ||||
| // associated with an assembly. | ||||
| 
 | ||||
| [assembly : AssemblyTitle("OpenSim.ApplicationPlugins.LoadRegions")] | ||||
| [assembly : AssemblyTitle("OpenSim.Addin")] | ||||
| [assembly : AssemblyDescription("")] | ||||
| [assembly : AssemblyConfiguration("")] | ||||
| [assembly : AssemblyCompany("http://opensimulator.org")] | ||||
| [assembly : AssemblyProduct("OpenSim")] | ||||
| [assembly : AssemblyProduct("OpenSim.Addin")] | ||||
| [assembly : AssemblyCopyright("Copyright © OpenSimulator.org Developers 2007-2009")] | ||||
| [assembly : AssemblyTrademark("")] | ||||
| [assembly : AssemblyCulture("")] | ||||
|  | @ -61,8 +60,6 @@ using Mono.Addins; | |||
| // | ||||
| // You can specify all the values or you can default the Build and Revision Numbers | ||||
| // by using the '*' as shown below: | ||||
| // [assembly: AssemblyVersion("0.7.6.*")] | ||||
| 
 | ||||
| [assembly : AssemblyVersion(OpenSim.VersionInfo.AssemblyVersionNumber)] | ||||
| 
 | ||||
| [assembly: Addin("OpenSim.ApplicationPlugins.LoadRegions", OpenSim.VersionInfo.VersionNumber)] | ||||
| [assembly: AddinDependency("OpenSim", OpenSim.VersionInfo.VersionNumber)] | ||||
| [assembly : AssemblyVersion("0.8.1.*")] | ||||
|  |  | |||
|  | @ -0,0 +1,11 @@ | |||
| <Addin id="OpenSim.ApplicationPlugins.LoadRegions" version="0.1"> | ||||
|     <Runtime> | ||||
|         <Import assembly="OpenSim.ApplicationPlugins.LoadRegions.dll"/> | ||||
|     </Runtime> | ||||
|     <Dependencies> | ||||
|         <Addin id="OpenSim" version="0.5" /> | ||||
|     </Dependencies> | ||||
|     <Extension path = "/OpenSim/Startup"> | ||||
|         <Plugin id="LoadRegions" type="OpenSim.ApplicationPlugins.LoadRegions.LoadRegionsPlugin" /> | ||||
|     </Extension> | ||||
| </Addin> | ||||
|  | @ -1,9 +1,8 @@ | |||
| using System.Reflection; | ||||
| using System.Runtime.CompilerServices; | ||||
| using System.Runtime.InteropServices; | ||||
| using Mono.Addins; | ||||
| 
 | ||||
| // General Information about an assembly is controlled through the following | ||||
| // General Information about an assembly is controlled through the following  | ||||
| // set of attributes. Change these attribute values to modify the information | ||||
| // associated with an assembly. | ||||
| [assembly: AssemblyTitle("OpenSim.ApplicationPlugins.RegionModulesController")] | ||||
|  | @ -15,8 +14,8 @@ using Mono.Addins; | |||
| [assembly: AssemblyTrademark("")] | ||||
| [assembly: AssemblyCulture("")] | ||||
| 
 | ||||
| // Setting ComVisible to false makes the types in this assembly not visible | ||||
| // to COM components.  If you need to access a type in this assembly from | ||||
| // Setting ComVisible to false makes the types in this assembly not visible  | ||||
| // to COM components.  If you need to access a type in this assembly from  | ||||
| // COM, set the ComVisible attribute to true on that type. | ||||
| [assembly: ComVisible(false)] | ||||
| 
 | ||||
|  | @ -26,11 +25,9 @@ using Mono.Addins; | |||
| // Version information for an assembly consists of the following four values: | ||||
| // | ||||
| //      Major Version | ||||
| //      Minor Version | ||||
| //      Minor Version  | ||||
| //      Build Number | ||||
| //      Revision | ||||
| // | ||||
| [assembly: AssemblyVersion(OpenSim.VersionInfo.AssemblyVersionNumber)] | ||||
| [assembly: AssemblyVersion("0.8.1.*")] | ||||
| 
 | ||||
| [assembly: Addin("OpenSim.ApplicationPlugins.RegionModulesController", OpenSim.VersionInfo.VersionNumber)] | ||||
| [assembly: AddinDependency("OpenSim", OpenSim.VersionInfo.VersionNumber)] | ||||
|  |  | |||
|  | @ -38,7 +38,6 @@ using OpenSim.Region.Framework.Scenes; | |||
| 
 | ||||
| namespace OpenSim.ApplicationPlugins.RegionModulesController | ||||
| { | ||||
|     [Extension(Path = "/OpenSim/Startup", Id = "LoadRegions", NodeName = "Plugin")] | ||||
|     public class RegionModulesControllerPlugin : IRegionModulesController, | ||||
|             IApplicationPlugin | ||||
|     { | ||||
|  | @ -75,7 +74,7 @@ namespace OpenSim.ApplicationPlugins.RegionModulesController | |||
|         } | ||||
| 
 | ||||
| #region IApplicationPlugin implementation | ||||
| 
 | ||||
|          | ||||
|         public void Initialise (OpenSimBase openSim) | ||||
|         { | ||||
|             m_openSim = openSim; | ||||
|  | @ -111,7 +110,7 @@ namespace OpenSim.ApplicationPlugins.RegionModulesController | |||
|             { | ||||
|                 m_log.InfoFormat( | ||||
|                     "[REGIONMODULES]: From plugin {0}, (version {1}), loaded {2} modules, {3} shared, {4} non-shared {5} unknown", | ||||
|                     loadedModuleData.Key.Id, | ||||
|                     loadedModuleData.Key.Id,  | ||||
|                     loadedModuleData.Key.Version, | ||||
|                     loadedModuleData.Value[0] + loadedModuleData.Value[1] + loadedModuleData.Value[2], | ||||
|                     loadedModuleData.Value[0], loadedModuleData.Value[1], loadedModuleData.Value[2]); | ||||
|  | @ -131,9 +130,6 @@ namespace OpenSim.ApplicationPlugins.RegionModulesController | |||
|                 // Read the config again | ||||
|                 string moduleString = | ||||
|                         modulesConfig.GetString("Setup_" + node.Id, String.Empty); | ||||
|                 // Test to see if we want this module | ||||
|                 if (moduleString == "disabled") | ||||
|                     continue; | ||||
| 
 | ||||
|                 // Get the port number, if there is one | ||||
|                 if (moduleString != String.Empty) | ||||
|  | @ -261,7 +257,7 @@ namespace OpenSim.ApplicationPlugins.RegionModulesController | |||
|         } | ||||
| 
 | ||||
| #region Region Module interfacesController implementation | ||||
| 
 | ||||
|          | ||||
|         /// <summary> | ||||
|         /// Check that the given module is no disabled in the [Modules] section of the config files. | ||||
|         /// </summary> | ||||
|  | @ -293,10 +289,10 @@ namespace OpenSim.ApplicationPlugins.RegionModulesController | |||
|                 if (className != String.Empty && | ||||
|                         node.Type.ToString() != className) | ||||
|                     return false; | ||||
|             } | ||||
| 
 | ||||
|             }             | ||||
|              | ||||
|             return true; | ||||
|         } | ||||
|         }         | ||||
| 
 | ||||
|         // The root of all evil. | ||||
|         // This is where we handle adding the modules to scenes when they | ||||
|  | @ -368,10 +364,6 @@ namespace OpenSim.ApplicationPlugins.RegionModulesController | |||
|                 string moduleString = | ||||
|                         modulesConfig.GetString("Setup_" + node.Id, String.Empty); | ||||
| 
 | ||||
|                 // We may not want to load this at all | ||||
|                 if (moduleString == "disabled") | ||||
|                     continue; | ||||
| 
 | ||||
|                 // Get the port number, if there is one | ||||
|                 if (moduleString != String.Empty) | ||||
|                 { | ||||
|  | @ -509,8 +501,6 @@ namespace OpenSim.ApplicationPlugins.RegionModulesController | |||
|             { | ||||
|                 module.RegionLoaded(scene); | ||||
|             } | ||||
| 
 | ||||
|             scene.AllModulesLoaded(); | ||||
|         } | ||||
| 
 | ||||
|         public void RemoveRegionFromModules (Scene scene) | ||||
|  |  | |||
|  | @ -0,0 +1,13 @@ | |||
| <Addin id="OpenSim.ApplicationPlugins.RegionModulesController" version="0.1"> | ||||
|     <Runtime> | ||||
|         <Import assembly="OpenSim.ApplicationPlugins.RegionModulesController.dll"/> | ||||
|     </Runtime> | ||||
| 
 | ||||
|     <Dependencies> | ||||
|         <Addin id="OpenSim" version="0.5" /> | ||||
|     </Dependencies> | ||||
| 
 | ||||
|     <Extension path = "/OpenSim/Startup"> | ||||
|         <Plugin id="RegionModulesController" type="OpenSim.ApplicationPlugins.RegionModulesController.RegionModulesControllerPlugin" /> | ||||
|     </Extension> | ||||
| </Addin> | ||||
|  | @ -1,9 +1,8 @@ | |||
| using System.Reflection; | ||||
| using System.Runtime.CompilerServices; | ||||
| using System.Runtime.InteropServices; | ||||
| using Mono.Addins; | ||||
| 
 | ||||
| // General Information about an assembly is controlled through the following | ||||
| // General Information about an assembly is controlled through the following  | ||||
| // set of attributes. Change these attribute values to modify the information | ||||
| // associated with an assembly. | ||||
| [assembly: AssemblyTitle("OpenSim.ApplicationPlugins.RemoteController")] | ||||
|  | @ -15,8 +14,8 @@ using Mono.Addins; | |||
| [assembly: AssemblyTrademark("")] | ||||
| [assembly: AssemblyCulture("")] | ||||
| 
 | ||||
| // Setting ComVisible to false makes the types in this assembly not visible | ||||
| // to COM components.  If you need to access a type in this assembly from | ||||
| // Setting ComVisible to false makes the types in this assembly not visible  | ||||
| // to COM components.  If you need to access a type in this assembly from  | ||||
| // COM, set the ComVisible attribute to true on that type. | ||||
| [assembly: ComVisible(false)] | ||||
| 
 | ||||
|  | @ -26,11 +25,9 @@ using Mono.Addins; | |||
| // Version information for an assembly consists of the following four values: | ||||
| // | ||||
| //      Major Version | ||||
| //      Minor Version | ||||
| //      Minor Version  | ||||
| //      Build Number | ||||
| //      Revision | ||||
| // | ||||
| [assembly: AssemblyVersion(OpenSim.VersionInfo.AssemblyVersionNumber)] | ||||
| [assembly: AssemblyVersion("0.8.1.*")] | ||||
| 
 | ||||
| [assembly: Addin("OpenSim.ApplicationPlugins.RemoteController", OpenSim.VersionInfo.VersionNumber)] | ||||
| [assembly: AddinDependency("OpenSim", OpenSim.VersionInfo.VersionNumber)] | ||||
|  |  | |||
|  | @ -39,9 +39,9 @@ using log4net; | |||
| using Nini.Config; | ||||
| using Nwc.XmlRpc; | ||||
| using OpenMetaverse; | ||||
| using Mono.Addins; | ||||
| using OpenSim; | ||||
| using OpenSim.Framework; | ||||
| using OpenSim.Framework.Communications; | ||||
| using OpenSim.Framework.Console; | ||||
| using OpenSim.Framework.Servers; | ||||
| using OpenSim.Framework.Servers.HttpServer; | ||||
|  | @ -56,7 +56,6 @@ using RegionInfo = OpenSim.Framework.RegionInfo; | |||
| 
 | ||||
| namespace OpenSim.ApplicationPlugins.RemoteController | ||||
| { | ||||
|     [Extension(Path = "/OpenSim/Startup", Id = "LoadRegions", NodeName = "Plugin")] | ||||
|     public class RemoteAdminPlugin : IApplicationPlugin | ||||
|     { | ||||
|         private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | ||||
|  | @ -74,7 +73,6 @@ namespace OpenSim.ApplicationPlugins.RemoteController | |||
| 
 | ||||
|         private string m_name = "RemoteAdminPlugin"; | ||||
|         private string m_version = "0.0"; | ||||
|         private string m_openSimVersion; | ||||
| 
 | ||||
|         public string Version | ||||
|         { | ||||
|  | @ -94,8 +92,6 @@ namespace OpenSim.ApplicationPlugins.RemoteController | |||
| 
 | ||||
|         public void Initialise(OpenSimBase openSim) | ||||
|         { | ||||
|             m_openSimVersion = openSim.GetVersionText(); | ||||
| 
 | ||||
|             m_configSource = openSim.ConfigSource.Source; | ||||
|             try | ||||
|             { | ||||
|  | @ -138,13 +134,10 @@ namespace OpenSim.ApplicationPlugins.RemoteController | |||
|                     availableMethods["admin_region_query"] = (req, ep) => InvokeXmlRpcMethod(req, ep, XmlRpcRegionQueryMethod); | ||||
|                     availableMethods["admin_shutdown"] = (req, ep) => InvokeXmlRpcMethod(req, ep, XmlRpcShutdownMethod); | ||||
|                     availableMethods["admin_broadcast"] = (req, ep) => InvokeXmlRpcMethod(req, ep, XmlRpcAlertMethod); | ||||
|                     availableMethods["admin_dialog"] = (req, ep) => InvokeXmlRpcMethod(req, ep, XmlRpcDialogMethod); | ||||
|                     availableMethods["admin_restart"] = (req, ep) => InvokeXmlRpcMethod(req, ep, XmlRpcRestartMethod); | ||||
|                     availableMethods["admin_load_heightmap"] = (req, ep) => InvokeXmlRpcMethod(req, ep, XmlRpcLoadHeightmapMethod); | ||||
|                     availableMethods["admin_save_heightmap"] = (req, ep) => InvokeXmlRpcMethod(req, ep, XmlRpcSaveHeightmapMethod); | ||||
| 
 | ||||
|                     availableMethods["admin_reset_land"] = (req, ep) => InvokeXmlRpcMethod(req, ep, XmlRpcResetLand); | ||||
| 
 | ||||
|                     // Agent management | ||||
|                     availableMethods["admin_get_agents"] = (req, ep) => InvokeXmlRpcMethod(req, ep, XmlRpcGetAgentsMethod); | ||||
|                     availableMethods["admin_teleport_agent"] = (req, ep) => InvokeXmlRpcMethod(req, ep, XmlRpcTeleportAgentMethod); | ||||
|  | @ -169,11 +162,8 @@ namespace OpenSim.ApplicationPlugins.RemoteController | |||
|                     availableMethods["admin_acl_list"] = (req, ep) => InvokeXmlRpcMethod(req, ep, XmlRpcAccessListList); | ||||
|                     availableMethods["admin_estate_reload"] = (req, ep) => InvokeXmlRpcMethod(req, ep, XmlRpcEstateReload); | ||||
| 
 | ||||
|                     // Misc | ||||
|                     availableMethods["admin_refresh_search"] = (req, ep) => InvokeXmlRpcMethod(req, ep, XmlRpcRefreshSearch); | ||||
|                     availableMethods["admin_refresh_map"] = (req, ep) => InvokeXmlRpcMethod(req, ep, XmlRpcRefreshMap); | ||||
|                     availableMethods["admin_get_opensim_version"] = (req, ep) => InvokeXmlRpcMethod(req, ep, XmlRpcGetOpenSimVersion); | ||||
|                     availableMethods["admin_get_agent_count"] = (req, ep) => InvokeXmlRpcMethod(req, ep, XmlRpcGetAgentCount); | ||||
|                     // Land management | ||||
|                     availableMethods["admin_reset_land"] = (req, ep) => InvokeXmlRpcMethod(req, ep, XmlRpcResetLand); | ||||
| 
 | ||||
|                     // Either enable full remote functionality or just selected features | ||||
|                     string enabledMethods = m_config.GetString("enabled_methods", "all"); | ||||
|  | @ -274,148 +264,32 @@ namespace OpenSim.ApplicationPlugins.RemoteController | |||
| 
 | ||||
|             try | ||||
|             { | ||||
|                 m_log.Info("[RADMIN]: Request to restart Region."); | ||||
| 
 | ||||
|                 CheckRegionParams(requestData, responseData); | ||||
| 
 | ||||
|                 Scene rebootedScene = null; | ||||
|                 bool restartAll = false; | ||||
| 
 | ||||
|                 IConfig startupConfig = m_configSource.Configs["Startup"]; | ||||
|                 if (startupConfig != null) | ||||
|                 { | ||||
|                     if (startupConfig.GetBoolean("InworldRestartShutsDown", false)) | ||||
|                     { | ||||
|                         rebootedScene = m_application.SceneManager.CurrentOrFirstScene; | ||||
|                         restartAll = true; | ||||
|                     } | ||||
|                 } | ||||
| 
 | ||||
|                 if (rebootedScene == null) | ||||
|                 { | ||||
|                     CheckRegionParams(requestData, responseData); | ||||
| 
 | ||||
|                     GetSceneFromRegionParams(requestData, responseData, out rebootedScene); | ||||
|                 } | ||||
| 
 | ||||
|                 IRestartModule restartModule = rebootedScene.RequestModuleInterface<IRestartModule>(); | ||||
|                 GetSceneFromRegionParams(requestData, responseData, out rebootedScene); | ||||
| 
 | ||||
|                 responseData["success"] = false; | ||||
|                 responseData["accepted"] = true; | ||||
|                 responseData["rebooting"] = true; | ||||
| 
 | ||||
|                 string message; | ||||
|                 List<int> times = new List<int>(); | ||||
| 
 | ||||
|                 if (requestData.ContainsKey("alerts")) | ||||
|                 IRestartModule restartModule = rebootedScene.RequestModuleInterface<IRestartModule>(); | ||||
|                 if (restartModule != null) | ||||
|                 { | ||||
|                     string[] alertTimes = requestData["alerts"].ToString().Split( new char[] {','}); | ||||
|                     if (alertTimes.Length == 1 && Convert.ToInt32(alertTimes[0]) == -1) | ||||
|                     { | ||||
|                         m_log.Info("[RADMIN]: Request to cancel restart."); | ||||
|                     List<int> times = new List<int> { 30, 15 }; | ||||
| 
 | ||||
|                         if (restartModule != null) | ||||
|                         { | ||||
|                             message = "Restart has been cancelled"; | ||||
| 
 | ||||
|                             if (requestData.ContainsKey("message")) | ||||
|                                 message = requestData["message"].ToString(); | ||||
| 
 | ||||
|                             restartModule.AbortRestart(message); | ||||
| 
 | ||||
|                             responseData["success"] = true; | ||||
|                             responseData["rebooting"] = false; | ||||
| 
 | ||||
|                             return; | ||||
|                         } | ||||
|                     } | ||||
|                     foreach (string a in alertTimes) | ||||
|                         times.Add(Convert.ToInt32(a)); | ||||
|                     restartModule.ScheduleRestart(UUID.Zero, "Region will restart in {0}", times.ToArray(), true); | ||||
|                     responseData["success"] = true; | ||||
|                 } | ||||
|                 else | ||||
|                 { | ||||
|                     int timeout = 30; | ||||
|                     if (requestData.ContainsKey("milliseconds")) | ||||
|                         timeout = Int32.Parse(requestData["milliseconds"].ToString()) / 1000; | ||||
|                     while (timeout > 0) | ||||
|                     { | ||||
|                         times.Add(timeout); | ||||
|                         if (timeout > 300) | ||||
|                             timeout -= 120; | ||||
|                         else if (timeout > 30) | ||||
|                             timeout -= 30; | ||||
|                         else | ||||
|                             timeout -= 15; | ||||
|                     } | ||||
|                 } | ||||
| 
 | ||||
|                 m_log.Info("[RADMIN]: Request to restart Region."); | ||||
| 
 | ||||
|                 message = "Region is restarting in {0}. Please save what you are doing and log out."; | ||||
| 
 | ||||
|                 if (requestData.ContainsKey("message")) | ||||
|                     message = requestData["message"].ToString(); | ||||
| 
 | ||||
|                 bool notice = true; | ||||
|                 if (requestData.ContainsKey("noticetype") | ||||
|                     && ((string)requestData["noticetype"] == "dialog")) | ||||
|                 { | ||||
|                     notice = false; | ||||
|                 } | ||||
| 
 | ||||
|                 if (startupConfig.GetBoolean("SkipDelayOnEmptyRegion", false)) | ||||
|                 { | ||||
|                     m_log.Info("[RADMIN]: Counting affected avatars"); | ||||
|                     int agents = 0; | ||||
| 
 | ||||
|                     if (restartAll) | ||||
|                     { | ||||
|                         foreach (Scene s in m_application.SceneManager.Scenes) | ||||
|                         { | ||||
|                             foreach (ScenePresence sp in s.GetScenePresences()) | ||||
|                             { | ||||
|                                 if (!sp.IsChildAgent && !sp.IsNPC) | ||||
|                                     agents++; | ||||
|                             } | ||||
|                         } | ||||
|                     } | ||||
|                     else | ||||
|                     { | ||||
|                         foreach (ScenePresence sp in rebootedScene.GetScenePresences()) | ||||
|                         { | ||||
|                             if (!sp.IsChildAgent && !sp.IsNPC) | ||||
|                                 agents++; | ||||
|                         } | ||||
|                     } | ||||
| 
 | ||||
|                     m_log.InfoFormat("[RADMIN]: Avatars in region: {0}", agents); | ||||
| 
 | ||||
|                     if (agents == 0) | ||||
|                     { | ||||
|                         m_log.Info("[RADMIN]: No avatars detected, shutting down without delay"); | ||||
| 
 | ||||
|                         times.Clear(); | ||||
|                         times.Add(0); | ||||
|                     } | ||||
|                 } | ||||
| 
 | ||||
|                 List<Scene> restartList; | ||||
| 
 | ||||
|                 if (restartAll) | ||||
|                     restartList = m_application.SceneManager.Scenes; | ||||
|                 else | ||||
|                     restartList = new List<Scene>() { rebootedScene }; | ||||
| 
 | ||||
|                 foreach (Scene s in m_application.SceneManager.Scenes) | ||||
|                 { | ||||
|                     restartModule = s.RequestModuleInterface<IRestartModule>(); | ||||
|                     if (restartModule != null) | ||||
|                         restartModule.ScheduleRestart(UUID.Zero, message, times.ToArray(), notice); | ||||
|                 } | ||||
|                 responseData["success"] = true; | ||||
|             } | ||||
|             catch (Exception e) | ||||
|             { | ||||
|                 m_log.ErrorFormat("[RADMIN]: Restart region: failed: {0} {1}", e.Message, e.StackTrace); | ||||
| //                m_log.ErrorFormat("[RADMIN]: Restart region: failed: {0} {1}", e.Message, e.StackTrace); | ||||
|                 responseData["rebooting"] = false; | ||||
| 
 | ||||
|                 throw; | ||||
|                 throw e; | ||||
|             } | ||||
| 
 | ||||
|             m_log.Info("[RADMIN]: Restart Region request complete"); | ||||
|  | @ -445,32 +319,6 @@ namespace OpenSim.ApplicationPlugins.RemoteController | |||
|             m_log.Info("[RADMIN]: Alert request complete"); | ||||
|         } | ||||
| 
 | ||||
|         public void XmlRpcDialogMethod(XmlRpcRequest request, XmlRpcResponse response, IPEndPoint remoteClient) | ||||
|         { | ||||
|             Hashtable responseData = (Hashtable)response.Value; | ||||
| 
 | ||||
|             m_log.Info("[RADMIN]: Dialog request started"); | ||||
| 
 | ||||
|             Hashtable requestData = (Hashtable)request.Params[0]; | ||||
| 
 | ||||
|             string message = (string)requestData["message"]; | ||||
|             string fromuuid = (string)requestData["from"]; | ||||
|             m_log.InfoFormat("[RADMIN]: Broadcasting: {0}", message); | ||||
| 
 | ||||
|             responseData["accepted"] = true; | ||||
|             responseData["success"] = true; | ||||
| 
 | ||||
|             m_application.SceneManager.ForEachScene( | ||||
|                 delegate(Scene scene) | ||||
|                 { | ||||
|                     IDialogModule dialogModule = scene.RequestModuleInterface<IDialogModule>(); | ||||
|                     if (dialogModule != null) | ||||
|                         dialogModule.SendNotificationToUsersInRegion(UUID.Zero, fromuuid, message); | ||||
|                 }); | ||||
| 
 | ||||
|             m_log.Info("[RADMIN]: Dialog request complete"); | ||||
|         } | ||||
| 
 | ||||
|         private void XmlRpcLoadHeightmapMethod(XmlRpcRequest request, XmlRpcResponse response, IPEndPoint remoteClient) | ||||
|         { | ||||
|             m_log.Info("[RADMIN]: Load height maps request started"); | ||||
|  | @ -574,32 +422,13 @@ namespace OpenSim.ApplicationPlugins.RemoteController | |||
|                 message = "Region is going down now."; | ||||
|             } | ||||
| 
 | ||||
|             if (requestData.ContainsKey("noticetype") | ||||
|                 && ((string) requestData["noticetype"] == "dialog")) | ||||
|             { | ||||
|                 m_application.SceneManager.ForEachScene( | ||||
| 
 | ||||
|             m_application.SceneManager.ForEachScene( | ||||
|                 delegate(Scene scene) | ||||
|                 { | ||||
|                     IDialogModule dialogModule = scene.RequestModuleInterface<IDialogModule>(); | ||||
|                     if (dialogModule != null) | ||||
|                             dialogModule.SendNotificationToUsersInRegion(UUID.Zero, "System", message); | ||||
|                 }); | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 if (!requestData.ContainsKey("noticetype") | ||||
|                     || ((string)requestData["noticetype"] != "none")) | ||||
|                 { | ||||
|                     m_application.SceneManager.ForEachScene( | ||||
|                     delegate(Scene scene) | ||||
|                     { | ||||
|                         IDialogModule dialogModule = scene.RequestModuleInterface<IDialogModule>(); | ||||
|                         if (dialogModule != null) | ||||
|                             dialogModule.SendGeneralAlert(message); | ||||
|                     }); | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|             // Perform shutdown | ||||
|             System.Timers.Timer shutdownTimer = new System.Timers.Timer(timeout); // Wait before firing | ||||
|  | @ -611,7 +440,7 @@ namespace OpenSim.ApplicationPlugins.RemoteController | |||
|             } | ||||
| 
 | ||||
|             responseData["success"] = true; | ||||
| 
 | ||||
|              | ||||
|             m_log.Info("[RADMIN]: Shutdown Administrator Request complete"); | ||||
|         } | ||||
| 
 | ||||
|  | @ -783,9 +612,9 @@ namespace OpenSim.ApplicationPlugins.RemoteController | |||
|                     { | ||||
|                         // No INI setting recorded. | ||||
|                     } | ||||
| 
 | ||||
|                      | ||||
|                     string regionIniPath; | ||||
| 
 | ||||
|                      | ||||
|                     if (requestData.Contains("region_file")) | ||||
|                     { | ||||
|                         // Make sure that the file to be created is in a subdirectory of the region storage directory. | ||||
|  | @ -809,7 +638,7 @@ namespace OpenSim.ApplicationPlugins.RemoteController | |||
|                                                             region.RegionName.Replace(" ", "_").Replace(":", "_"). | ||||
|                                                                 Replace("/", "_"))); | ||||
|                     } | ||||
| 
 | ||||
|                      | ||||
|                     m_log.DebugFormat("[RADMIN] CreateRegion: persisting region {0} to {1}", | ||||
|                                       region.RegionID, regionIniPath); | ||||
|                     region.SaveRegionToFile("dynamic region", regionIniPath); | ||||
|  | @ -818,9 +647,9 @@ namespace OpenSim.ApplicationPlugins.RemoteController | |||
|                 { | ||||
|                     region.Persistent = false; | ||||
|                 } | ||||
| 
 | ||||
|                      | ||||
|                 // Set the estate | ||||
| 
 | ||||
|                  | ||||
|                 // Check for an existing estate | ||||
|                 List<int> estateIDs = m_application.EstateDataService.GetEstates((string) requestData["estate_name"]); | ||||
|                 if (estateIDs.Count < 1) | ||||
|  | @ -831,12 +660,12 @@ namespace OpenSim.ApplicationPlugins.RemoteController | |||
|                         // ok, client wants us to use an explicit UUID | ||||
|                         // regardless of what the avatar name provided | ||||
|                         userID = new UUID((string) requestData["estate_owner_uuid"]); | ||||
| 
 | ||||
|                          | ||||
|                         // Check that the specified user exists | ||||
|                         Scene currentOrFirst = m_application.SceneManager.CurrentOrFirstScene; | ||||
|                         IUserAccountService accountService = currentOrFirst.UserAccountService; | ||||
|                         UserAccount user = accountService.GetUserAccount(currentOrFirst.RegionInfo.ScopeID, userID); | ||||
| 
 | ||||
|                          | ||||
|                         if (user == null) | ||||
|                             throw new Exception("Specified user was not found."); | ||||
|                     } | ||||
|  | @ -845,23 +674,23 @@ namespace OpenSim.ApplicationPlugins.RemoteController | |||
|                         // We need to look up the UUID for the avatar with the provided name. | ||||
|                         string ownerFirst = (string) requestData["estate_owner_first"]; | ||||
|                         string ownerLast = (string) requestData["estate_owner_last"]; | ||||
| 
 | ||||
|                          | ||||
|                         Scene currentOrFirst = m_application.SceneManager.CurrentOrFirstScene; | ||||
|                         IUserAccountService accountService = currentOrFirst.UserAccountService; | ||||
|                         UserAccount user = accountService.GetUserAccount(currentOrFirst.RegionInfo.ScopeID, | ||||
|                                                                            ownerFirst, ownerLast); | ||||
| 
 | ||||
|                          | ||||
|                         // Check that the specified user exists | ||||
|                         if (user == null) | ||||
|                             throw new Exception("Specified user was not found."); | ||||
| 
 | ||||
|                          | ||||
|                         userID = user.PrincipalID; | ||||
|                     } | ||||
|                     else | ||||
|                     { | ||||
|                         throw new Exception("Estate owner details not provided."); | ||||
|                     } | ||||
| 
 | ||||
|                      | ||||
|                     // Create a new estate with the name provided | ||||
|                     region.EstateSettings = m_application.EstateDataService.CreateNewEstate(); | ||||
| 
 | ||||
|  | @ -888,7 +717,7 @@ namespace OpenSim.ApplicationPlugins.RemoteController | |||
|                             throw new Exception("Failed to join estate."); | ||||
|                     } | ||||
|                 } | ||||
| 
 | ||||
|                  | ||||
|                 // Create the region and perform any initial initialization | ||||
| 
 | ||||
|                 IScene newScene; | ||||
|  | @ -1195,7 +1024,7 @@ namespace OpenSim.ApplicationPlugins.RemoteController | |||
| 
 | ||||
|                     // Set home position | ||||
| 
 | ||||
|                     GridRegion home = scene.GridService.GetRegionByPosition(scopeID, | ||||
|                     GridRegion home = scene.GridService.GetRegionByPosition(scopeID,  | ||||
|                                         (int)Util.RegionToWorldLoc(regionXLocation), (int)Util.RegionToWorldLoc(regionYLocation)); | ||||
|                     if (null == home) | ||||
|                     { | ||||
|  | @ -1425,7 +1254,7 @@ namespace OpenSim.ApplicationPlugins.RemoteController | |||
| 
 | ||||
|                     if ((null != regionXLocation) && (null != regionYLocation)) | ||||
|                     { | ||||
|                         GridRegion home = scene.GridService.GetRegionByPosition(scopeID, | ||||
|                         GridRegion home = scene.GridService.GetRegionByPosition(scopeID,  | ||||
|                                         (int)Util.RegionToWorldLoc((uint)regionXLocation), (int)Util.RegionToWorldLoc((uint)regionYLocation)); | ||||
|                         if (null == home) { | ||||
|                             m_log.WarnFormat("[RADMIN]: Unable to set home region for updated user account {0} {1}", firstName, lastName); | ||||
|  | @ -1452,7 +1281,7 @@ namespace OpenSim.ApplicationPlugins.RemoteController | |||
| 
 | ||||
|                     throw e; | ||||
|                 } | ||||
| 
 | ||||
|                  | ||||
|                 m_log.Info("[RADMIN]: UpdateUserAccount: request complete"); | ||||
|             } | ||||
|         } | ||||
|  | @ -1644,7 +1473,7 @@ namespace OpenSim.ApplicationPlugins.RemoteController | |||
|                     GetSceneFromRegionParams(requestData, responseData, out scene); | ||||
| 
 | ||||
|                     string filename = (string) requestData["filename"]; | ||||
| 
 | ||||
|                      | ||||
|                     bool mergeOar = false; | ||||
|                     bool skipAssets = false; | ||||
| 
 | ||||
|  | @ -1658,7 +1487,7 @@ namespace OpenSim.ApplicationPlugins.RemoteController | |||
|                     } | ||||
| 
 | ||||
|                     IRegionArchiverModule archiver = scene.RequestModuleInterface<IRegionArchiverModule>(); | ||||
|                     Dictionary<string, object> archiveOptions = new Dictionary<string, object>(); | ||||
|                     Dictionary<string, object> archiveOptions = new Dictionary<string,object>(); | ||||
|                     if (mergeOar) archiveOptions.Add("merge", null); | ||||
|                     if (skipAssets) archiveOptions.Add("skipAssets", null); | ||||
|                     if (archiver != null) | ||||
|  | @ -1771,7 +1600,7 @@ namespace OpenSim.ApplicationPlugins.RemoteController | |||
|                     scene.EventManager.OnOarFileSaved += RemoteAdminOarSaveCompleted; | ||||
| 
 | ||||
|                     m_log.InfoFormat( | ||||
|                         "[RADMIN]: Submitting save OAR request for {0} to file {1}, request ID {2}", | ||||
|                         "[RADMIN]: Submitting save OAR request for {0} to file {1}, request ID {2}",  | ||||
|                         scene.Name, filename, requestId); | ||||
| 
 | ||||
|                     archiver.ArchiveRegion(filename, requestId, options); | ||||
|  | @ -1918,31 +1747,21 @@ namespace OpenSim.ApplicationPlugins.RemoteController | |||
| 
 | ||||
|         private void XmlRpcRegionQueryMethod(XmlRpcRequest request, XmlRpcResponse response, IPEndPoint remoteClient) | ||||
|         { | ||||
|             m_log.Info("[RADMIN]: Received Query XML Administrator Request"); | ||||
| 
 | ||||
|             Hashtable responseData = (Hashtable)response.Value; | ||||
|             Hashtable requestData = (Hashtable)request.Params[0]; | ||||
| 
 | ||||
|             int flags = 0; | ||||
|             string text = String.Empty; | ||||
|             int health = 0; | ||||
|             responseData["success"] = true; | ||||
| 
 | ||||
|             CheckRegionParams(requestData, responseData); | ||||
| 
 | ||||
|             Scene scene = null; | ||||
|             try | ||||
|             { | ||||
|                 GetSceneFromRegionParams(requestData, responseData, out scene); | ||||
|                 health = scene.GetHealth(out flags, out text); | ||||
|             } | ||||
|             catch | ||||
|             { | ||||
|                 responseData["error"] = null; | ||||
|             } | ||||
|             GetSceneFromRegionParams(requestData, responseData, out scene); | ||||
| 
 | ||||
|             int health = scene.GetHealth(); | ||||
|             responseData["health"] = health; | ||||
| 
 | ||||
|             responseData["success"] = true; | ||||
|             responseData["health"] = health; | ||||
|             responseData["flags"] = flags; | ||||
|             responseData["message"] = text; | ||||
|             m_log.Info("[RADMIN]: Query XML Administrator Request complete"); | ||||
|         } | ||||
| 
 | ||||
|         private void XmlRpcConsoleCommandMethod(XmlRpcRequest request, XmlRpcResponse response, IPEndPoint remoteClient) | ||||
|  | @ -2118,8 +1937,8 @@ namespace OpenSim.ApplicationPlugins.RemoteController | |||
|             Hashtable responseData = (Hashtable)response.Value; | ||||
| //            Hashtable requestData = (Hashtable)request.Params[0]; | ||||
| 
 | ||||
|             m_application.SceneManager.ForEachScene(s => | ||||
|                 s.RegionInfo.EstateSettings = m_application.EstateDataService.LoadEstateSettings(s.RegionInfo.RegionID, false) | ||||
|             m_application.SceneManager.ForEachScene(s =>  | ||||
|                 s.RegionInfo.EstateSettings = m_application.EstateDataService.LoadEstateSettings(s.RegionInfo.RegionID, false)                 | ||||
|             ); | ||||
| 
 | ||||
|             responseData["success"] = true; | ||||
|  | @ -2251,6 +2070,7 @@ namespace OpenSim.ApplicationPlugins.RemoteController | |||
|         { | ||||
|             Hashtable requestData = (Hashtable)request.Params[0]; | ||||
|             Hashtable responseData = (Hashtable)response.Value; | ||||
| 
 | ||||
|             string musicURL = string.Empty; | ||||
|             UUID groupID = UUID.Zero; | ||||
|             uint flags = 0; | ||||
|  | @ -2260,129 +2080,41 @@ namespace OpenSim.ApplicationPlugins.RemoteController | |||
|                 set_group = UUID.TryParse(requestData["group"].ToString(), out groupID); | ||||
|             if (requestData.Contains("music") && requestData["music"] != null) | ||||
|             { | ||||
| 
 | ||||
|                 musicURL = requestData["music"].ToString(); | ||||
|                 set_music = true; | ||||
|             } | ||||
| 
 | ||||
|             if (requestData.Contains("flags") && requestData["flags"] != null) | ||||
|                 set_flags = UInt32.TryParse(requestData["flags"].ToString(), out flags); | ||||
| 
 | ||||
|             m_log.InfoFormat("[RADMIN]: Received Reset Land Request group={0} musicURL={1} flags={2}", | ||||
|                 (set_group ? groupID.ToString() : "unchanged"), | ||||
|                 (set_music ? musicURL : "unchanged"), | ||||
|             m_log.InfoFormat("[RADMIN]: Received Reset Land Request group={0} musicURL={1} flags={2}",  | ||||
|                 (set_group ? groupID.ToString() : "unchanged"),  | ||||
|                 (set_music ? musicURL : "unchanged"),  | ||||
|                 (set_flags ? flags.ToString() : "unchanged")); | ||||
| 
 | ||||
|             m_application.SceneManager.ForEachScene(delegate (Scene s) | ||||
|             m_application.SceneManager.ForEachScene(delegate(Scene s) | ||||
|             { | ||||
|                 List<ILandObject> parcels = s.LandChannel.AllParcels(); | ||||
|                 foreach (ILandObject p in parcels) | ||||
|                 { | ||||
|                     if (set_music) | ||||
|                         p.LandData.MusicURL = musicURL; | ||||
| 
 | ||||
|                     if (set_group) | ||||
|                         p.LandData.GroupID = groupID; | ||||
| 
 | ||||
|                     if (set_flags) | ||||
|                         p.LandData.Flags = flags; | ||||
| 
 | ||||
|                     s.LandChannel.UpdateLandObject(p.LandData.LocalID, p.LandData); | ||||
|                 } | ||||
|             } | ||||
|             ); | ||||
| 
 | ||||
|             responseData["success"] = true; | ||||
| 
 | ||||
|             m_log.Info("[RADMIN]: Reset Land Request complete"); | ||||
|         } | ||||
| 
 | ||||
|         private void XmlRpcRefreshSearch(XmlRpcRequest request, XmlRpcResponse response, IPEndPoint remoteClient) | ||||
|         { | ||||
|             m_log.Info("[RADMIN]: Received Refresh Search Request"); | ||||
| 
 | ||||
|             Hashtable responseData = (Hashtable)response.Value; | ||||
|             Hashtable requestData = (Hashtable)request.Params[0]; | ||||
| 
 | ||||
|             CheckRegionParams(requestData, responseData); | ||||
| 
 | ||||
|             Scene scene = null; | ||||
|             GetSceneFromRegionParams(requestData, responseData, out scene); | ||||
| 
 | ||||
|             ISearchModule searchModule = scene.RequestModuleInterface<ISearchModule>(); | ||||
|             if (searchModule != null) | ||||
|             { | ||||
|                 searchModule.Refresh(); | ||||
|                 responseData["success"] = true; | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 responseData["success"] = false; | ||||
|             } | ||||
| 
 | ||||
|             m_log.Info("[RADMIN]: Refresh Search Request complete"); | ||||
|         } | ||||
| 
 | ||||
|         private void XmlRpcRefreshMap(XmlRpcRequest request, XmlRpcResponse response, IPEndPoint remoteClient) | ||||
|         { | ||||
|             m_log.Info("[RADMIN]: Received Refresh Map Request"); | ||||
| 
 | ||||
|             Hashtable responseData = (Hashtable)response.Value; | ||||
|             Hashtable requestData = (Hashtable)request.Params[0]; | ||||
| 
 | ||||
|             CheckRegionParams(requestData, responseData); | ||||
| 
 | ||||
|             Scene scene = null; | ||||
|             GetSceneFromRegionParams(requestData, responseData, out scene); | ||||
| 
 | ||||
|             IMapImageUploadModule mapTileModule = scene.RequestModuleInterface<IMapImageUploadModule>(); | ||||
|             if (mapTileModule != null) | ||||
|             { | ||||
|                 Util.FireAndForget((x) => | ||||
|                 { | ||||
|                     mapTileModule.UploadMapTile(scene); | ||||
|                 }); | ||||
|                 responseData["success"] = true; | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 responseData["success"] = false; | ||||
|             } | ||||
| 
 | ||||
|             m_log.Info("[RADMIN]: Refresh Map Request complete"); | ||||
|         } | ||||
| 
 | ||||
|         private void XmlRpcGetOpenSimVersion(XmlRpcRequest request, XmlRpcResponse response, IPEndPoint remoteClient) | ||||
|         { | ||||
|             m_log.Info("[RADMIN]: Received Get OpenSim Version Request"); | ||||
| 
 | ||||
|             Hashtable responseData = (Hashtable)response.Value; | ||||
| 
 | ||||
|             responseData["version"] = m_openSimVersion; | ||||
|             responseData["success"] = true; | ||||
| 
 | ||||
|             m_log.Info("[RADMIN]: Get OpenSim Version Request complete"); | ||||
|         } | ||||
| 
 | ||||
|         private void XmlRpcGetAgentCount(XmlRpcRequest request, XmlRpcResponse response, IPEndPoint remoteClient) | ||||
|         { | ||||
|             m_log.Info("[RADMIN]: Received Get Agent Count Request"); | ||||
| 
 | ||||
|             Hashtable responseData = (Hashtable)response.Value; | ||||
|             Hashtable requestData = (Hashtable)request.Params[0]; | ||||
| 
 | ||||
|             CheckRegionParams(requestData, responseData); | ||||
| 
 | ||||
|             Scene scene = null; | ||||
|             GetSceneFromRegionParams(requestData, responseData, out scene); | ||||
| 
 | ||||
|             if (scene == null) | ||||
|             { | ||||
|                 responseData["success"] = false; | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 responseData["count"] = scene.GetRootAgentCount(); | ||||
|                 responseData["success"] = true; | ||||
|             } | ||||
| 
 | ||||
|             m_log.Info("[RADMIN]: Get Agent Count Request complete"); | ||||
|         } | ||||
| 
 | ||||
|         /// <summary> | ||||
|         /// Parse a float with the given parameter name from a request data hash table. | ||||
|  | @ -2805,8 +2537,8 @@ namespace OpenSim.ApplicationPlugins.RemoteController | |||
|             try | ||||
|             { | ||||
|                 Dictionary<UUID,UUID> inventoryMap = new Dictionary<UUID,UUID>(); | ||||
|                 CopyInventoryFolders(destination, source, FolderType.Clothing, inventoryMap, avatarAppearance); | ||||
|                 CopyInventoryFolders(destination, source, FolderType.BodyPart, inventoryMap, avatarAppearance); | ||||
|                 CopyInventoryFolders(destination, source, AssetType.Clothing, inventoryMap, avatarAppearance); | ||||
|                 CopyInventoryFolders(destination, source, AssetType.Bodypart, inventoryMap, avatarAppearance); | ||||
| 
 | ||||
|                 AvatarWearable[] wearables = avatarAppearance.Wearables; | ||||
| 
 | ||||
|  | @ -2842,20 +2574,20 @@ namespace OpenSim.ApplicationPlugins.RemoteController | |||
|             IInventoryService inventoryService = m_application.SceneManager.CurrentOrFirstScene.InventoryService; | ||||
| 
 | ||||
|             // Get Clothing folder of receiver | ||||
|             InventoryFolderBase destinationFolder = inventoryService.GetFolderForType(destination, FolderType.Clothing); | ||||
|             InventoryFolderBase destinationFolder = inventoryService.GetFolderForType(destination, AssetType.Clothing); | ||||
| 
 | ||||
|             if (destinationFolder == null) | ||||
|                 throw new Exception("Cannot locate folder(s)"); | ||||
| 
 | ||||
|             // Missing destination folder? This should *never* be the case | ||||
|             if (destinationFolder.Type != (short)FolderType.Clothing) | ||||
|             if (destinationFolder.Type != (short)AssetType.Clothing) | ||||
|             { | ||||
|                 destinationFolder = new InventoryFolderBase(); | ||||
| 
 | ||||
|                  | ||||
|                 destinationFolder.ID       = UUID.Random(); | ||||
|                 destinationFolder.Name     = "Clothing"; | ||||
|                 destinationFolder.Owner    = destination; | ||||
|                 destinationFolder.Type = (short)FolderType.Clothing; | ||||
|                 destinationFolder.Type     = (short)AssetType.Clothing; | ||||
|                 destinationFolder.ParentID = inventoryService.GetRootFolder(destination).ID; | ||||
|                 destinationFolder.Version  = 1; | ||||
|                 inventoryService.AddFolder(destinationFolder);     // store base record | ||||
|  | @ -2872,7 +2604,8 @@ namespace OpenSim.ApplicationPlugins.RemoteController | |||
|                 if (wearable[0].ItemID != UUID.Zero) | ||||
|                 { | ||||
|                     // Get inventory item and copy it | ||||
|                     InventoryItemBase item = inventoryService.GetItem(source, wearable[0].ItemID); | ||||
|                     InventoryItemBase item = new InventoryItemBase(wearable[0].ItemID, source); | ||||
|                     item = inventoryService.GetItem(item); | ||||
| 
 | ||||
|                     if (item != null) | ||||
|                     { | ||||
|  | @ -2925,7 +2658,8 @@ namespace OpenSim.ApplicationPlugins.RemoteController | |||
|                 if (itemID != UUID.Zero) | ||||
|                 { | ||||
|                     // Get inventory item and copy it | ||||
|                     InventoryItemBase item = inventoryService.GetItem(source, itemID); | ||||
|                     InventoryItemBase item = new InventoryItemBase(itemID, source); | ||||
|                     item = inventoryService.GetItem(item); | ||||
| 
 | ||||
|                     if (item != null) | ||||
|                     { | ||||
|  | @ -2971,7 +2705,7 @@ namespace OpenSim.ApplicationPlugins.RemoteController | |||
|         /// This method is called by establishAppearance to copy inventory folders to make | ||||
|         /// copies of Clothing and Bodyparts inventory folders and attaches worn attachments | ||||
|         /// </summary> | ||||
|         private void CopyInventoryFolders(UUID destination, UUID source, FolderType assetType, Dictionary<UUID, UUID> inventoryMap, | ||||
|         private void CopyInventoryFolders(UUID destination, UUID source, AssetType assetType, Dictionary<UUID,UUID> inventoryMap, | ||||
|                                           AvatarAppearance avatarAppearance) | ||||
|         { | ||||
|             IInventoryService inventoryService = m_application.SceneManager.CurrentOrFirstScene.InventoryService; | ||||
|  | @ -2987,12 +2721,9 @@ namespace OpenSim.ApplicationPlugins.RemoteController | |||
|             { | ||||
|                 sourceFolder = new InventoryFolderBase(); | ||||
|                 sourceFolder.ID       = UUID.Random(); | ||||
|                 if (assetType == FolderType.Clothing) | ||||
|                 { | ||||
|                 if (assetType == AssetType.Clothing) { | ||||
|                     sourceFolder.Name     = "Clothing"; | ||||
|                 } | ||||
|                 else | ||||
|                 { | ||||
|                 } else { | ||||
|                     sourceFolder.Name     = "Body Parts"; | ||||
|                 } | ||||
|                 sourceFolder.Owner    = source; | ||||
|  | @ -3008,7 +2739,7 @@ namespace OpenSim.ApplicationPlugins.RemoteController | |||
|             { | ||||
|                 destinationFolder = new InventoryFolderBase(); | ||||
|                 destinationFolder.ID       = UUID.Random(); | ||||
|                 if (assetType == FolderType.Clothing) | ||||
|                 if (assetType == AssetType.Clothing) | ||||
|                 { | ||||
|                     destinationFolder.Name  = "Clothing"; | ||||
|                 } | ||||
|  | @ -3204,7 +2935,7 @@ namespace OpenSim.ApplicationPlugins.RemoteController | |||
| 
 | ||||
|                             // Set home position | ||||
| 
 | ||||
|                             GridRegion home = scene.GridService.GetRegionByPosition(scopeID, | ||||
|                             GridRegion home = scene.GridService.GetRegionByPosition(scopeID,  | ||||
|                                         (int)Util.RegionToWorldLoc(regionXLocation), (int)Util.RegionToWorldLoc(regionYLocation)); | ||||
|                             if (null == home) { | ||||
|                                 m_log.WarnFormat("[RADMIN]: Unable to set home region for newly created user account {0} {1}", names[0], names[1]); | ||||
|  | @ -3247,16 +2978,16 @@ namespace OpenSim.ApplicationPlugins.RemoteController | |||
|                                 // m_log.DebugFormat("[RADMIN] {0} folders, {1} items in inventory", | ||||
|                                 //   uic.folders.Count, uic.items.Count); | ||||
| 
 | ||||
|                                 InventoryFolderBase clothingFolder = inventoryService.GetFolderForType(ID, FolderType.Clothing); | ||||
|                                 InventoryFolderBase clothingFolder = inventoryService.GetFolderForType(ID, AssetType.Clothing); | ||||
| 
 | ||||
|                                 // This should *never* be the case | ||||
|                                 if (clothingFolder == null || clothingFolder.Type != (short)FolderType.Clothing) | ||||
|                                 if (clothingFolder == null || clothingFolder.Type != (short)AssetType.Clothing) | ||||
|                                 { | ||||
|                                     clothingFolder = new InventoryFolderBase(); | ||||
|                                     clothingFolder.ID       = UUID.Random(); | ||||
|                                     clothingFolder.Name     = "Clothing"; | ||||
|                                     clothingFolder.Owner    = ID; | ||||
|                                     clothingFolder.Type     = (short)FolderType.Clothing; | ||||
|                                     clothingFolder.Type     = (short)AssetType.Clothing; | ||||
|                                     clothingFolder.ParentID = inventoryService.GetRootFolder(ID).ID; | ||||
|                                     clothingFolder.Version  = 1; | ||||
|                                     inventoryService.AddFolder(clothingFolder);     // store base record | ||||
|  | @ -3302,7 +3033,7 @@ namespace OpenSim.ApplicationPlugins.RemoteController | |||
|                                         extraFolder.ID       = UUID.Random(); | ||||
|                                         extraFolder.Name     = outfitName; | ||||
|                                         extraFolder.Owner    = ID; | ||||
|                                         extraFolder.Type     = (short)FolderType.Clothing; | ||||
|                                         extraFolder.Type     = (short)AssetType.Clothing; | ||||
|                                         extraFolder.Version  = 1; | ||||
|                                         extraFolder.ParentID = clothingFolder.ID; | ||||
|                                         inventoryService.AddFolder(extraFolder); | ||||
|  |  | |||
|  | @ -0,0 +1,11 @@ | |||
| <Addin id="OpenSim.ApplicationPlugins.RemoteController" version="0.1"> | ||||
|     <Runtime> | ||||
|         <Import assembly="OpenSim.ApplicationPlugins.RemoteController.dll"/> | ||||
|     </Runtime> | ||||
|     <Dependencies> | ||||
|         <Addin id="OpenSim" version="0.5" /> | ||||
|     </Dependencies> | ||||
|     <Extension path = "/OpenSim/Startup"> | ||||
|         <Plugin id="RemoteController" type="OpenSim.ApplicationPlugins.RemoteController.RemoteAdminPlugin" /> | ||||
|     </Extension> | ||||
| </Addin> | ||||
|  | @ -28,10 +28,8 @@ | |||
| using System; | ||||
| using System.Collections; | ||||
| using System.Collections.Generic; | ||||
| using System.Collections.Concurrent; | ||||
| using System.IO; | ||||
| using System.Reflection; | ||||
| using System.Threading; | ||||
| using log4net; | ||||
| using Nini.Config; | ||||
| using OpenMetaverse; | ||||
|  | @ -50,9 +48,9 @@ namespace OpenSim.Framework.Capabilities | |||
|     /// </summary> | ||||
|     public delegate IClientAPI GetClientDelegate(UUID agentID); | ||||
| 
 | ||||
|     public class Caps : IDisposable | ||||
|     public class Caps | ||||
|     { | ||||
|         private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | ||||
| //        private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | ||||
| 
 | ||||
|         private string m_httpListenerHostName; | ||||
|         private uint m_httpListenPort; | ||||
|  | @ -65,15 +63,14 @@ namespace OpenSim.Framework.Capabilities | |||
| 
 | ||||
|         private CapsHandlers m_capsHandlers; | ||||
| 
 | ||||
|         private ConcurrentDictionary<string, PollServiceEventArgs> m_pollServiceHandlers | ||||
|             = new ConcurrentDictionary<string, PollServiceEventArgs>(); | ||||
|         private Dictionary<string, PollServiceEventArgs> m_pollServiceHandlers  | ||||
|             = new Dictionary<string, PollServiceEventArgs>(); | ||||
| 
 | ||||
|         private Dictionary<string, string> m_externalCapsHandlers = new Dictionary<string, string>(); | ||||
| 
 | ||||
|         private IHttpServer m_httpListener; | ||||
|         private UUID m_agentID; | ||||
|         private string m_regionName; | ||||
|         private ManualResetEvent m_capsActive = new ManualResetEvent(false); | ||||
| 
 | ||||
|         public UUID AgentID | ||||
|         { | ||||
|  | @ -120,19 +117,6 @@ namespace OpenSim.Framework.Capabilities | |||
|             get { return m_externalCapsHandlers; } | ||||
|         } | ||||
| 
 | ||||
|         [Flags] | ||||
|         public enum CapsFlags:uint | ||||
|         { | ||||
|             None =          0, | ||||
|             SentSeeds =     1, | ||||
| 
 | ||||
|             ObjectAnim =    0x100, | ||||
|             WLEnv =         0x200, | ||||
|             AdvEnv =        0x400 | ||||
|         } | ||||
| 
 | ||||
|         public CapsFlags Flags { get; set;} | ||||
| 
 | ||||
|         public Caps(IHttpServer httpServer, string httpListen, uint httpPort, string capsPath, | ||||
|                     UUID agent, string regionName) | ||||
|         { | ||||
|  | @ -150,37 +134,8 @@ namespace OpenSim.Framework.Capabilities | |||
|             } | ||||
| 
 | ||||
|             m_agentID = agent; | ||||
|             m_capsHandlers = new CapsHandlers(httpServer, httpListen, httpPort); | ||||
|             m_capsHandlers = new CapsHandlers(httpServer, httpListen, httpPort, (httpServer == null) ? false : httpServer.UseSSL); | ||||
|             m_regionName = regionName; | ||||
|             Flags = CapsFlags.None; | ||||
|             m_capsActive.Reset(); | ||||
|         } | ||||
| 
 | ||||
|         ~Caps() | ||||
|         { | ||||
|             Flags = CapsFlags.None; | ||||
|             if (m_capsActive!= null) | ||||
|             { | ||||
|                 m_capsActive.Dispose(); | ||||
|                 m_capsActive = null; | ||||
|             } | ||||
|         } | ||||
|          | ||||
|         public void Dispose() | ||||
|         { | ||||
|             Dispose(true); | ||||
|             GC.SuppressFinalize(this); | ||||
|         } | ||||
| 
 | ||||
|         public void Dispose(bool disposing) | ||||
|         { | ||||
|             Flags = CapsFlags.None; | ||||
|             if (m_capsActive != null) | ||||
|             { | ||||
|                 DeregisterHandlers(); | ||||
|                 m_capsActive.Dispose(); | ||||
|                 m_capsActive = null; | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         /// <summary> | ||||
|  | @ -194,32 +149,20 @@ namespace OpenSim.Framework.Capabilities | |||
|             m_capsHandlers[capName] = handler; | ||||
|         } | ||||
| 
 | ||||
|         public void RegisterSimpleHandler(string capName, ISimpleStreamHandler handler, bool addToListener = true) | ||||
|         { | ||||
|             //m_log.DebugFormat("[CAPS]: Registering handler for \"{0}\": path {1}", capName, handler.Path); | ||||
|             m_capsHandlers.AddSimpleHandler(capName, handler, addToListener); | ||||
|         } | ||||
| 
 | ||||
|         public void RegisterPollHandler(string capName, PollServiceEventArgs pollServiceHandler) | ||||
|         { | ||||
| //            m_log.DebugFormat( | ||||
| //                "[CAPS]: Registering handler with name {0}, url {1} for {2}", | ||||
| //                "[CAPS]: Registering handler with name {0}, url {1} for {2}",  | ||||
| //                capName, pollServiceHandler.Url, m_agentID, m_regionName); | ||||
| 
 | ||||
|             if(!m_pollServiceHandlers.TryAdd(capName, pollServiceHandler)) | ||||
|             { | ||||
|                 m_log.ErrorFormat( | ||||
|                     "[CAPS]: Handler with name {0} already registered (ulr {1}, agent {2}, region {3}", | ||||
|                     capName, pollServiceHandler.Url, m_agentID, m_regionName); | ||||
|                 return; | ||||
|             } | ||||
|             m_pollServiceHandlers.Add(capName, pollServiceHandler); | ||||
| 
 | ||||
|             m_httpListener.AddPollServiceHTTPHandler(pollServiceHandler); | ||||
|             m_httpListener.AddPollServiceHTTPHandler(pollServiceHandler.Url, pollServiceHandler); | ||||
| 
 | ||||
| //            uint port = (MainServer.Instance == null) ? 0 : MainServer.Instance.Port; | ||||
| //            string protocol = "http"; | ||||
| //            string hostName = m_httpListenerHostName; | ||||
| // | ||||
| //             | ||||
| //            if (MainServer.Instance.UseSSL) | ||||
| //            { | ||||
| //                hostName = MainServer.Instance.SSLCommonName; | ||||
|  | @ -254,9 +197,8 @@ namespace OpenSim.Framework.Capabilities | |||
| 
 | ||||
|             foreach (PollServiceEventArgs handler in m_pollServiceHandlers.Values) | ||||
|             { | ||||
|                 m_httpListener.RemovePollServiceHTTPHandler(handler.Url); | ||||
|                 m_httpListener.RemovePollServiceHTTPHandler("", handler.Url); | ||||
|             } | ||||
|             m_pollServiceHandlers.Clear(); | ||||
|         } | ||||
| 
 | ||||
|         public bool TryGetPollHandler(string name, out PollServiceEventArgs pollHandler) | ||||
|  | @ -288,13 +230,16 @@ namespace OpenSim.Framework.Capabilities | |||
|                         string hostName = m_httpListenerHostName; | ||||
|                         uint port = (MainServer.Instance == null) ? 0 : MainServer.Instance.Port; | ||||
|                         string protocol = "http"; | ||||
| 
 | ||||
|                          | ||||
|                         if (MainServer.Instance.UseSSL) | ||||
|                         { | ||||
|                             hostName = MainServer.Instance.SSLCommonName; | ||||
|                             port = MainServer.Instance.SSLPort; | ||||
|                             protocol = "https"; | ||||
|                         } | ||||
|     // | ||||
|     //            caps.RegisterHandler("FetchInventoryDescendents2", String.Format("{0}://{1}:{2}{3}", protocol, hostName, port, capUrl)); | ||||
| 
 | ||||
|                         caps[kvp.Key] = string.Format("{0}://{1}:{2}{3}", protocol, hostName, port, kvp.Value.Url); | ||||
|                 } | ||||
|             } | ||||
|  | @ -308,19 +253,7 @@ namespace OpenSim.Framework.Capabilities | |||
|                 caps[kvp.Key] = kvp.Value; | ||||
|             } | ||||
| 
 | ||||
| 
 | ||||
|             return caps; | ||||
|         } | ||||
| 
 | ||||
|         public void Activate() | ||||
|         { | ||||
|             m_capsActive.Set(); | ||||
|         } | ||||
| 
 | ||||
|         public bool WaitForActivation() | ||||
|         { | ||||
|             // Wait for 30s. If that elapses, return false and run without caps | ||||
|             return m_capsActive.WaitOne(120000); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | @ -27,7 +27,6 @@ | |||
| 
 | ||||
| using System.Collections; | ||||
| using System.Collections.Generic; | ||||
| using System.Collections.Concurrent; | ||||
| using OpenSim.Framework.Servers; | ||||
| using OpenSim.Framework.Servers.HttpServer; | ||||
| 
 | ||||
|  | @ -41,7 +40,6 @@ namespace OpenSim.Framework.Capabilities | |||
|     public class CapsHandlers | ||||
|     { | ||||
|         private Dictionary<string, IRequestHandler> m_capsHandlers = new Dictionary<string, IRequestHandler>(); | ||||
|         private ConcurrentDictionary<string, ISimpleStreamHandler> m_capsSimpleHandlers = new ConcurrentDictionary<string, ISimpleStreamHandler>(); | ||||
|         private IHttpServer m_httpListener; | ||||
|         private string m_httpListenerHostName; | ||||
|         private uint m_httpListenerPort; | ||||
|  | @ -55,15 +53,31 @@ namespace OpenSim.Framework.Capabilities | |||
|         /// <param name="httpListener">base HTTP server</param> | ||||
|         /// <param name="httpListenerHostname">host name of the HTTP server</param> | ||||
|         /// <param name="httpListenerPort">HTTP port</param> | ||||
|         public CapsHandlers(IHttpServer httpListener, string httpListenerHostname, uint httpListenerPort) | ||||
|            { | ||||
|         public CapsHandlers(BaseHttpServer httpListener, string httpListenerHostname, uint httpListenerPort) | ||||
|             : this(httpListener,httpListenerHostname,httpListenerPort, false) | ||||
|         { | ||||
|         } | ||||
| 
 | ||||
|         /// <summary></summary> | ||||
|         /// CapsHandlers is a cap handler container but also takes | ||||
|         /// care of adding and removing cap handlers to and from the | ||||
|         /// supplied BaseHttpServer. | ||||
|         /// </summary> | ||||
|         /// <param name="httpListener">base HTTP server</param> | ||||
|         /// <param name="httpListenerHostname">host name of the HTTP | ||||
|         /// server</param> | ||||
|         /// <param name="httpListenerPort">HTTP port</param> | ||||
|         public CapsHandlers(IHttpServer httpListener, string httpListenerHostname, uint httpListenerPort, bool https) | ||||
|         { | ||||
|             m_httpListener = httpListener; | ||||
|             m_httpListenerHostName = httpListenerHostname; | ||||
|             m_httpListenerPort = httpListenerPort; | ||||
|             if (httpListener != null && httpListener.UseSSL) | ||||
|                 m_useSSL = true; | ||||
|             else | ||||
|                 m_useSSL = false; | ||||
|             m_useSSL = https; | ||||
|             if (httpListener != null && m_useSSL) | ||||
|             { | ||||
|                 m_httpListenerHostName = httpListener.SSLCommonName; | ||||
|                 m_httpListenerPort = httpListener.SSLPort; | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         /// <summary> | ||||
|  | @ -75,35 +89,16 @@ namespace OpenSim.Framework.Capabilities | |||
|         { | ||||
|             lock (m_capsHandlers) | ||||
|             { | ||||
|                 if(m_capsHandlers.ContainsKey(capsName)) | ||||
|                 { | ||||
|                     m_httpListener.RemoveStreamHandler("POST", m_capsHandlers[capsName].Path); | ||||
|                     m_httpListener.RemoveStreamHandler("PUT", m_capsHandlers[capsName].Path); | ||||
|                     m_httpListener.RemoveStreamHandler("GET", m_capsHandlers[capsName].Path); | ||||
|                     m_httpListener.RemoveStreamHandler("DELETE", m_capsHandlers[capsName].Path); | ||||
|                     m_capsHandlers.Remove(capsName); | ||||
|                 } | ||||
|                 m_httpListener.RemoveStreamHandler("POST", m_capsHandlers[capsName].Path); | ||||
|                 m_httpListener.RemoveStreamHandler("GET", m_capsHandlers[capsName].Path); | ||||
|                 m_capsHandlers.Remove(capsName); | ||||
|             } | ||||
|             if(m_capsSimpleHandlers.TryRemove(capsName, out ISimpleStreamHandler hdr)) | ||||
|             { | ||||
|                 m_httpListener.RemoveSimpleStreamHandler(hdr.Path); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         public void AddSimpleHandler(string capName, ISimpleStreamHandler handler, bool addToListener = true) | ||||
|         { | ||||
|             if(ContainsCap(capName)) | ||||
|                 Remove(capName); | ||||
|             if(m_capsSimpleHandlers.TryAdd(capName, handler) && addToListener) | ||||
|                 m_httpListener.AddSimpleStreamHandler(handler); | ||||
|         } | ||||
| 
 | ||||
|         public bool ContainsCap(string cap) | ||||
|         { | ||||
|             lock (m_capsHandlers) | ||||
|                 if (m_capsHandlers.ContainsKey(cap)) | ||||
|                     return true; | ||||
|             return m_capsSimpleHandlers.ContainsKey(cap); | ||||
|                 return m_capsHandlers.ContainsKey(cap); | ||||
|         } | ||||
| 
 | ||||
|         /// <summary> | ||||
|  | @ -130,14 +125,11 @@ namespace OpenSim.Framework.Capabilities | |||
|                     if (m_capsHandlers.ContainsKey(idx)) | ||||
|                     { | ||||
|                         m_httpListener.RemoveStreamHandler("POST", m_capsHandlers[idx].Path); | ||||
|                         m_httpListener.RemoveStreamHandler("PUT", m_capsHandlers[idx].Path); | ||||
|                         m_httpListener.RemoveStreamHandler("GET", m_capsHandlers[idx].Path); | ||||
|                         m_httpListener.RemoveStreamHandler("DELETE", m_capsHandlers[idx].Path); | ||||
|                         m_capsHandlers.Remove(idx); | ||||
|                     } | ||||
| 
 | ||||
|      | ||||
|                     if (null == value) return; | ||||
| 
 | ||||
|      | ||||
|                     m_capsHandlers[idx] = value; | ||||
|                     m_httpListener.AddStreamHandler(value); | ||||
|                 } | ||||
|  | @ -154,9 +146,8 @@ namespace OpenSim.Framework.Capabilities | |||
|             { | ||||
|                 lock (m_capsHandlers) | ||||
|                 { | ||||
|                     string[] __keys = new string[m_capsHandlers.Keys.Count + m_capsSimpleHandlers.Keys.Count]; | ||||
|                     string[] __keys = new string[m_capsHandlers.Keys.Count]; | ||||
|                     m_capsHandlers.Keys.CopyTo(__keys, 0); | ||||
|                     m_capsSimpleHandlers.Keys.CopyTo(__keys, m_capsHandlers.Keys.Count); | ||||
|                     return __keys; | ||||
|                 } | ||||
|             } | ||||
|  | @ -170,39 +161,24 @@ namespace OpenSim.Framework.Capabilities | |||
|         public Hashtable GetCapsDetails(bool excludeSeed, List<string> requestedCaps) | ||||
|         { | ||||
|             Hashtable caps = new Hashtable(); | ||||
|             string protocol = "http://"; | ||||
|              | ||||
|             if (m_useSSL) | ||||
|                 protocol = "https://"; | ||||
| 
 | ||||
|             string protocol = m_useSSL ? "https://" : "http://"; | ||||
|             string baseUrl = protocol + m_httpListenerHostName + ":" + m_httpListenerPort.ToString(); | ||||
| 
 | ||||
|             if (requestedCaps == null) | ||||
|             { | ||||
|                 lock (m_capsHandlers) | ||||
|                 { | ||||
|                     foreach (KeyValuePair<string, ISimpleStreamHandler> kvp in m_capsSimpleHandlers) | ||||
|                         caps[kvp.Key] = baseUrl + kvp.Value.Path; | ||||
|                     foreach (KeyValuePair<string, IRequestHandler> kvp in m_capsHandlers) | ||||
|                         caps[kvp.Key] = baseUrl + kvp.Value.Path; | ||||
|                 } | ||||
|                 return caps; | ||||
|             } | ||||
| 
 | ||||
|             lock (m_capsHandlers) | ||||
|             { | ||||
|                 for(int i = 0; i < requestedCaps.Count; ++i) | ||||
|                 foreach (string capsName in m_capsHandlers.Keys) | ||||
|                 { | ||||
|                     string capsName = requestedCaps[i]; | ||||
|                     if (excludeSeed && "SEED" == capsName) | ||||
|                         continue; | ||||
| 
 | ||||
|                     if (m_capsSimpleHandlers.TryGetValue(capsName, out ISimpleStreamHandler shdr)) | ||||
|                     { | ||||
|                         caps[capsName] = baseUrl + shdr.Path; | ||||
|                     if (requestedCaps != null && !requestedCaps.Contains(capsName)) | ||||
|                         continue; | ||||
|                     } | ||||
|                     if (m_capsHandlers.TryGetValue(capsName, out IRequestHandler chdr)) | ||||
|                     { | ||||
|                         caps[capsName] = baseUrl + chdr.Path; | ||||
|                     } | ||||
| 
 | ||||
|                     caps[capsName] = baseUrl + m_capsHandlers[capsName].Path; | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|  |  | |||
|  | @ -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); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | @ -1,449 +0,0 @@ | |||
| /* | ||||
|  * Copyright (c) Contributors, http://opensimulator.org/ | ||||
|  * See CONTRIBUTORS.TXT for a full list of copyright holders. | ||||
|  * | ||||
|  * Redistribution and use in source and binary forms, with or without | ||||
|  * modification, are permitted provided that the following conditions are met: | ||||
|  *     * Redistributions of source code must retain the above copyright | ||||
|  *       notice, this list of conditions and the following disclaimer. | ||||
|  *     * Redistributions in binary form must reproduce the above copyright | ||||
|  *       notice, this list of conditions and the following disclaimer in the | ||||
|  *       documentation and/or other materials provided with the distribution. | ||||
|  *     * Neither the name of the OpenSimulator Project nor the | ||||
|  *       names of its contributors may be used to endorse or promote products | ||||
|  *       derived from this software without specific prior written permission. | ||||
|  * | ||||
|  * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY | ||||
|  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | ||||
|  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||||
|  * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY | ||||
|  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | ||||
|  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||||
|  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | ||||
|  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||||
|  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||||
|  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||
|  */ | ||||
| 
 | ||||
| using System; | ||||
| using System.Collections; | ||||
| using System.Collections.Generic; | ||||
| using System.IO; | ||||
| using System.Linq; | ||||
| using System.Reflection; | ||||
| using System.Text; | ||||
| using log4net; | ||||
| using Nini.Config; | ||||
| using OpenMetaverse; | ||||
| using OpenMetaverse.StructuredData; | ||||
| using OpenSim.Framework; | ||||
| using OpenSim.Framework.Capabilities; | ||||
| using OpenSim.Framework.Servers.HttpServer; | ||||
| using OpenSim.Services.Interfaces; | ||||
| using OSDMap = OpenMetaverse.StructuredData.OSDMap; | ||||
| using OSDArray = OpenMetaverse.StructuredData.OSDArray; | ||||
| 
 | ||||
| namespace OpenSim.Capabilities.Handlers | ||||
| { | ||||
|     public class FetchInvDescHandler | ||||
|     { | ||||
|         private static readonly ILog m_log = | ||||
|             LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | ||||
| 
 | ||||
|         private static byte[] EmptyResponse = Util.UTF8NBGetbytes("<llsd><map><key>folders</key><array /></map></llsd>"); | ||||
|         private IInventoryService m_InventoryService; | ||||
|         private ILibraryService m_LibraryService; | ||||
|         private IScene m_Scene; | ||||
| 
 | ||||
|         public FetchInvDescHandler(IInventoryService invService, ILibraryService libService, IScene s) | ||||
|         { | ||||
|             m_InventoryService = invService; | ||||
|             m_LibraryService = libService; | ||||
|             m_Scene = s; | ||||
|         } | ||||
| 
 | ||||
|         public void FetchInventoryDescendentsRequest(IOSHttpRequest httpRequest, IOSHttpResponse httpResponse, ExpiringKey<UUID> BadRequests) | ||||
|         { | ||||
|             //m_log.DebugFormat("[XXX]: FetchInventoryDescendentsRequest in {0}, {1}", (m_Scene == null) ? "none" : m_Scene.Name, request); | ||||
| 
 | ||||
|             List<LLSDFetchInventoryDescendents> folders = null; | ||||
|             List<UUID> bad_folders = new List<UUID>(); | ||||
|             try | ||||
|             { | ||||
|                 OSDArray foldersrequested = null; | ||||
|                 OSD tmp = OSDParser.DeserializeLLSDXml(httpRequest.InputStream); | ||||
|                 OSDMap map = (OSDMap)tmp; | ||||
|                 if(map.TryGetValue("folders", out tmp) && tmp is OSDArray) | ||||
|                     foldersrequested = tmp as OSDArray; | ||||
| 
 | ||||
|                 if (foldersrequested == null || foldersrequested.Count == 0) | ||||
|                 { | ||||
|                     httpResponse.RawBuffer = EmptyResponse; | ||||
|                     return; | ||||
|                 } | ||||
| 
 | ||||
|                 folders = new List<LLSDFetchInventoryDescendents>(foldersrequested.Count); | ||||
|                 for (int i = 0; i < foldersrequested.Count; i++) | ||||
|                 { | ||||
|                     OSDMap mfolder = foldersrequested[i] as OSDMap; | ||||
|                     UUID id = mfolder["folder_id"].AsUUID(); | ||||
|                     if(BadRequests.ContainsKey(id)) | ||||
|                     { | ||||
|                         bad_folders.Add(id); | ||||
|                     } | ||||
|                     else | ||||
|                     { | ||||
|                         LLSDFetchInventoryDescendents llsdRequest = new LLSDFetchInventoryDescendents(); | ||||
|                         try | ||||
|                         { | ||||
|                             llsdRequest.folder_id = id; | ||||
|                             llsdRequest.owner_id = mfolder["owner_id"].AsUUID(); | ||||
|                             llsdRequest.sort_order = mfolder["sort_order"].AsInteger(); | ||||
|                             llsdRequest.fetch_folders = mfolder["fetch_folders"].AsBoolean(); | ||||
|                             llsdRequest.fetch_items = mfolder["fetch_items"].AsBoolean(); | ||||
|                         } | ||||
|                         catch (Exception e) | ||||
|                         { | ||||
|                             m_log.Debug("[WEB FETCH INV DESC HANDLER]: caught exception doing OSD deserialize" + e.Message); | ||||
|                             continue; | ||||
|                         } | ||||
|                         folders.Add(llsdRequest); | ||||
|                     } | ||||
|                 } | ||||
|                 foldersrequested = null; | ||||
|                 tmp = null; | ||||
|             } | ||||
|             catch (Exception e) | ||||
|             { | ||||
|                 m_log.ErrorFormat("[FETCH INV DESC]: fail parsing request: {0}", e.Message); | ||||
|                 httpResponse.RawBuffer = EmptyResponse; | ||||
|                 return; | ||||
|             } | ||||
| 
 | ||||
|             if (folders == null || folders.Count == 0) | ||||
|             { | ||||
|                 if(bad_folders.Count == 0) | ||||
|                 { | ||||
|                     httpResponse.RawBuffer = EmptyResponse; | ||||
|                     return; | ||||
|                 } | ||||
|                 StringBuilder sb = osStringBuilderCache.Acquire(); | ||||
|                 sb.Append("<llsd><map><key>folders</key><array /></map><map><key>bad_folders</key><array>"); | ||||
|                 foreach (UUID bad in bad_folders) | ||||
|                 { | ||||
|                     sb.Append("<map><key>folder_id</key><uuid>"); | ||||
|                     sb.Append(bad.ToString()); | ||||
|                     sb.Append("</uuid><key>error</key><string>Unknown</string></map>"); | ||||
|                 } | ||||
|                 sb.Append("</array></map></llsd>"); | ||||
|                 httpResponse.RawBuffer = Util.UTF8NBGetbytes(osStringBuilderCache.GetStringAndRelease(sb)); | ||||
|             } | ||||
| 
 | ||||
|             int total_folders = 0; | ||||
|             int total_items = 0; | ||||
| 
 | ||||
|             List<InventoryCollection> invcollSet = Fetch(folders, bad_folders, ref total_folders, ref total_items); | ||||
|             //m_log.DebugFormat("[XXX]: Got {0} folders from a request of {1}", invcollSet.Count, folders.Count); | ||||
| 
 | ||||
|             int invcollSetCount = 0; | ||||
|             if (invcollSet != null) | ||||
|                 invcollSetCount = invcollSet.Count; | ||||
| 
 | ||||
|             int mem = 8192 + ((256 * invcollSetCount + | ||||
|                                 384 * total_folders + | ||||
|                                 1024 * total_items + | ||||
|                                 128 * bad_folders.Count) & 0x7ffff000); | ||||
| 
 | ||||
|             StringBuilder lastresponse = new StringBuilder(mem); | ||||
|             lastresponse.Append("<llsd>"); | ||||
| 
 | ||||
|             if (invcollSetCount > 0) | ||||
|             { | ||||
|                 lastresponse.Append("<map><key>folders</key><array>"); | ||||
|                 int i = 0; | ||||
|                 InventoryCollection thiscoll; | ||||
|                 for (i = 0; i < invcollSetCount; i++) | ||||
|                 { | ||||
|                     thiscoll = invcollSet[i]; | ||||
|                     invcollSet[i] = null; | ||||
| 
 | ||||
|                     LLSDxmlEncode.AddMap(lastresponse); | ||||
|                     LLSDxmlEncode.AddElem("agent_id", thiscoll.OwnerID, lastresponse); | ||||
|                     LLSDxmlEncode.AddElem("descendents", thiscoll.Descendents, lastresponse); | ||||
|                     LLSDxmlEncode.AddElem("folder_id", thiscoll.FolderID, lastresponse); | ||||
| 
 | ||||
|                     if (thiscoll.Folders == null || thiscoll.Folders.Count == 0) | ||||
|                         LLSDxmlEncode.AddEmptyArray("categories", lastresponse); | ||||
|                     else | ||||
|                     { | ||||
|                         LLSDxmlEncode.AddArray("categories", lastresponse); | ||||
|                         foreach (InventoryFolderBase invFolder in thiscoll.Folders) | ||||
|                         { | ||||
|                             LLSDxmlEncode.AddMap(lastresponse); | ||||
| 
 | ||||
|                             LLSDxmlEncode.AddElem("folder_id", invFolder.ID, lastresponse); | ||||
|                             LLSDxmlEncode.AddElem("parent_id", invFolder.ParentID, lastresponse); | ||||
|                             LLSDxmlEncode.AddElem("name", invFolder.Name, lastresponse); | ||||
|                             LLSDxmlEncode.AddElem("type", invFolder.Type, lastresponse); | ||||
|                             LLSDxmlEncode.AddElem("preferred_type", (int)-1, lastresponse); | ||||
|                             LLSDxmlEncode.AddElem("version", invFolder.Version, lastresponse); | ||||
| 
 | ||||
|                             LLSDxmlEncode.AddEndMap(lastresponse); | ||||
|                         } | ||||
|                         LLSDxmlEncode.AddEndArray(lastresponse); | ||||
|                     } | ||||
| 
 | ||||
|                     if (thiscoll.Items == null || thiscoll.Items.Count == 0) | ||||
|                         LLSDxmlEncode.AddEmptyArray("items", lastresponse); | ||||
|                     else | ||||
|                     { | ||||
|                         LLSDxmlEncode.AddArray("items", lastresponse); | ||||
|                         foreach (InventoryItemBase invItem in thiscoll.Items) | ||||
|                         { | ||||
|                             invItem.ToLLSDxml(lastresponse); | ||||
|                         } | ||||
| 
 | ||||
|                         LLSDxmlEncode.AddEndArray(lastresponse); | ||||
|                     } | ||||
| 
 | ||||
|                     LLSDxmlEncode.AddElem("owner_id", thiscoll.OwnerID, lastresponse); | ||||
|                     LLSDxmlEncode.AddElem("version", thiscoll.Version, lastresponse); | ||||
| 
 | ||||
|                     LLSDxmlEncode.AddEndMap(lastresponse); | ||||
|                     invcollSet[i] = null; | ||||
|                 } | ||||
|                 lastresponse.Append("</array></map>"); | ||||
|                 thiscoll = null; | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 lastresponse.Append("<map><key>folders</key><array /></map>"); | ||||
|             } | ||||
| 
 | ||||
|             //m_log.DebugFormat("[WEB FETCH INV DESC HANDLER]: Bad folders {0}", string.Join(", ", bad_folders)); | ||||
|             if (bad_folders.Count > 0) | ||||
|             { | ||||
|                 lastresponse.Append("<map><key>bad_folders</key><array>"); | ||||
|                 foreach (UUID bad in bad_folders) | ||||
|                 { | ||||
|                     BadRequests.Add(bad); | ||||
|                     lastresponse.Append("<map><key>folder_id</key><uuid>"); | ||||
|                     lastresponse.Append(bad.ToString()); | ||||
|                     lastresponse.Append("</uuid><key>error</key><string>Unknown</string></map>"); | ||||
|                 } | ||||
|                 lastresponse.Append("</array></map>"); | ||||
|             } | ||||
|             lastresponse.Append("</llsd>"); | ||||
| 
 | ||||
|             httpResponse.RawBuffer = Util.UTF8NBGetbytes(lastresponse.ToString()); | ||||
|         } | ||||
| 
 | ||||
|         private void AddLibraryFolders(List<LLSDFetchInventoryDescendents> libFolders, List<InventoryCollection> result, ref int total_folders, ref int total_items) | ||||
|         { | ||||
|             InventoryFolderImpl fold; | ||||
|             if (m_LibraryService == null || m_LibraryService.LibraryRootFolder == null) | ||||
|                 return; | ||||
|              | ||||
|             foreach (LLSDFetchInventoryDescendents f in libFolders) | ||||
|             { | ||||
|                 if ((fold = m_LibraryService.LibraryRootFolder.FindFolder(f.folder_id)) != null) | ||||
|                 { | ||||
|                     InventoryCollection Collection = new InventoryCollection(); | ||||
| //                        ret.Collection.Folders = new List<InventoryFolderBase>(); | ||||
|                     Collection.Folders = fold.RequestListOfFolders(); | ||||
|                     Collection.Items = fold.RequestListOfItems(); | ||||
|                     Collection.OwnerID = m_LibraryService.LibraryRootFolder.Owner; | ||||
|                     Collection.FolderID = f.folder_id; | ||||
|                     Collection.Version = fold.Version; | ||||
| 
 | ||||
|                     Collection.Descendents = Collection.Items.Count + Collection.Folders.Count; | ||||
|                     total_folders += Collection.Folders.Count; | ||||
|                     total_items += Collection.Items.Count; | ||||
|                     result.Add(Collection); | ||||
| 
 | ||||
|                     //m_log.DebugFormat("[XXX]: Added libfolder {0} ({1}) {2}", ret.Collection.FolderID, ret.Collection.OwnerID); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         private List<InventoryCollection> Fetch(List<LLSDFetchInventoryDescendents> fetchFolders, List<UUID> bad_folders, ref int total_folders, ref int total_items) | ||||
|         { | ||||
|             //m_log.DebugFormat( | ||||
|             //    "[WEB FETCH INV DESC HANDLER]: Fetching {0} folders for owner {1}", fetchFolders.Count, fetchFolders[0].owner_id); | ||||
| 
 | ||||
|             // FIXME MAYBE: We're not handling sortOrder! | ||||
| 
 | ||||
|             List<InventoryCollection> result = new List<InventoryCollection>(32); | ||||
|             List<LLSDFetchInventoryDescendents> libFolders = new List<LLSDFetchInventoryDescendents>(32); | ||||
|             List<LLSDFetchInventoryDescendents> otherFolders = new List<LLSDFetchInventoryDescendents>(32); | ||||
|             HashSet<UUID> libIDs = new HashSet<UUID>(); | ||||
|             HashSet<UUID> otherIDs = new HashSet<UUID>(); | ||||
| 
 | ||||
|             bool dolib = (m_LibraryService != null && m_LibraryService.LibraryRootFolder != null); | ||||
|             UUID libOwner = UUID.Zero; | ||||
|             if(dolib) | ||||
|                 libOwner = m_LibraryService.LibraryRootFolder.Owner; | ||||
| 
 | ||||
|             // Filter folder Zero right here. Some viewers (Firestorm) send request for folder Zero, which doesn't make sense | ||||
|             // and can kill the sim (all root folders have parent_id Zero) | ||||
|             // send something. | ||||
|             bool doneZeroID = false; | ||||
|             foreach(LLSDFetchInventoryDescendents f in fetchFolders) | ||||
|             { | ||||
|                 if (f.folder_id == UUID.Zero) | ||||
|                 { | ||||
|                     if(doneZeroID) | ||||
|                         continue; | ||||
|                     doneZeroID = true; | ||||
|                     InventoryCollection Collection = new InventoryCollection(); | ||||
|                     Collection.OwnerID = f.owner_id; | ||||
|                     Collection.Version = 0; | ||||
|                     Collection.FolderID = f.folder_id; | ||||
|                     Collection.Descendents = 0; | ||||
|                     result.Add(Collection); | ||||
|                     continue; | ||||
|                 } | ||||
|                 if(dolib && f.owner_id == libOwner) | ||||
|                 { | ||||
|                     if(libIDs.Contains(f.folder_id)) | ||||
|                         continue; | ||||
|                     libIDs.Add(f.folder_id); | ||||
|                     libFolders.Add(f); | ||||
|                     continue; | ||||
|                 } | ||||
|                 if(otherIDs.Contains(f.folder_id)) | ||||
|                     continue; | ||||
| 
 | ||||
|                 otherIDs.Add(f.folder_id); | ||||
|                 otherFolders.Add(f); | ||||
|             } | ||||
| 
 | ||||
|             fetchFolders.Clear(); | ||||
| 
 | ||||
|             if(otherFolders.Count > 0) | ||||
|             {  | ||||
|                 int i = 0; | ||||
| 
 | ||||
|                 //m_log.DebugFormat("[XXX]: {0}", string.Join(",", fids)); | ||||
| 
 | ||||
|                 InventoryCollection[] fetchedContents = m_InventoryService.GetMultipleFoldersContent(otherFolders[0].owner_id, otherIDs.ToArray()); | ||||
| 
 | ||||
|                 if (fetchedContents == null) | ||||
|                      return null; | ||||
|   | ||||
|                 if (fetchedContents.Length == 0) | ||||
|                 { | ||||
|                     foreach (LLSDFetchInventoryDescendents freq in otherFolders) | ||||
|                         BadFolder(freq, null, bad_folders); | ||||
|                 } | ||||
|                 else | ||||
|                 { | ||||
|                     i = 0; | ||||
|                     // Do some post-processing. May need to fetch more from inv server for links | ||||
|                     foreach (InventoryCollection contents in fetchedContents) | ||||
|                     { | ||||
|                         // Find the original request | ||||
|                         LLSDFetchInventoryDescendents freq = otherFolders[i]; | ||||
|                         otherFolders[i]=null; | ||||
|                         i++; | ||||
| 
 | ||||
|                         if (BadFolder(freq, contents, bad_folders)) | ||||
|                             continue; | ||||
| 
 | ||||
|                         if(!freq.fetch_folders) | ||||
|                             contents.Folders.Clear(); | ||||
|                         if(!freq.fetch_items) | ||||
|                             contents.Items.Clear(); | ||||
| 
 | ||||
|                         contents.Descendents = contents.Items.Count + contents.Folders.Count; | ||||
|   | ||||
|                         // Next: link management | ||||
|                         ProcessLinks(freq, contents); | ||||
| 
 | ||||
|                         total_folders += contents.Folders.Count; | ||||
|                         total_items += contents.Items.Count; | ||||
|                         result.Add(contents); | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|             if(dolib && libFolders.Count > 0) | ||||
|             { | ||||
|                 AddLibraryFolders(libFolders, result, ref total_folders, ref total_items);            | ||||
|             } | ||||
| 
 | ||||
|             return result; | ||||
|         } | ||||
| 
 | ||||
|         private bool BadFolder(LLSDFetchInventoryDescendents freq, InventoryCollection contents, List<UUID> bad_folders) | ||||
|         { | ||||
|             if (contents == null) | ||||
|             { | ||||
|                 bad_folders.Add(freq.folder_id); | ||||
|                 return true; | ||||
|             } | ||||
| 
 | ||||
|             // The inventory server isn't sending FolderID in the collection... | ||||
|             // Must fetch it individually | ||||
|             if (contents.FolderID == UUID.Zero) | ||||
|             { | ||||
|                 InventoryFolderBase containingFolder = m_InventoryService.GetFolder(freq.owner_id, freq.folder_id); | ||||
|                 if (containingFolder == null) | ||||
|                 { | ||||
|                     m_log.WarnFormat("[WEB FETCH INV DESC HANDLER]: Unable to fetch folder {0}", freq.folder_id); | ||||
|                     bad_folders.Add(freq.folder_id); | ||||
|                     return true; | ||||
|                 } | ||||
|                 contents.FolderID = containingFolder.ID; | ||||
|                 contents.OwnerID = containingFolder.Owner; | ||||
|                 contents.Version = containingFolder.Version; | ||||
|             } | ||||
| 
 | ||||
|             return false; | ||||
|         } | ||||
| 
 | ||||
|         private void ProcessLinks(LLSDFetchInventoryDescendents freq, InventoryCollection contents) | ||||
|         { | ||||
|             if (contents.Items == null || contents.Items.Count == 0) | ||||
|                 return; | ||||
| 
 | ||||
|             // viewers are lasy and want a copy of the linked item sent before the link to it | ||||
| 
 | ||||
|             // look for item links | ||||
|             List<UUID> itemIDs = new List<UUID>(); | ||||
|             foreach (InventoryItemBase item in contents.Items) | ||||
|             { | ||||
|                 //m_log.DebugFormat("[XXX]:   {0} {1}", item.Name, item.AssetType); | ||||
|                 if (item.AssetType == (int)AssetType.Link) | ||||
|                     itemIDs.Add(item.AssetID); | ||||
|             } | ||||
| 
 | ||||
|             // get the linked if any | ||||
|             if (itemIDs.Count > 0) | ||||
|             { | ||||
|                 InventoryItemBase[] linked = m_InventoryService.GetMultipleItems(freq.owner_id, itemIDs.ToArray()); | ||||
|                      | ||||
|                 if (linked != null) | ||||
|                 { | ||||
|                     List<InventoryItemBase> linkedItems = new List<InventoryItemBase>(linked.Length); | ||||
|                     // check for broken | ||||
|                     foreach (InventoryItemBase linkedItem in linked) | ||||
|                     { | ||||
|                         // Take care of genuinely broken links where the target doesn't exist | ||||
|                         // HACK: Also, don't follow up links that just point to other links.  In theory this is legitimate, | ||||
|                         // but no viewer has been observed to set these up and this is the lazy way of avoiding cycles | ||||
|                         // rather than having to keep track of every folder requested in the recursion. | ||||
|                         if (linkedItem != null && linkedItem.AssetType != (int)AssetType.Link) | ||||
|                         { | ||||
|                             linkedItems.Add(linkedItem); | ||||
|                             //m_log.DebugFormat("[WEB FETCH INV DESC HANDLER]: Added {0} {1} {2}", linkedItem.Name, linkedItem.AssetType, linkedItem.Folder); | ||||
|                         } | ||||
|                     } | ||||
|                     // insert them | ||||
|                     if(linkedItems.Count > 0) | ||||
|                         contents.Items.InsertRange(0, linkedItems); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | @ -1,166 +0,0 @@ | |||
| /* | ||||
|  * Copyright (c) Contributors, http://opensimulator.org/ | ||||
|  * See CONTRIBUTORS.TXT for a full list of copyright holders. | ||||
|  * | ||||
|  * Redistribution and use in source and binary forms, with or without | ||||
|  * modification, are permitted provided that the following conditions are met: | ||||
|  *     * Redistributions of source code must retain the above copyright | ||||
|  *       notice, this list of conditions and the following disclaimer. | ||||
|  *     * Redistributions in binary form must reproduce the above copyright | ||||
|  *       notice, this list of conditions and the following disclaimer in the | ||||
|  *       documentation and/or other materials provided with the distribution. | ||||
|  *     * Neither the name of the OpenSimulator Project nor the | ||||
|  *       names of its contributors may be used to endorse or promote products | ||||
|  *       derived from this software without specific prior written permission. | ||||
|  * | ||||
|  * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY | ||||
|  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | ||||
|  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||||
|  * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY | ||||
|  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | ||||
|  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||||
|  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | ||||
|  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||||
|  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||||
|  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||
|  */ | ||||
| 
 | ||||
| using System.Net; | ||||
| using System.Reflection; | ||||
| using System.Text; | ||||
| using OpenMetaverse; | ||||
| using OpenMetaverse.StructuredData; | ||||
| using OpenSim.Framework; | ||||
| using OpenSim.Framework.Servers.HttpServer; | ||||
| using OpenSim.Services.Interfaces; | ||||
| using OSDArray = OpenMetaverse.StructuredData.OSDArray; | ||||
| using OSDMap = OpenMetaverse.StructuredData.OSDMap; | ||||
| 
 | ||||
| using log4net; | ||||
| 
 | ||||
| namespace OpenSim.Capabilities.Handlers | ||||
| { | ||||
|     public class FetchInventory2Handler | ||||
|     { | ||||
|         private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | ||||
| 
 | ||||
|         private IInventoryService m_inventoryService; | ||||
|         private UUID m_agentID; | ||||
| 
 | ||||
|         public FetchInventory2Handler(IInventoryService invService, UUID agentId) | ||||
|         { | ||||
|             m_inventoryService = invService; | ||||
|             m_agentID = agentId; | ||||
|         } | ||||
| 
 | ||||
|         public string FetchInventoryRequest(string request, string path, string param, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) | ||||
|         { | ||||
|             //m_log.DebugFormat("[FETCH INVENTORY HANDLER]: Received FetchInventory capability request {0}", request); | ||||
| 
 | ||||
|             OSDMap requestmap = (OSDMap)OSDParser.DeserializeLLSDXml(Utils.StringToBytes(request)); | ||||
|             OSDArray itemsRequested = (OSDArray)requestmap["items"]; | ||||
| 
 | ||||
|             UUID[] itemIDs = new UUID[itemsRequested.Count]; | ||||
|             int i = 0; | ||||
| 
 | ||||
|             foreach (OSDMap osdItemId in itemsRequested) | ||||
|             { | ||||
|                 itemIDs[i++] = osdItemId["item_id"].AsUUID(); | ||||
|             } | ||||
| 
 | ||||
|             InventoryItemBase[] items = null; | ||||
| 
 | ||||
|             if (m_agentID != UUID.Zero) | ||||
|             { | ||||
|                 items = m_inventoryService.GetMultipleItems(m_agentID, itemIDs); | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 items = new InventoryItemBase[itemsRequested.Count]; | ||||
|                 foreach (UUID id in itemIDs) | ||||
|                     items[i++] = m_inventoryService.GetItem(UUID.Zero, id); | ||||
|             } | ||||
| 
 | ||||
|             StringBuilder lsl = LLSDxmlEncode.Start(4096); | ||||
|             LLSDxmlEncode.AddMap(lsl); | ||||
| 
 | ||||
|             if(m_agentID == UUID.Zero && items.Length > 0) | ||||
|                 LLSDxmlEncode.AddElem("agent_id", items[0].Owner, lsl); | ||||
|             else | ||||
|                 LLSDxmlEncode.AddElem("agent_id", m_agentID, lsl); | ||||
| 
 | ||||
|             if(items == null || items.Length == 0) | ||||
|             { | ||||
|                 LLSDxmlEncode.AddEmptyArray("items", lsl); | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 LLSDxmlEncode.AddArray("items", lsl); | ||||
|                 foreach (InventoryItemBase item in items) | ||||
|                 { | ||||
|                     if (item != null) | ||||
|                         item.ToLLSDxml(lsl, 0xff); | ||||
|                 } | ||||
|                 LLSDxmlEncode.AddEndArray(lsl); | ||||
|             }             | ||||
| 
 | ||||
|             LLSDxmlEncode.AddEndMap(lsl); | ||||
|             return LLSDxmlEncode.End(lsl); | ||||
|         } | ||||
| 
 | ||||
|         public void FetchInventorySimpleRequest(IOSHttpRequest httpRequest, IOSHttpResponse httpResponse, OSDMap requestmap, ExpiringKey<UUID> BadRequests) | ||||
|         { | ||||
|             //m_log.DebugFormat("[FETCH INVENTORY HANDLER]: Received FetchInventory capability request {0}", request); | ||||
| 
 | ||||
|             if(BadRequests == null) | ||||
|             { | ||||
|                 httpResponse.StatusCode = (int)HttpStatusCode.NotFound; | ||||
|                 return; | ||||
|             } | ||||
| 
 | ||||
|             OSDArray itemsRequested = (OSDArray)requestmap["items"]; | ||||
| 
 | ||||
|             UUID[] itemIDs = new UUID[itemsRequested.Count]; | ||||
|             int i = 0; | ||||
|             foreach (OSDMap osdItemId in itemsRequested) | ||||
|             { | ||||
|                 UUID id = osdItemId["item_id"].AsUUID(); | ||||
|                 if(!BadRequests.ContainsKey(id)) | ||||
|                     itemIDs[i++] = id; | ||||
|             } | ||||
| 
 | ||||
|             InventoryItemBase[] items = null; | ||||
|             try | ||||
|             { | ||||
|                 // badrequests still not filled | ||||
|                 items = m_inventoryService.GetMultipleItems(m_agentID, itemIDs); | ||||
|             } | ||||
|             catch{ } | ||||
| 
 | ||||
|             StringBuilder lsl = LLSDxmlEncode.Start(4096); | ||||
|             LLSDxmlEncode.AddMap(lsl); | ||||
| 
 | ||||
|             LLSDxmlEncode.AddElem("agent_id", m_agentID, lsl); | ||||
| 
 | ||||
|             if (items == null || items.Length == 0) | ||||
|             { | ||||
|                 LLSDxmlEncode.AddEmptyArray("items", lsl); | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 LLSDxmlEncode.AddArray("items", lsl); | ||||
|                 foreach (InventoryItemBase item in items) | ||||
|                 { | ||||
|                     if (item != null) | ||||
|                         item.ToLLSDxml(lsl, 0xff); | ||||
|                 } | ||||
|                 LLSDxmlEncode.AddEndArray(lsl); | ||||
|             } | ||||
| 
 | ||||
|             LLSDxmlEncode.AddEndMap(lsl); | ||||
|             httpResponse.RawBuffer = Util.UTF8.GetBytes(LLSDxmlEncode.End(lsl)); | ||||
|             httpResponse.StatusCode = (int)HttpStatusCode.OK; | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
|  | @ -1,170 +0,0 @@ | |||
| /* | ||||
|  * Copyright (c) Contributors, http://opensimulator.org/ | ||||
|  * See CONTRIBUTORS.TXT for a full list of copyright holders. | ||||
|  * | ||||
|  * Redistribution and use in source and binary forms, with or without | ||||
|  * modification, are permitted provided that the following conditions are met: | ||||
|  *     * Redistributions of source code must retain the above copyright | ||||
|  *       notice, this list of conditions and the following disclaimer. | ||||
|  *     * Redistributions in binary form must reproduce the above copyright | ||||
|  *       notice, this list of conditions and the following disclaimer in the | ||||
|  *       documentation and/or other materials provided with the distribution. | ||||
|  *     * Neither the name of the OpenSimulator Project nor the | ||||
|  *       names of its contributors may be used to endorse or promote products | ||||
|  *       derived from this software without specific prior written permission. | ||||
|  * | ||||
|  * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY | ||||
|  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | ||||
|  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||||
|  * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY | ||||
|  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | ||||
|  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||||
|  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | ||||
|  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||||
|  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||||
|  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||
|  */ | ||||
| 
 | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using System.Linq; | ||||
| using System.Net; | ||||
| using System.Text.RegularExpressions; | ||||
| using log4net; | ||||
| using log4net.Config; | ||||
| using NUnit.Framework; | ||||
| using OpenMetaverse; | ||||
| using OpenSim.Capabilities.Handlers; | ||||
| using OpenSim.Framework; | ||||
| using OpenSim.Framework.Servers.HttpServer; | ||||
| using OpenSim.Region.Framework.Scenes; | ||||
| using OpenSim.Services.Interfaces; | ||||
| using OpenSim.Tests.Common; | ||||
| 
 | ||||
| namespace OpenSim.Capabilities.Handlers.FetchInventory.Tests | ||||
| { | ||||
|     [TestFixture] | ||||
|     public class FetchInventory2HandlerTests : OpenSimTestCase | ||||
|     { | ||||
|         private UUID m_userID = UUID.Random(); | ||||
|         private Scene m_scene; | ||||
|         private UUID m_rootFolderID; | ||||
|         private UUID m_notecardsFolder; | ||||
|         private UUID m_objectsFolder; | ||||
| 
 | ||||
|         private void Init() | ||||
|         { | ||||
|             // Create an inventory that looks like this: | ||||
|             // | ||||
|             // /My Inventory | ||||
|             //   <other system folders> | ||||
|             //   /Objects | ||||
|             //      Object 1 | ||||
|             //      Object 2 | ||||
|             //      Object 3 | ||||
|             //   /Notecards | ||||
|             //      Notecard 1 | ||||
|             //      Notecard 2 | ||||
|             //      Notecard 3 | ||||
|             //      Notecard 4 | ||||
|             //      Notecard 5 | ||||
| 
 | ||||
|             m_scene = new SceneHelpers().SetupScene(); | ||||
| 
 | ||||
|             m_scene.InventoryService.CreateUserInventory(m_userID); | ||||
| 
 | ||||
|             m_rootFolderID = m_scene.InventoryService.GetRootFolder(m_userID).ID; | ||||
| 
 | ||||
|             InventoryFolderBase of = m_scene.InventoryService.GetFolderForType(m_userID, FolderType.Object); | ||||
|             m_objectsFolder = of.ID; | ||||
| 
 | ||||
|             // Add 3 objects | ||||
|             InventoryItemBase item; | ||||
|             for (int i = 1; i <= 3; i++) | ||||
|             { | ||||
|                 item = new InventoryItemBase(new UUID("b0000000-0000-0000-0000-0000000000b" + i), m_userID); | ||||
|                 item.AssetID = UUID.Random(); | ||||
|                 item.AssetType = (int)AssetType.Object; | ||||
|                 item.Folder = m_objectsFolder; | ||||
|                 item.Name = "Object " + i; | ||||
|                 m_scene.InventoryService.AddItem(item); | ||||
|             } | ||||
| 
 | ||||
|             InventoryFolderBase ncf = m_scene.InventoryService.GetFolderForType(m_userID, FolderType.Notecard); | ||||
|             m_notecardsFolder = ncf.ID; | ||||
| 
 | ||||
|             // Add 5 notecards | ||||
|             for (int i = 1; i <= 5; i++) | ||||
|             { | ||||
|                 item = new InventoryItemBase(new UUID("10000000-0000-0000-0000-00000000000" + i), m_userID); | ||||
|                 item.AssetID = UUID.Random(); | ||||
|                 item.AssetType = (int)AssetType.Notecard; | ||||
|                 item.Folder = m_notecardsFolder; | ||||
|                 item.Name = "Notecard " + i; | ||||
|                 m_scene.InventoryService.AddItem(item); | ||||
|             } | ||||
| 
 | ||||
|         } | ||||
| 
 | ||||
|         [Test] | ||||
|         public void Test_001_RequestOne() | ||||
|         { | ||||
|             TestHelpers.InMethod(); | ||||
| 
 | ||||
|             Init(); | ||||
| 
 | ||||
|             FetchInventory2Handler handler = new FetchInventory2Handler(m_scene.InventoryService, m_userID); | ||||
|             TestOSHttpRequest req = new TestOSHttpRequest(); | ||||
|             TestOSHttpResponse resp = new TestOSHttpResponse(); | ||||
| 
 | ||||
|             string request = "<llsd><map><key>items</key><array><map><key>item_id</key><uuid>"; | ||||
|             request += "10000000-0000-0000-0000-000000000001"; // Notecard 1 | ||||
|             request += "</uuid></map></array></map></llsd>"; | ||||
| 
 | ||||
|             string llsdresponse = handler.FetchInventoryRequest(request, "/FETCH", string.Empty, req, resp); | ||||
| 
 | ||||
|             Assert.That(llsdresponse != null, Is.True, "Incorrect null response"); | ||||
|             Assert.That(llsdresponse != string.Empty, Is.True, "Incorrect empty response"); | ||||
|             Assert.That(llsdresponse.Contains(m_userID.ToString()), Is.True, "Response should contain userID"); | ||||
| 
 | ||||
|             Assert.That(llsdresponse.Contains("10000000-0000-0000-0000-000000000001"), Is.True, "Response does not contain item uuid"); | ||||
|             Assert.That(llsdresponse.Contains("Notecard 1"), Is.True, "Response does not contain item Name"); | ||||
|             Console.WriteLine(llsdresponse); | ||||
|         } | ||||
| 
 | ||||
|         [Test] | ||||
|         public void Test_002_RequestMany() | ||||
|         { | ||||
|             TestHelpers.InMethod(); | ||||
| 
 | ||||
|             Init(); | ||||
| 
 | ||||
|             FetchInventory2Handler handler = new FetchInventory2Handler(m_scene.InventoryService, m_userID); | ||||
|             TestOSHttpRequest req = new TestOSHttpRequest(); | ||||
|             TestOSHttpResponse resp = new TestOSHttpResponse(); | ||||
| 
 | ||||
|             string request = "<llsd><map><key>items</key><array>"; | ||||
|             request += "<map><key>item_id</key><uuid>10000000-0000-0000-0000-000000000001</uuid></map>"; // Notecard 1 | ||||
|             request += "<map><key>item_id</key><uuid>10000000-0000-0000-0000-000000000002</uuid></map>"; // Notecard 2 | ||||
|             request += "<map><key>item_id</key><uuid>10000000-0000-0000-0000-000000000003</uuid></map>"; // Notecard 3 | ||||
|             request += "<map><key>item_id</key><uuid>10000000-0000-0000-0000-000000000004</uuid></map>"; // Notecard 4 | ||||
|             request += "<map><key>item_id</key><uuid>10000000-0000-0000-0000-000000000005</uuid></map>"; // Notecard 5 | ||||
|             request += "</array></map></llsd>"; | ||||
| 
 | ||||
|             string llsdresponse = handler.FetchInventoryRequest(request, "/FETCH", string.Empty, req, resp); | ||||
| 
 | ||||
|             Assert.That(llsdresponse != null, Is.True, "Incorrect null response"); | ||||
|             Assert.That(llsdresponse != string.Empty, Is.True, "Incorrect empty response"); | ||||
|             Assert.That(llsdresponse.Contains(m_userID.ToString()), Is.True, "Response should contain userID"); | ||||
| 
 | ||||
|             Console.WriteLine(llsdresponse); | ||||
|             Assert.That(llsdresponse.Contains("10000000-0000-0000-0000-000000000001"), Is.True, "Response does not contain notecard 1"); | ||||
|             Assert.That(llsdresponse.Contains("10000000-0000-0000-0000-000000000002"), Is.True, "Response does not contain notecard 2"); | ||||
|             Assert.That(llsdresponse.Contains("10000000-0000-0000-0000-000000000003"), Is.True, "Response does not contain notecard 3"); | ||||
|             Assert.That(llsdresponse.Contains("10000000-0000-0000-0000-000000000004"), Is.True, "Response does not contain notecard 4"); | ||||
|             Assert.That(llsdresponse.Contains("10000000-0000-0000-0000-000000000005"), Is.True, "Response does not contain notecard 5"); | ||||
|         } | ||||
| 
 | ||||
|     } | ||||
| 
 | ||||
| } | ||||
|  | @ -1,300 +0,0 @@ | |||
| /* | ||||
|  * Copyright (c) Contributors, http://opensimulator.org/ | ||||
|  * See CONTRIBUTORS.TXT for a full list of copyright holders. | ||||
|  * | ||||
|  * Redistribution and use in source and binary forms, with or without | ||||
|  * modification, are permitted provided that the following conditions are met: | ||||
|  *     * Redistributions of source code must retain the above copyright | ||||
|  *       notice, this list of conditions and the following disclaimer. | ||||
|  *     * Redistributions in binary form must reproduce the above copyright | ||||
|  *       notice, this list of conditions and the following disclaimer in the | ||||
|  *       documentation and/or other materials provided with the distribution. | ||||
|  *     * Neither the name of the OpenSimulator Project nor the | ||||
|  *       names of its contributors may be used to endorse or promote products | ||||
|  *       derived from this software without specific prior written permission. | ||||
|  * | ||||
|  * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY | ||||
|  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | ||||
|  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||||
|  * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY | ||||
|  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | ||||
|  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||||
|  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | ||||
|  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||||
|  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||||
|  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||
|  */ | ||||
| 
 | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using System.Linq; | ||||
| using System.IO; | ||||
| using System.Text.RegularExpressions; | ||||
| using log4net; | ||||
| using log4net.Config; | ||||
| using NUnit.Framework; | ||||
| using OpenMetaverse; | ||||
| using OpenSim.Capabilities.Handlers; | ||||
| using OpenSim.Framework; | ||||
| using OpenSim.Framework.Servers.HttpServer; | ||||
| using OpenSim.Region.Framework.Scenes; | ||||
| using OpenSim.Services.Interfaces; | ||||
| using OpenSim.Tests.Common; | ||||
| 
 | ||||
| namespace OpenSim.Capabilities.Handlers.FetchInventory.Tests | ||||
| { | ||||
|     [TestFixture] | ||||
|     public class FetchInventoryDescendents2HandlerTests : OpenSimTestCase | ||||
|     { | ||||
|         private UUID m_userID = new UUID("00000000-0000-0000-0000-000000000001"); | ||||
|         private Scene m_scene; | ||||
|         private UUID m_rootFolderID; | ||||
|         private int m_rootDescendents; | ||||
|         private UUID m_notecardsFolder; | ||||
|         private UUID m_objectsFolder; | ||||
| 
 | ||||
|         private void Init() | ||||
|         { | ||||
|             // Create an inventory that looks like this: | ||||
|             // | ||||
|             // /My Inventory | ||||
|             //   <other system folders> | ||||
|             //   /Objects | ||||
|             //      Some Object | ||||
|             //   /Notecards | ||||
|             //      Notecard 1 | ||||
|             //      Notecard 2 | ||||
|             //   /Test Folder | ||||
|             //      Link to notecard  -> /Notecards/Notecard 2 | ||||
|             //      Link to Objects folder -> /Objects | ||||
| 
 | ||||
|             m_scene = new SceneHelpers().SetupScene(); | ||||
| 
 | ||||
|             m_scene.InventoryService.CreateUserInventory(m_userID); | ||||
| 
 | ||||
|             m_rootFolderID = m_scene.InventoryService.GetRootFolder(m_userID).ID; | ||||
| 
 | ||||
|             InventoryFolderBase of = m_scene.InventoryService.GetFolderForType(m_userID, FolderType.Object); | ||||
|             m_objectsFolder = of.ID; | ||||
| 
 | ||||
|             // Add an object | ||||
|             InventoryItemBase item = new InventoryItemBase(new UUID("b0000000-0000-0000-0000-00000000000b"), m_userID); | ||||
|             item.AssetID = UUID.Random(); | ||||
|             item.AssetType = (int)AssetType.Object; | ||||
|             item.Folder = m_objectsFolder; | ||||
|             item.Name = "Some Object"; | ||||
|             m_scene.InventoryService.AddItem(item); | ||||
| 
 | ||||
|             InventoryFolderBase ncf = m_scene.InventoryService.GetFolderForType(m_userID, FolderType.Notecard); | ||||
|             m_notecardsFolder = ncf.ID; | ||||
| 
 | ||||
|             // Add a notecard | ||||
|             item = new InventoryItemBase(new UUID("10000000-0000-0000-0000-000000000001"), m_userID); | ||||
|             item.AssetID = UUID.Random(); | ||||
|             item.AssetType = (int)AssetType.Notecard; | ||||
|             item.Folder = m_notecardsFolder; | ||||
|             item.Name = "Test Notecard 1"; | ||||
|             m_scene.InventoryService.AddItem(item); | ||||
|             // Add another notecard | ||||
|             item.ID = new UUID("20000000-0000-0000-0000-000000000002"); | ||||
|             item.AssetID = new UUID("a0000000-0000-0000-0000-00000000000a"); | ||||
|             item.Name = "Test Notecard 2"; | ||||
|             m_scene.InventoryService.AddItem(item); | ||||
| 
 | ||||
|             // Add a folder | ||||
|             InventoryFolderBase folder = new InventoryFolderBase(new UUID("f0000000-0000-0000-0000-00000000000f"), "Test Folder", m_userID, m_rootFolderID); | ||||
|             folder.Type = (short)FolderType.None; | ||||
|             m_scene.InventoryService.AddFolder(folder); | ||||
| 
 | ||||
|             // Add a link to notecard 2 in Test Folder | ||||
|             item.AssetID = item.ID; // use item ID of notecard 2 | ||||
|             item.ID = new UUID("40000000-0000-0000-0000-000000000004"); | ||||
|             item.AssetType = (int)AssetType.Link; | ||||
|             item.Folder = folder.ID; | ||||
|             item.Name = "Link to notecard"; | ||||
|             m_scene.InventoryService.AddItem(item); | ||||
| 
 | ||||
|             // Add a link to the Objects folder in Test Folder | ||||
|             item.AssetID = m_scene.InventoryService.GetFolderForType(m_userID, FolderType.Object).ID; // use item ID of Objects folder | ||||
|             item.ID = new UUID("50000000-0000-0000-0000-000000000005"); | ||||
|             item.AssetType = (int)AssetType.LinkFolder; | ||||
|             item.Folder = folder.ID; | ||||
|             item.Name = "Link to Objects folder"; | ||||
|             m_scene.InventoryService.AddItem(item); | ||||
| 
 | ||||
|             InventoryCollection coll = m_scene.InventoryService.GetFolderContent(m_userID, m_rootFolderID); | ||||
|             m_rootDescendents = coll.Items.Count + coll.Folders.Count; | ||||
|             Console.WriteLine("Number of descendents: " + m_rootDescendents); | ||||
|         } | ||||
| 
 | ||||
|         private string dorequest(FetchInvDescHandler handler, string request) | ||||
|         { | ||||
|             TestOSHttpRequest req = new TestOSHttpRequest(); | ||||
|             TestOSHttpResponse resp = new TestOSHttpResponse(); | ||||
|             using(ExpiringKey<UUID> bad = new ExpiringKey<UUID>(5000)) // bad but this is test | ||||
|             using (MemoryStream ms = new MemoryStream(Utils.StringToBytes(request), false)) | ||||
|             { | ||||
|                 req.InputStream = ms; | ||||
|                 handler.FetchInventoryDescendentsRequest(req, resp, bad); | ||||
|             } | ||||
|             return Util.UTF8.GetString(resp.RawBuffer); | ||||
|         } | ||||
| 
 | ||||
|         [Test] | ||||
|         public void Test_001_SimpleFolder() | ||||
|         { | ||||
|             TestHelpers.InMethod(); | ||||
| 
 | ||||
|             Init(); | ||||
| 
 | ||||
|             FetchInvDescHandler handler = new FetchInvDescHandler(m_scene.InventoryService, null, m_scene); | ||||
| 
 | ||||
|             string request = "<llsd><map><key>folders</key><array><map><key>fetch_folders</key><integer>1</integer><key>fetch_items</key><boolean>1</boolean><key>folder_id</key><uuid>"; | ||||
|             request += m_rootFolderID; | ||||
|             request += "</uuid><key>owner_id</key><uuid>"; | ||||
|             request += m_userID.ToString(); | ||||
|             request += "</uuid><key>sort_order</key><integer>1</integer></map></array></map></llsd>"; | ||||
| 
 | ||||
|             string llsdresponse = dorequest(handler, request); | ||||
| 
 | ||||
|             Assert.That(llsdresponse != null, Is.True, "Incorrect null response"); | ||||
|             Assert.That(llsdresponse != string.Empty, Is.True, "Incorrect empty response"); | ||||
|             Assert.That(llsdresponse.Contains(m_userID.ToString()), Is.True, "Response should contain userID"); | ||||
| 
 | ||||
|             string descendents = "descendents</key><integer>" + m_rootDescendents + "</integer>"; | ||||
|             Assert.That(llsdresponse.Contains(descendents), Is.True, "Incorrect number of descendents"); | ||||
|             Console.WriteLine(llsdresponse); | ||||
|         } | ||||
| 
 | ||||
|         [Test] | ||||
|         public void Test_002_MultipleFolders() | ||||
|         { | ||||
|             TestHelpers.InMethod(); | ||||
| 
 | ||||
|             FetchInvDescHandler handler = new FetchInvDescHandler(m_scene.InventoryService, null, m_scene); | ||||
| 
 | ||||
|             string request = "<llsd><map><key>folders</key><array>"; | ||||
|             request += "<map><key>fetch_folders</key><integer>1</integer><key>fetch_items</key><boolean>1</boolean><key>folder_id</key><uuid>"; | ||||
|             request += m_rootFolderID; | ||||
|             request += "</uuid><key>owner_id</key><uuid>00000000-0000-0000-0000-000000000001</uuid><key>sort_order</key><integer>1</integer></map>"; | ||||
|             request += "<map><key>fetch_folders</key><integer>1</integer><key>fetch_items</key><boolean>1</boolean><key>folder_id</key><uuid>"; | ||||
|             request += m_notecardsFolder; | ||||
|             request += "</uuid><key>owner_id</key><uuid>00000000-0000-0000-0000-000000000001</uuid><key>sort_order</key><integer>1</integer></map>"; | ||||
|             request += "</array></map></llsd>"; | ||||
| 
 | ||||
|             string llsdresponse = dorequest(handler, request); | ||||
|             Console.WriteLine(llsdresponse); | ||||
| 
 | ||||
|             string descendents = "descendents</key><integer>" + m_rootDescendents + "</integer>"; | ||||
|             Assert.That(llsdresponse.Contains(descendents), Is.True, "Incorrect number of descendents for root folder"); | ||||
|             descendents = "descendents</key><integer>2</integer>"; | ||||
|             Assert.That(llsdresponse.Contains(descendents), Is.True, "Incorrect number of descendents for Notecard folder"); | ||||
| 
 | ||||
|             Assert.That(llsdresponse.Contains("10000000-0000-0000-0000-000000000001"), Is.True, "Notecard 1 is missing from response"); | ||||
|             Assert.That(llsdresponse.Contains("20000000-0000-0000-0000-000000000002"), Is.True, "Notecard 2 is missing from response"); | ||||
|         } | ||||
| 
 | ||||
|         [Test] | ||||
|         public void Test_003_Links() | ||||
|         { | ||||
|             TestHelpers.InMethod(); | ||||
| 
 | ||||
|             FetchInvDescHandler handler = new FetchInvDescHandler(m_scene.InventoryService, null, m_scene); | ||||
| 
 | ||||
|             string request = "<llsd><map><key>folders</key><array><map><key>fetch_folders</key><integer>1</integer><key>fetch_items</key><boolean>1</boolean><key>folder_id</key><uuid>"; | ||||
|             request += "f0000000-0000-0000-0000-00000000000f"; | ||||
|             request += "</uuid><key>owner_id</key><uuid>00000000-0000-0000-0000-000000000001</uuid><key>sort_order</key><integer>1</integer></map></array></map></llsd>"; | ||||
| 
 | ||||
|             string llsdresponse = dorequest(handler, request); | ||||
|             Console.WriteLine(llsdresponse); | ||||
| 
 | ||||
|             string descendents = "descendents</key><integer>2</integer>"; | ||||
|             Assert.That(llsdresponse.Contains(descendents), Is.True, "Incorrect number of descendents for Test Folder"); | ||||
| 
 | ||||
|             // Make sure that the note card link is included | ||||
|             Assert.That(llsdresponse.Contains("Link to notecard"), Is.True, "Link to notecard is missing"); | ||||
| 
 | ||||
|             //Make sure the notecard item itself is included | ||||
|             Assert.That(llsdresponse.Contains("Test Notecard 2"), Is.True, "Notecard 2 item (the source) is missing"); | ||||
| 
 | ||||
|             // Make sure that the source item is before the link item | ||||
|             int pos1 = llsdresponse.IndexOf("Test Notecard 2"); | ||||
|             int pos2 = llsdresponse.IndexOf("Link to notecard"); | ||||
|             Assert.Less(pos1, pos2, "Source of link is after link"); | ||||
| 
 | ||||
|             // Make sure the folder link is included | ||||
|             Assert.That(llsdresponse.Contains("Link to Objects folder"), Is.True, "Link to Objects folder is missing"); | ||||
| 
 | ||||
| /* contents of link folder are not supposed to be listed | ||||
|             // Make sure the objects inside the Objects folder are included | ||||
|             // Note: I'm not entirely sure this is needed, but that's what I found in the implementation | ||||
|             Assert.That(llsdresponse.Contains("Some Object"), Is.True, "Some Object item (contents of the source) is missing"); | ||||
| */ | ||||
|             // Make sure that the source item is before the link item | ||||
|             pos1 = llsdresponse.IndexOf("Some Object"); | ||||
|             pos2 = llsdresponse.IndexOf("Link to Objects folder"); | ||||
|             Assert.Less(pos1, pos2, "Contents of source of folder link is after folder link"); | ||||
|         } | ||||
| 
 | ||||
|         [Test] | ||||
|         public void Test_004_DuplicateFolders() | ||||
|         { | ||||
|             TestHelpers.InMethod(); | ||||
| 
 | ||||
|             FetchInvDescHandler handler = new FetchInvDescHandler(m_scene.InventoryService, null, m_scene); | ||||
| 
 | ||||
|             string request = "<llsd><map><key>folders</key><array>"; | ||||
|             request += "<map><key>fetch_folders</key><integer>1</integer><key>fetch_items</key><boolean>1</boolean><key>folder_id</key><uuid>"; | ||||
|             request += m_rootFolderID; | ||||
|             request += "</uuid><key>owner_id</key><uuid>00000000-0000-0000-0000-000000000000</uuid><key>sort_order</key><integer>1</integer></map>"; | ||||
|             request += "<map><key>fetch_folders</key><integer>1</integer><key>fetch_items</key><boolean>1</boolean><key>folder_id</key><uuid>"; | ||||
|             request += m_notecardsFolder; | ||||
|             request += "</uuid><key>owner_id</key><uuid>00000000-0000-0000-0000-000000000000</uuid><key>sort_order</key><integer>1</integer></map>"; | ||||
|             request += "<map><key>fetch_folders</key><integer>1</integer><key>fetch_items</key><boolean>1</boolean><key>folder_id</key><uuid>"; | ||||
|             request += m_rootFolderID; | ||||
|             request += "</uuid><key>owner_id</key><uuid>00000000-0000-0000-0000-000000000000</uuid><key>sort_order</key><integer>1</integer></map>"; | ||||
|             request += "<map><key>fetch_folders</key><integer>1</integer><key>fetch_items</key><boolean>1</boolean><key>folder_id</key><uuid>"; | ||||
|             request += m_notecardsFolder; | ||||
|             request += "</uuid><key>owner_id</key><uuid>00000000-0000-0000-0000-000000000000</uuid><key>sort_order</key><integer>1</integer></map>"; | ||||
|             request += "</array></map></llsd>"; | ||||
| 
 | ||||
|             string llsdresponse = dorequest(handler, request); | ||||
|             Console.WriteLine(llsdresponse); | ||||
| 
 | ||||
|             string root_folder = "<key>folder_id</key><uuid>" + m_rootFolderID + "</uuid>"; | ||||
|             string notecards_folder = "<key>folder_id</key><uuid>" + m_notecardsFolder + "</uuid>"; | ||||
| 
 | ||||
|             Assert.That(llsdresponse.Contains(root_folder), "Missing root folder"); | ||||
|             Assert.That(llsdresponse.Contains(notecards_folder), "Missing notecards folder"); | ||||
|             int count = Regex.Matches(llsdresponse, root_folder).Count; | ||||
|             Assert.AreEqual(1, count, "More than 1 root folder in response"); | ||||
|             count = Regex.Matches(llsdresponse, notecards_folder).Count; | ||||
|             Assert.AreEqual(2, count, "More than 1 notecards folder in response"); // Notecards will also be under root, so 2 | ||||
|         } | ||||
| 
 | ||||
|         [Test] | ||||
|         public void Test_005_FolderZero() | ||||
|         { | ||||
| 
 | ||||
|             TestHelpers.InMethod(); | ||||
| 
 | ||||
|             Init(); | ||||
| 
 | ||||
|             FetchInvDescHandler handler = new FetchInvDescHandler(m_scene.InventoryService, null, m_scene); | ||||
| 
 | ||||
|             string request = "<llsd><map><key>folders</key><array><map><key>fetch_folders</key><integer>1</integer><key>fetch_items</key><boolean>1</boolean><key>folder_id</key><uuid>"; | ||||
|             request += UUID.Zero; | ||||
|             request += "</uuid><key>owner_id</key><uuid>00000000-0000-0000-0000-000000000000</uuid><key>sort_order</key><integer>1</integer></map></array></map></llsd>"; | ||||
| 
 | ||||
|             string llsdresponse = dorequest(handler, request); | ||||
| 
 | ||||
|             Assert.That(llsdresponse != null, Is.True, "Incorrect null response"); | ||||
|             Assert.That(llsdresponse != string.Empty, Is.True, "Incorrect empty response"); | ||||
|             // we do return a answer now | ||||
|             //Assert.That(llsdresponse.Contains("bad_folders</key><array><uuid>00000000-0000-0000-0000-000000000000"), Is.True, "Folder Zero should be a bad folder"); | ||||
| 
 | ||||
|             Console.WriteLine(llsdresponse); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
| } | ||||
|  | @ -0,0 +1,124 @@ | |||
| /* | ||||
|  * Copyright (c) Contributors, http://opensimulator.org/ | ||||
|  * See CONTRIBUTORS.TXT for a full list of copyright holders. | ||||
|  * | ||||
|  * Redistribution and use in source and binary forms, with or without | ||||
|  * modification, are permitted provided that the following conditions are met: | ||||
|  *     * Redistributions of source code must retain the above copyright | ||||
|  *       notice, this list of conditions and the following disclaimer. | ||||
|  *     * Redistributions in binary form must reproduce the above copyright | ||||
|  *       notice, this list of conditions and the following disclaimer in the | ||||
|  *       documentation and/or other materials provided with the distribution. | ||||
|  *     * Neither the name of the OpenSimulator Project nor the | ||||
|  *       names of its contributors may be used to endorse or promote products | ||||
|  *       derived from this software without specific prior written permission. | ||||
|  * | ||||
|  * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY | ||||
|  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | ||||
|  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||||
|  * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY | ||||
|  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | ||||
|  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||||
|  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | ||||
|  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||||
|  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||||
|  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||
|  */ | ||||
| 
 | ||||
| using System; | ||||
| using System.Collections; | ||||
| using System.Collections.Generic; | ||||
| using System.Reflection; | ||||
| using log4net; | ||||
| using Nini.Config; | ||||
| using OpenMetaverse; | ||||
| using OpenMetaverse.StructuredData; | ||||
| using OpenSim.Framework; | ||||
| using OpenSim.Framework.Capabilities; | ||||
| using OpenSim.Region.Framework.Interfaces; | ||||
| using OpenSim.Framework.Servers.HttpServer; | ||||
| using OpenSim.Services.Interfaces; | ||||
| using Caps = OpenSim.Framework.Capabilities.Caps; | ||||
| using OSDArray = OpenMetaverse.StructuredData.OSDArray; | ||||
| using OSDMap = OpenMetaverse.StructuredData.OSDMap; | ||||
| 
 | ||||
| namespace OpenSim.Capabilities.Handlers | ||||
| { | ||||
|     public class FetchInventory2Handler | ||||
|     { | ||||
| //        private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | ||||
| 
 | ||||
|         private IInventoryService m_inventoryService; | ||||
| 
 | ||||
|         public FetchInventory2Handler(IInventoryService invService) | ||||
|         { | ||||
|             m_inventoryService = invService; | ||||
|         } | ||||
| 
 | ||||
|         public string FetchInventoryRequest(string request, string path, string param, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) | ||||
|         { | ||||
| //            m_log.DebugFormat("[FETCH INVENTORY HANDLER]: Received FetchInventory capabilty request"); | ||||
| 
 | ||||
|             OSDMap requestmap = (OSDMap)OSDParser.DeserializeLLSDXml(Utils.StringToBytes(request)); | ||||
|             OSDArray itemsRequested = (OSDArray)requestmap["items"]; | ||||
| 
 | ||||
|             string reply; | ||||
|             LLSDFetchInventory llsdReply = new LLSDFetchInventory(); | ||||
| 
 | ||||
|             foreach (OSDMap osdItemId in itemsRequested) | ||||
|             { | ||||
|                 UUID itemId = osdItemId["item_id"].AsUUID(); | ||||
| 
 | ||||
|                 InventoryItemBase item = m_inventoryService.GetItem(new InventoryItemBase(itemId)); | ||||
| 
 | ||||
|                 if (item != null) | ||||
|                 { | ||||
|                     // We don't know the agent that this request belongs to so we'll use the agent id of the item | ||||
|                     // which will be the same for all items. | ||||
|                     llsdReply.agent_id = item.Owner; | ||||
| 
 | ||||
|                     llsdReply.items.Array.Add(ConvertInventoryItem(item)); | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|             reply = LLSDHelpers.SerialiseLLSDReply(llsdReply); | ||||
| 
 | ||||
|             return reply; | ||||
|         } | ||||
| 
 | ||||
|         /// <summary> | ||||
|         /// Convert an internal inventory item object into an LLSD object. | ||||
|         /// </summary> | ||||
|         /// <param name="invItem"></param> | ||||
|         /// <returns></returns> | ||||
|         private LLSDInventoryItem ConvertInventoryItem(InventoryItemBase invItem) | ||||
|         { | ||||
|             LLSDInventoryItem llsdItem = new LLSDInventoryItem(); | ||||
|             llsdItem.asset_id = invItem.AssetID; | ||||
|             llsdItem.created_at = invItem.CreationDate; | ||||
|             llsdItem.desc = invItem.Description; | ||||
|             llsdItem.flags = (int)invItem.Flags; | ||||
|             llsdItem.item_id = invItem.ID; | ||||
|             llsdItem.name = invItem.Name; | ||||
|             llsdItem.parent_id = invItem.Folder; | ||||
|             llsdItem.type = invItem.AssetType; | ||||
|             llsdItem.inv_type = invItem.InvType; | ||||
| 
 | ||||
|             llsdItem.permissions = new LLSDPermissions(); | ||||
|             llsdItem.permissions.creator_id = invItem.CreatorIdAsUuid; | ||||
|             llsdItem.permissions.base_mask = (int)invItem.CurrentPermissions; | ||||
|             llsdItem.permissions.everyone_mask = (int)invItem.EveryOnePermissions; | ||||
|             llsdItem.permissions.group_id = invItem.GroupID; | ||||
|             llsdItem.permissions.group_mask = (int)invItem.GroupPermissions; | ||||
|             llsdItem.permissions.is_owner_group = invItem.GroupOwned; | ||||
|             llsdItem.permissions.next_owner_mask = (int)invItem.NextPermissions; | ||||
|             llsdItem.permissions.owner_id = invItem.Owner; | ||||
|             llsdItem.permissions.owner_mask = (int)invItem.CurrentPermissions; | ||||
|             llsdItem.sale_info = new LLSDSaleInfo(); | ||||
|             llsdItem.sale_info.sale_price = invItem.SalePrice; | ||||
|             llsdItem.sale_info.sale_type = invItem.SaleType; | ||||
| 
 | ||||
|             return llsdItem; | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | @ -61,7 +61,7 @@ namespace OpenSim.Capabilities.Handlers | |||
|             if (m_InventoryService == null) | ||||
|                 throw new Exception(String.Format("Failed to load InventoryService from {0}; config is {1}", invService, m_ConfigName)); | ||||
| 
 | ||||
|             FetchInventory2Handler fiHandler = new FetchInventory2Handler(m_InventoryService, UUID.Zero); | ||||
|             FetchInventory2Handler fiHandler = new FetchInventory2Handler(m_InventoryService); | ||||
|             IRequestHandler reqHandler | ||||
|                 = new RestStreamHandler( | ||||
|                     "POST", "/CAPS/FetchInventory/", fiHandler.FetchInventoryRequest, "FetchInventory", null); | ||||
|  | @ -1,190 +0,0 @@ | |||
| /* | ||||
|  * Copyright (c) Contributors, http://opensimulator.org/ | ||||
|  * See CONTRIBUTORS.TXT for a full list of copyright holders. | ||||
|  * | ||||
|  * Redistribution and use in source and binary forms, with or without | ||||
|  * modification, are permitted provided that the following conditions are met: | ||||
|  *     * Redistributions of source code must retain the above copyright | ||||
|  *       notice, this list of conditions and the following disclaimer. | ||||
|  *     * Redistributions in binary form must reproduce the above copyright | ||||
|  *       notice, this list of conditions and the following disclaimer in the | ||||
|  *       documentation and/or other materials provided with the distribution. | ||||
|  *     * Neither the name of the OpenSimulator Project nor the | ||||
|  *       names of its contributors may be used to endorse or promote products | ||||
|  *       derived from this software without specific prior written permission. | ||||
|  * | ||||
|  * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY | ||||
|  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | ||||
|  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||||
|  * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY | ||||
|  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | ||||
|  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||||
|  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | ||||
|  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||||
|  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||||
|  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||
|  */ | ||||
| 
 | ||||
| using System; | ||||
| using System.Collections; | ||||
| using System.Collections.Generic; | ||||
| using System.Net; | ||||
| using System.Reflection; | ||||
| using log4net; | ||||
| using Nini.Config; | ||||
| using OpenMetaverse; | ||||
| using OpenMetaverse.StructuredData; | ||||
| using OpenSim.Framework; | ||||
| using OpenSim.Framework.Servers; | ||||
| using OpenSim.Framework.Servers.HttpServer; | ||||
| using OpenSim.Services.Interfaces; | ||||
| using Caps = OpenSim.Framework.Capabilities.Caps; | ||||
| 
 | ||||
| namespace OpenSim.Capabilities.Handlers | ||||
| { | ||||
|     public class GetAssetsHandler | ||||
|     { | ||||
|         private static readonly ILog m_log = | ||||
|                    LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | ||||
| 
 | ||||
|         private static readonly Dictionary<string, AssetType> queryTypes = new Dictionary<string, AssetType>() | ||||
|         { | ||||
|             {"texture_id", AssetType.Texture}, | ||||
|             {"sound_id", AssetType.Sound}, | ||||
|             {"callcard_id", AssetType.CallingCard}, | ||||
|             {"landmark_id", AssetType.Landmark}, | ||||
|             {"script_id", AssetType.LSLText}, | ||||
|             {"clothing_id", AssetType.Clothing}, | ||||
|             {"object_id", AssetType.Object}, | ||||
|             {"notecard_id", AssetType.Notecard}, | ||||
|             {"lsltext_id", AssetType.LSLText}, | ||||
|             {"lslbyte_id", AssetType.LSLBytecode}, | ||||
|             {"txtr_tga_id", AssetType.TextureTGA}, | ||||
|             {"bodypart_id", AssetType.Bodypart}, | ||||
|             {"snd_wav_id", AssetType.SoundWAV}, | ||||
|             {"img_tga_id", AssetType.ImageTGA}, | ||||
|             {"jpeg_id", AssetType.ImageJPEG}, | ||||
|             {"animatn_id", AssetType.Animation}, | ||||
|             {"gesture_id", AssetType.Gesture}, | ||||
|             {"mesh_id", AssetType.Mesh}, | ||||
|             {"settings_id", AssetType.Settings} | ||||
|         }; | ||||
| 
 | ||||
|         private IAssetService m_assetService; | ||||
| 
 | ||||
|         public GetAssetsHandler(IAssetService assService) | ||||
|         { | ||||
|             m_assetService = assService; | ||||
|         } | ||||
| 
 | ||||
|         public void Handle(OSHttpRequest req, OSHttpResponse response) | ||||
|         { | ||||
|             response.ContentType = "text/plain"; | ||||
| 
 | ||||
|             if (m_assetService == null) | ||||
|             { | ||||
|                 response.StatusCode = (int)HttpStatusCode.ServiceUnavailable; | ||||
|                 response.KeepAlive = false; | ||||
|                 return; | ||||
|             } | ||||
| 
 | ||||
|             response.StatusCode = (int)HttpStatusCode.BadRequest; | ||||
| 
 | ||||
|             var queries = req.QueryAsDictionary; | ||||
|             if(queries.Count == 0) | ||||
|                 return; | ||||
| 
 | ||||
|             AssetType type = AssetType.Unknown; | ||||
|             string assetStr = string.Empty; | ||||
|             foreach (KeyValuePair<string,string> kvp in queries) | ||||
|             { | ||||
|                 if (queryTypes.ContainsKey(kvp.Key)) | ||||
|                 { | ||||
|                     type = queryTypes[kvp.Key]; | ||||
|                     assetStr = kvp.Value; | ||||
|                     break; | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|             if(type == AssetType.Unknown) | ||||
|             { | ||||
|                 //m_log.Warn("[GETASSET]: Unknown type: " + query); | ||||
|                 m_log.Warn("[GETASSET]: Unknown type"); | ||||
|                 response.StatusCode = (int)HttpStatusCode.NotFound; | ||||
|                 return; | ||||
|             } | ||||
| 
 | ||||
|             if (String.IsNullOrEmpty(assetStr)) | ||||
|                 return; | ||||
| 
 | ||||
|             UUID assetID = UUID.Zero; | ||||
|             if(!UUID.TryParse(assetStr, out assetID)) | ||||
|                 return; | ||||
| 
 | ||||
|             AssetBase asset = m_assetService.Get(assetID.ToString()); | ||||
|             if(asset == null) | ||||
|             { | ||||
|                 // m_log.Warn("[GETASSET]: not found: " + query + " " + assetStr); | ||||
|                 response.StatusCode = (int)HttpStatusCode.NotFound; | ||||
|                 return; | ||||
|             } | ||||
| 
 | ||||
|             if (asset.Type != (sbyte)type) | ||||
|                 return; | ||||
| 
 | ||||
|             int len = asset.Data.Length; | ||||
| 
 | ||||
|             string range = null; | ||||
|             if (req.Headers["Range"] != null) | ||||
|                 range = req.Headers["Range"]; | ||||
|             else if (req.Headers["range"] != null) | ||||
|                 range = req.Headers["range"]; | ||||
| 
 | ||||
|             // range request | ||||
|             int start, end; | ||||
|             if (Util.TryParseHttpRange(range, out start, out end)) | ||||
|             { | ||||
|                 // Before clamping start make sure we can satisfy it in order to avoid | ||||
|                 // sending back the last byte instead of an error status | ||||
|                 if (start >= asset.Data.Length) | ||||
|                 { | ||||
|                     response.StatusCode = (int)HttpStatusCode.RequestedRangeNotSatisfiable; | ||||
|                     return; | ||||
|                 } | ||||
| 
 | ||||
|                 if (end == -1) | ||||
|                     end = asset.Data.Length - 1; | ||||
|                 else | ||||
|                     end = Utils.Clamp(end, 0, asset.Data.Length - 1); | ||||
| 
 | ||||
|                 start = Utils.Clamp(start, 0, end); | ||||
|                 len = end - start + 1; | ||||
| 
 | ||||
|                 //m_log.Debug("Serving " + start + " to " + end + " of " + texture.Data.Length + " bytes for texture " + texture.ID); | ||||
|                 response.AddHeader("Content-Range", String.Format("bytes {0}-{1}/{2}", start, end, asset.Data.Length)); | ||||
|                 response.StatusCode = (int)HttpStatusCode.PartialContent; | ||||
|                 response.RawBufferStart = start; | ||||
|             } | ||||
|             else | ||||
|                 response.StatusCode = (int)HttpStatusCode.OK; | ||||
| 
 | ||||
|             response.ContentType = asset.Metadata.ContentType; | ||||
|             response.RawBuffer = asset.Data; | ||||
|             response.RawBufferLen = len; | ||||
|             if (type == AssetType.Mesh || type == AssetType.Texture) | ||||
|             { | ||||
|                 if(len > 8196) | ||||
|                 { | ||||
|                     //if(type == AssetType.Texture && ((asset.Flags & AssetFlags.AvatarBake)!= 0)) | ||||
|                     //    responsedata["prio"] = 1; | ||||
|                     //else | ||||
|                     response.Priority = 2; | ||||
|                 } | ||||
|                 else | ||||
|                     response.Priority = 1; | ||||
|             } | ||||
|             else | ||||
|                 response.Priority = -1; | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | @ -30,6 +30,7 @@ using System.Collections; | |||
| using System.Collections.Specialized; | ||||
| using System.Reflection; | ||||
| using System.IO; | ||||
| using System.Text; | ||||
| using System.Web; | ||||
| using log4net; | ||||
| using Nini.Config; | ||||
|  | @ -43,113 +44,71 @@ using Caps = OpenSim.Framework.Capabilities.Caps; | |||
| 
 | ||||
| namespace OpenSim.Capabilities.Handlers | ||||
| { | ||||
|     public class GetMeshHandler | ||||
|     public class GetMeshHandler : BaseStreamHandler | ||||
|     { | ||||
|         private static readonly ILog m_log = | ||||
|                    LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | ||||
| 
 | ||||
| //        private static readonly ILog m_log = | ||||
| //            LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | ||||
|          | ||||
|         private IAssetService m_assetService; | ||||
| 
 | ||||
|         public const string DefaultFormat = "vnd.ll.mesh"; | ||||
| 
 | ||||
|         public GetMeshHandler(IAssetService assService) | ||||
|         public GetMeshHandler(string path, IAssetService assService, string name, string description) | ||||
|             : base("GET", path, name, description) | ||||
|         { | ||||
|             m_assetService = assService; | ||||
|         } | ||||
|         public Hashtable Handle(Hashtable request) | ||||
| 
 | ||||
|         protected override byte[] ProcessRequest(string path, Stream request, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) | ||||
|         { | ||||
|             return ProcessGetMesh(request, UUID.Zero, null); ; | ||||
|         } | ||||
|             // Try to parse the texture ID from the request URL | ||||
|             NameValueCollection query = HttpUtility.ParseQueryString(httpRequest.Url.Query); | ||||
|             string meshStr = query.GetOne("mesh_id"); | ||||
| 
 | ||||
|         public Hashtable ProcessGetMesh(Hashtable request, UUID AgentId, Caps cap) | ||||
|         { | ||||
|             Hashtable responsedata = new Hashtable(); | ||||
|             if (m_assetService == null) | ||||
|             { | ||||
|                 responsedata["int_response_code"] = (int)System.Net.HttpStatusCode.ServiceUnavailable; | ||||
|                 responsedata["str_response_string"] = "The asset service is unavailable"; | ||||
|                 responsedata["keepalive"] = false; | ||||
|                 return responsedata; | ||||
|             } | ||||
| 
 | ||||
|             responsedata["int_response_code"] = (int)System.Net.HttpStatusCode.BadRequest; | ||||
|             responsedata["content_type"] = "text/plain"; | ||||
|             responsedata["int_bytes"] = 0; | ||||
| 
 | ||||
|             string meshStr = string.Empty; | ||||
|             if (request.ContainsKey("mesh_id")) | ||||
|                 meshStr = request["mesh_id"].ToString(); | ||||
| 
 | ||||
|             if (String.IsNullOrEmpty(meshStr)) | ||||
|                 return responsedata; | ||||
| //            m_log.DebugFormat("Fetching mesh {0}", meshStr); | ||||
| 
 | ||||
|             UUID meshID = UUID.Zero; | ||||
|             if(!UUID.TryParse(meshStr, out meshID)) | ||||
|                 return responsedata; | ||||
| 
 | ||||
|             AssetBase mesh = m_assetService.Get(meshID.ToString()); | ||||
|             if(mesh == null) | ||||
|             if (!String.IsNullOrEmpty(meshStr) && UUID.TryParse(meshStr, out meshID)) | ||||
|             { | ||||
|                 responsedata["int_response_code"] = (int)System.Net.HttpStatusCode.NotFound; | ||||
|                 responsedata["str_response_string"] = "Mesh not found."; | ||||
|                 return responsedata; | ||||
|             } | ||||
| 
 | ||||
|             if (mesh.Type != (SByte)AssetType.Mesh) | ||||
|             { | ||||
|                 responsedata["str_response_string"] = "Asset isn't a mesh."; | ||||
|                 return responsedata; | ||||
|             } | ||||
| 
 | ||||
|             string range = String.Empty; | ||||
| 
 | ||||
|             if (((Hashtable)request["headers"])["range"] != null) | ||||
|                range = (string)((Hashtable)request["headers"])["range"]; | ||||
|             else if (((Hashtable)request["headers"])["Range"] != null) | ||||
|                 range = (string)((Hashtable)request["headers"])["Range"]; | ||||
| 
 | ||||
|             responsedata["content_type"] = "application/vnd.ll.mesh"; | ||||
|             if (String.IsNullOrEmpty(range)) | ||||
|             { | ||||
|                 // full mesh | ||||
|                 responsedata["str_response_string"] = Convert.ToBase64String(mesh.Data); | ||||
|                 responsedata["int_response_code"] = (int)System.Net.HttpStatusCode.OK; | ||||
|                 return responsedata; | ||||
|             } | ||||
| 
 | ||||
|             // range request | ||||
|             int start, end; | ||||
|             if (Util.TryParseHttpRange(range, out start, out end)) | ||||
|             { | ||||
|                 // Before clamping start make sure we can satisfy it in order to avoid | ||||
|                 // sending back the last byte instead of an error status | ||||
|                 if (start >= mesh.Data.Length) | ||||
|                 if (m_assetService == null) | ||||
|                 { | ||||
|                     responsedata["str_response_string"] = "This range doesnt exist."; | ||||
|                     return responsedata; | ||||
|                     httpResponse.StatusCode = 404; | ||||
|                     httpResponse.ContentType = "text/plain"; | ||||
|                     byte[] data = Encoding.UTF8.GetBytes("The asset service is unavailable.  So is your mesh."); | ||||
|                     httpResponse.Body.Write(data, 0, data.Length); | ||||
|                     return null; | ||||
|                 } | ||||
| 
 | ||||
|                 end = Utils.Clamp(end, 0, mesh.Data.Length - 1); | ||||
|                 start = Utils.Clamp(start, 0, end); | ||||
|                 int len = end - start + 1; | ||||
|                 AssetBase mesh = m_assetService.Get(meshID.ToString()); | ||||
| 
 | ||||
|                 //m_log.Debug("Serving " + start + " to " + end + " of " + texture.Data.Length + " bytes for texture " + texture.ID); | ||||
|                 Hashtable headers = new Hashtable(); | ||||
|                 headers["Content-Range"] = String.Format("bytes {0}-{1}/{2}", start, end, mesh.Data.Length); | ||||
|                 responsedata["headers"] = headers; | ||||
|                 responsedata["int_response_code"] = (int)System.Net.HttpStatusCode.PartialContent; | ||||
| 
 | ||||
|                 byte[] d = new byte[len]; | ||||
|                 Array.Copy(mesh.Data, start, d, 0, len); | ||||
|                 responsedata["bin_response_data"] = d; | ||||
|                 responsedata["int_bytes"] = len; | ||||
|                 return responsedata; | ||||
|                 if (mesh != null) | ||||
|                 { | ||||
|                     if (mesh.Type == (SByte)AssetType.Mesh) | ||||
|                     { | ||||
|                         byte[] data = mesh.Data; | ||||
|                         httpResponse.Body.Write(data, 0, data.Length); | ||||
|                         httpResponse.ContentType = "application/vnd.ll.mesh"; | ||||
|                         httpResponse.StatusCode = 200; | ||||
|                     } | ||||
|                     // Optionally add additional mesh types here | ||||
|                     else | ||||
|                     { | ||||
|                         httpResponse.StatusCode = 404; | ||||
|                         httpResponse.ContentType = "text/plain"; | ||||
|                         byte[] data = Encoding.UTF8.GetBytes("Unfortunately, this asset isn't a mesh."); | ||||
|                         httpResponse.Body.Write(data, 0, data.Length); | ||||
|                         httpResponse.KeepAlive = false; | ||||
|                     } | ||||
|                 } | ||||
|                 else | ||||
|                 { | ||||
|                     httpResponse.StatusCode = 404; | ||||
|                     httpResponse.ContentType = "text/plain"; | ||||
|                     byte[] data = Encoding.UTF8.GetBytes("Your Mesh wasn't found.  Sorry!"); | ||||
|                     httpResponse.Body.Write(data, 0, data.Length); | ||||
|                     httpResponse.KeepAlive = false; | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|             m_log.Warn("[GETMESH]: Failed to parse a range from GetMesh request, sending full asset: " + (string)request["uri"]); | ||||
|             responsedata["str_response_string"] = Convert.ToBase64String(mesh.Data); | ||||
|             responsedata["int_response_code"] = (int)System.Net.HttpStatusCode.OK; | ||||
|             return responsedata; | ||||
|             return null; | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | @ -25,13 +25,16 @@ | |||
|  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||
|  */ | ||||
| 
 | ||||
| using Nini.Config; | ||||
| using OpenMetaverse; | ||||
| using OpenSim.Framework.Servers.HttpServer; | ||||
| using OpenSim.Server.Base; | ||||
| using OpenSim.Server.Handlers.Base; | ||||
| using OpenSim.Services.Interfaces; | ||||
| using System; | ||||
| using System.Collections; | ||||
| using Nini.Config; | ||||
| using OpenSim.Server.Base; | ||||
| using OpenSim.Services.Interfaces; | ||||
| using OpenSim.Framework.Servers.HttpServer; | ||||
| using OpenSim.Server.Handlers.Base; | ||||
| using OpenSim.Framework.Servers; | ||||
| 
 | ||||
| using OpenMetaverse; | ||||
| 
 | ||||
| namespace OpenSim.Capabilities.Handlers | ||||
| { | ||||
|  | @ -62,17 +65,8 @@ namespace OpenSim.Capabilities.Handlers | |||
|             if (m_AssetService == null) | ||||
|                 throw new Exception(String.Format("Failed to load AssetService from {0}; config is {1}", assetService, m_ConfigName)); | ||||
| 
 | ||||
|             string rurl = serverConfig.GetString("GetMeshRedirectURL"); | ||||
| 
 | ||||
|             GetMeshHandler gmeshHandler = new GetMeshHandler(m_AssetService); | ||||
|             IRequestHandler reqHandler | ||||
|                 = new RestHTTPHandler( | ||||
|                     "GET", | ||||
|                     "/" + UUID.Random(), | ||||
|                     httpMethod => gmeshHandler.ProcessGetMesh(httpMethod, UUID.Zero, null), | ||||
|                     "GetMesh", | ||||
|                     null); | ||||
|             server.AddStreamHandler(reqHandler); ; | ||||
|             server.AddStreamHandler( | ||||
|                 new GetMeshHandler("/CAPS/GetMesh/" /*+ UUID.Random() */, m_AssetService, "GetMesh", null)); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | @ -47,41 +47,46 @@ using Caps = OpenSim.Framework.Capabilities.Caps; | |||
| 
 | ||||
| namespace OpenSim.Capabilities.Handlers | ||||
| { | ||||
|     public class GetTextureHandler | ||||
|     public class GetTextureHandler : BaseStreamHandler | ||||
|     { | ||||
|         private static readonly ILog m_log = | ||||
|             LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | ||||
| 
 | ||||
|         private IAssetService m_assetService; | ||||
| 
 | ||||
|         public const string DefaultFormat = "x-j2c"; | ||||
| 
 | ||||
|         public GetTextureHandler(IAssetService assService) | ||||
|         // TODO: Change this to a config option | ||||
|         private string m_RedirectURL = null; | ||||
| 
 | ||||
|         public GetTextureHandler(string path, IAssetService assService, string name, string description, string redirectURL) | ||||
|             : base("GET", path, name, description) | ||||
|         { | ||||
|             m_assetService = assService; | ||||
|             m_RedirectURL = redirectURL; | ||||
|             if (m_RedirectURL != null && !m_RedirectURL.EndsWith("/")) | ||||
|                 m_RedirectURL += "/"; | ||||
|         } | ||||
| 
 | ||||
|         public Hashtable Handle(Hashtable request) | ||||
|         protected override byte[] ProcessRequest(string path, Stream request, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) | ||||
|         { | ||||
|             Hashtable ret = new Hashtable(); | ||||
|             ret["int_response_code"] = (int)System.Net.HttpStatusCode.NotFound; | ||||
|             ret["content_type"] = "text/plain"; | ||||
|             ret["int_bytes"] = 0; | ||||
|             string textureStr = (string)request["texture_id"]; | ||||
|             string format = (string)request["format"]; | ||||
|             // Try to parse the texture ID from the request URL | ||||
|             NameValueCollection query = HttpUtility.ParseQueryString(httpRequest.Url.Query); | ||||
|             string textureStr = query.GetOne("texture_id"); | ||||
|             string format = query.GetOne("format"); | ||||
| 
 | ||||
|             //m_log.DebugFormat("[GETTEXTURE]: called {0}", textureStr); | ||||
| 
 | ||||
|             if (m_assetService == null) | ||||
|             { | ||||
|                 m_log.Error("[GETTEXTURE]: Cannot fetch texture " + textureStr + " without an asset service"); | ||||
|                 httpResponse.StatusCode = (int)System.Net.HttpStatusCode.NotFound; | ||||
|             } | ||||
| 
 | ||||
|             UUID textureID; | ||||
|             if (!String.IsNullOrEmpty(textureStr) && UUID.TryParse(textureStr, out textureID)) | ||||
|             { | ||||
| //                m_log.DebugFormat("[GETTEXTURE]: Received request for texture id {0}", textureID); | ||||
| 
 | ||||
|                  | ||||
|                 string[] formats; | ||||
|                 if (!string.IsNullOrEmpty(format)) | ||||
|                 { | ||||
|  | @ -89,50 +94,41 @@ namespace OpenSim.Capabilities.Handlers | |||
|                 } | ||||
|                 else | ||||
|                 { | ||||
|                     formats = new string[1] { DefaultFormat }; // default | ||||
|                     if (((Hashtable)request["headers"])["Accept"] != null) | ||||
|                         formats = WebUtil.GetPreferredImageTypes((string)((Hashtable)request["headers"])["Accept"]); | ||||
|                     formats = WebUtil.GetPreferredImageTypes(httpRequest.Headers.Get("Accept")); | ||||
|                     if (formats.Length == 0) | ||||
|                         formats = new string[1] { DefaultFormat }; // default | ||||
| 
 | ||||
|                 } | ||||
|                 // OK, we have an array with preferred formats, possibly with only one entry | ||||
|                 bool foundtexture = false; | ||||
| 
 | ||||
|                 httpResponse.StatusCode = (int)System.Net.HttpStatusCode.NotFound; | ||||
|                 foreach (string f in formats) | ||||
|                 { | ||||
|                     foundtexture = FetchTexture(request, ret, textureID, f); | ||||
|                     if (foundtexture) | ||||
|                     if (FetchTexture(httpRequest, httpResponse, textureID, f)) | ||||
|                         break; | ||||
|                 } | ||||
|                 if (!foundtexture) | ||||
|                 { | ||||
|                     ret["int_response_code"] = 404; | ||||
|                     ret["error_status_text"] = "not found"; | ||||
|                     ret["str_response_string"] = "not found"; | ||||
|                     ret["content_type"] = "text/plain"; | ||||
|                     ret["int_bytes"] = 0; | ||||
|                 } | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 m_log.Warn("[GETTEXTURE]: Failed to parse a texture_id from GetTexture request: " + (string)request["uri"]); | ||||
|                 m_log.Warn("[GETTEXTURE]: Failed to parse a texture_id from GetTexture request: " + httpRequest.Url); | ||||
|             } | ||||
| 
 | ||||
| //            m_log.DebugFormat( | ||||
| //                "[GETTEXTURE]: For texture {0} sending back response {1}, data length {2}", | ||||
| //                textureID, httpResponse.StatusCode, httpResponse.ContentLength); | ||||
|             return ret; | ||||
| 
 | ||||
|             return null; | ||||
|         } | ||||
| 
 | ||||
|         /// <summary> | ||||
|         /// | ||||
|         ///  | ||||
|         /// </summary> | ||||
|         /// <param name="httpRequest"></param> | ||||
|         /// <param name="httpResponse"></param> | ||||
|         /// <param name="textureID"></param> | ||||
|         /// <param name="format"></param> | ||||
|         /// <returns>False for "caller try another codec"; true otherwise</returns> | ||||
|         private bool FetchTexture(Hashtable request, Hashtable response, UUID textureID, string format) | ||||
|         private bool FetchTexture(IOSHttpRequest httpRequest, IOSHttpResponse httpResponse, UUID textureID, string format) | ||||
|         { | ||||
| //            m_log.DebugFormat("[GETTEXTURE]: {0} with requested format {1}", textureID, format); | ||||
|             AssetBase texture; | ||||
|  | @ -141,76 +137,92 @@ namespace OpenSim.Capabilities.Handlers | |||
|             if (format != DefaultFormat) | ||||
|                 fullID = fullID + "-" + format; | ||||
| 
 | ||||
|             // try the cache | ||||
|             texture = m_assetService.GetCached(fullID); | ||||
| 
 | ||||
|             if (texture == null) | ||||
|             if (!String.IsNullOrEmpty(m_RedirectURL)) | ||||
|             { | ||||
|                 //m_log.DebugFormat("[GETTEXTURE]: texture was not in the cache"); | ||||
| 
 | ||||
|                 // Fetch locally or remotely. Misses return a 404 | ||||
|                 texture = m_assetService.Get(textureID.ToString()); | ||||
|                 // Only try to fetch locally cached textures. Misses are redirected | ||||
|                 texture = m_assetService.GetCached(fullID); | ||||
| 
 | ||||
|                 if (texture != null) | ||||
|                 { | ||||
|                     if (texture.Type != (sbyte)AssetType.Texture) | ||||
|                         return true; | ||||
| 
 | ||||
|                     if (format == DefaultFormat) | ||||
|                     { | ||||
|                         WriteTextureData(request, response, texture, format); | ||||
|                         return true; | ||||
|                     } | ||||
|                     else | ||||
|                     { | ||||
|                         AssetBase newTexture = new AssetBase(texture.ID + "-" + format, texture.Name, (sbyte)AssetType.Texture, texture.Metadata.CreatorID); | ||||
|                         newTexture.Data = ConvertTextureData(texture, format); | ||||
|                         if (newTexture.Data.Length == 0) | ||||
|                             return false; // !!! Caller try another codec, please! | ||||
| 
 | ||||
|                         newTexture.Flags = AssetFlags.Collectable; | ||||
|                         newTexture.Temporary = true; | ||||
|                         newTexture.Local = true; | ||||
|                         m_assetService.Store(newTexture); | ||||
|                         WriteTextureData(request, response, newTexture, format); | ||||
|                         httpResponse.StatusCode = (int)System.Net.HttpStatusCode.NotFound; | ||||
|                         return true; | ||||
|                     } | ||||
|                     WriteTextureData(httpRequest, httpResponse, texture, format); | ||||
|                 } | ||||
|            } | ||||
|            else // it was on the cache | ||||
|            { | ||||
|                //m_log.DebugFormat("[GETTEXTURE]: texture was in the cache"); | ||||
|                WriteTextureData(request, response, texture, format); | ||||
|                return true; | ||||
|            } | ||||
|                 else | ||||
|                 { | ||||
|                     string textureUrl = m_RedirectURL + "?texture_id="+ textureID.ToString(); | ||||
|                     m_log.Debug("[GETTEXTURE]: Redirecting texture request to " + textureUrl); | ||||
|                     httpResponse.StatusCode = (int)OSHttpStatusCode.RedirectMovedPermanently; | ||||
|                     httpResponse.RedirectLocation = textureUrl; | ||||
|                     return true; | ||||
|                 } | ||||
|             } | ||||
|             else // no redirect | ||||
|             { | ||||
|                 // try the cache | ||||
|                 texture = m_assetService.GetCached(fullID); | ||||
| 
 | ||||
|             //response = new Hashtable(); | ||||
|                 if (texture == null) | ||||
|                 { | ||||
| //                    m_log.DebugFormat("[GETTEXTURE]: texture was not in the cache"); | ||||
| 
 | ||||
|                     // Fetch locally or remotely. Misses return a 404 | ||||
|                     texture = m_assetService.Get(textureID.ToString()); | ||||
| 
 | ||||
|                     if (texture != null) | ||||
|                     { | ||||
|                         if (texture.Type != (sbyte)AssetType.Texture) | ||||
|                         { | ||||
|                             httpResponse.StatusCode = (int)System.Net.HttpStatusCode.NotFound; | ||||
|                             return true; | ||||
|                         } | ||||
|                         if (format == DefaultFormat) | ||||
|                         { | ||||
|                             WriteTextureData(httpRequest, httpResponse, texture, format); | ||||
|                             return true; | ||||
|                         } | ||||
|                         else | ||||
|                         { | ||||
|                             AssetBase newTexture = new AssetBase(texture.ID + "-" + format, texture.Name, (sbyte)AssetType.Texture, texture.Metadata.CreatorID); | ||||
|                             newTexture.Data = ConvertTextureData(texture, format); | ||||
|                             if (newTexture.Data.Length == 0) | ||||
|                                 return false; // !!! Caller try another codec, please! | ||||
| 
 | ||||
|                             newTexture.Flags = AssetFlags.Collectable; | ||||
|                             newTexture.Temporary = true; | ||||
|                             newTexture.Local = true; | ||||
|                             m_assetService.Store(newTexture); | ||||
|                             WriteTextureData(httpRequest, httpResponse, newTexture, format); | ||||
|                             return true; | ||||
|                         } | ||||
|                     } | ||||
|                } | ||||
|                else // it was on the cache | ||||
|                { | ||||
| //                   m_log.DebugFormat("[GETTEXTURE]: texture was in the cache"); | ||||
|                    WriteTextureData(httpRequest, httpResponse, texture, format); | ||||
|                    return true; | ||||
|                } | ||||
|             } | ||||
| 
 | ||||
|             //WriteTextureData(request,response,null,format); | ||||
|             // not found | ||||
|             //m_log.Warn("[GETTEXTURE]: Texture " + textureID + " not found"); | ||||
|             return false; | ||||
| //            m_log.Warn("[GETTEXTURE]: Texture " + textureID + " not found"); | ||||
|             httpResponse.StatusCode = (int)System.Net.HttpStatusCode.NotFound; | ||||
|             return true; | ||||
|         } | ||||
| 
 | ||||
|         private void WriteTextureData(Hashtable request, Hashtable response, AssetBase texture, string format) | ||||
|         private void WriteTextureData(IOSHttpRequest request, IOSHttpResponse response, AssetBase texture, string format) | ||||
|         { | ||||
|             Hashtable headers = new Hashtable(); | ||||
|             response["headers"] = headers; | ||||
| 
 | ||||
|             string range = String.Empty; | ||||
| 
 | ||||
|             if (((Hashtable)request["headers"])["range"] != null) | ||||
|                 range = (string)((Hashtable)request["headers"])["range"]; | ||||
| 
 | ||||
|             else if (((Hashtable)request["headers"])["Range"] != null) | ||||
|                 range = (string)((Hashtable)request["headers"])["Range"]; | ||||
|             string range = request.Headers.GetOne("Range"); | ||||
| 
 | ||||
|             if (!String.IsNullOrEmpty(range)) // JP2's only | ||||
|             { | ||||
|                 // Range request | ||||
|                 int start, end; | ||||
|                 if (Util.TryParseHttpRange(range, out start, out end)) | ||||
|                 if (TryParseRange(range, out start, out end)) | ||||
|                 { | ||||
|                     // Before clamping start make sure we can satisfy it in order to avoid | ||||
|                     // sending back the last byte instead of an error status | ||||
|  | @ -232,8 +244,10 @@ namespace OpenSim.Capabilities.Handlers | |||
|                         // However, if we return PartialContent (or OK) instead, the viewer will display that resolution. | ||||
| 
 | ||||
| //                        response.StatusCode = (int)System.Net.HttpStatusCode.RequestedRangeNotSatisfiable; | ||||
|                         // viewers don't seem to handle RequestedRangeNotSatisfiable and keep retrying with same parameters | ||||
|                         response["int_response_code"] = (int)System.Net.HttpStatusCode.NotFound; | ||||
| //                        response.AddHeader("Content-Range", String.Format("bytes */{0}", texture.Data.Length)); | ||||
| //                        response.StatusCode = (int)System.Net.HttpStatusCode.OK; | ||||
|                         response.StatusCode = (int)System.Net.HttpStatusCode.PartialContent; | ||||
|                         response.ContentType = texture.Metadata.ContentType; | ||||
|                     } | ||||
|                     else | ||||
|                     { | ||||
|  | @ -248,35 +262,41 @@ namespace OpenSim.Capabilities.Handlers | |||
| 
 | ||||
| //                        m_log.Debug("Serving " + start + " to " + end + " of " + texture.Data.Length + " bytes for texture " + texture.ID); | ||||
| 
 | ||||
|                         response["content-type"] = texture.Metadata.ContentType; | ||||
|                         response["int_response_code"] = (int)System.Net.HttpStatusCode.PartialContent; | ||||
|                         headers["Content-Range"] = String.Format("bytes {0}-{1}/{2}", start, end, texture.Data.Length); | ||||
|                         // Always return PartialContent, even if the range covered the entire data length | ||||
|                         // We were accidentally sending back 404 before in this situation | ||||
|                         // https://issues.apache.org/bugzilla/show_bug.cgi?id=51878 supports sending 206 even if the | ||||
|                         // entire range is requested, and viewer 3.2.2 (and very probably earlier) seems fine with this. | ||||
|                         // | ||||
|                         // We also do not want to send back OK even if the whole range was satisfiable since this causes | ||||
|                         // HTTP textures on at least Imprudence 1.4.0-beta2 to never display the final texture quality. | ||||
| //                        if (end > maxEnd) | ||||
| //                            response.StatusCode = (int)System.Net.HttpStatusCode.OK; | ||||
| //                        else | ||||
|                         response.StatusCode = (int)System.Net.HttpStatusCode.PartialContent; | ||||
| 
 | ||||
|                         byte[] d = new byte[len]; | ||||
|                         Array.Copy(texture.Data, start, d, 0, len); | ||||
|                         response["bin_response_data"] = d; | ||||
|                         response["int_bytes"] = len; | ||||
|                         response.ContentLength = len; | ||||
|                         response.ContentType = texture.Metadata.ContentType; | ||||
|                         response.AddHeader("Content-Range", String.Format("bytes {0}-{1}/{2}", start, end, texture.Data.Length)); | ||||
|      | ||||
|                         response.Body.Write(texture.Data, start, len); | ||||
|                     } | ||||
|                 } | ||||
|                 else | ||||
|                 { | ||||
|                     m_log.Warn("[GETTEXTURE]: Malformed Range header: " + range); | ||||
|                     response["int_response_code"] = (int)System.Net.HttpStatusCode.BadRequest; | ||||
|                     response.StatusCode = (int)System.Net.HttpStatusCode.BadRequest; | ||||
|                 } | ||||
|             } | ||||
|             else // JP2's or other formats | ||||
|             { | ||||
|                 // Full content request | ||||
|                 response["int_response_code"] = (int)System.Net.HttpStatusCode.OK; | ||||
|                 response.StatusCode = (int)System.Net.HttpStatusCode.OK; | ||||
|                 response.ContentLength = texture.Data.Length; | ||||
|                 if (format == DefaultFormat) | ||||
|                     response["content_type"] = texture.Metadata.ContentType; | ||||
|                     response.ContentType = texture.Metadata.ContentType; | ||||
|                 else | ||||
|                     response["content_type"] = "image/" + format; | ||||
| 
 | ||||
|                 response["bin_response_data"] = texture.Data; | ||||
|                 response["int_bytes"] = texture.Data.Length; | ||||
| 
 | ||||
| //                response.Body.Write(texture.Data, 0, texture.Data.Length); | ||||
|                     response.ContentType = "image/" + format; | ||||
|                 response.Body.Write(texture.Data, 0, texture.Data.Length); | ||||
|             } | ||||
| 
 | ||||
| //            if (response.StatusCode < 200 || response.StatusCode > 299) | ||||
|  | @ -289,41 +309,86 @@ namespace OpenSim.Capabilities.Handlers | |||
| //                    texture.FullID, range, response.StatusCode, response.ContentLength, texture.Data.Length); | ||||
|         } | ||||
| 
 | ||||
|         /// <summary> | ||||
|         /// Parse a range header. | ||||
|         /// </summary> | ||||
|         /// <remarks> | ||||
|         /// As per http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html, | ||||
|         /// this obeys range headers with two values (e.g. 533-4165) and no second value (e.g. 533-). | ||||
|         /// Where there is no value, -1 is returned. | ||||
|         /// FIXME: Need to cover the case where only a second value is specified (e.g. -4165), probably by returning -1 | ||||
|         /// for start.</remarks> | ||||
|         /// <returns></returns> | ||||
|         /// <param name='header'></param> | ||||
|         /// <param name='start'>Start of the range.  Undefined if this was not a number.</param> | ||||
|         /// <param name='end'>End of the range.  Will be -1 if no end specified.  Undefined if there was a raw string but this was not a number.</param> | ||||
|         private bool TryParseRange(string header, out int start, out int end) | ||||
|         { | ||||
|             start = end = 0; | ||||
| 
 | ||||
|             if (header.StartsWith("bytes=")) | ||||
|             { | ||||
|                 string[] rangeValues = header.Substring(6).Split('-'); | ||||
| 
 | ||||
|                 if (rangeValues.Length == 2) | ||||
|                 { | ||||
|                     if (!Int32.TryParse(rangeValues[0], out start)) | ||||
|                         return false; | ||||
| 
 | ||||
|                     string rawEnd = rangeValues[1]; | ||||
| 
 | ||||
|                     if (rawEnd == "") | ||||
|                     { | ||||
|                         end = -1; | ||||
|                         return true; | ||||
|                     } | ||||
|                     else if (Int32.TryParse(rawEnd, out end)) | ||||
|                     { | ||||
|                         return true; | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|             start = end = 0; | ||||
|             return false; | ||||
|         } | ||||
| 
 | ||||
|         private byte[] ConvertTextureData(AssetBase texture, string format) | ||||
|         { | ||||
|             m_log.DebugFormat("[GETTEXTURE]: Converting texture {0} to {1}", texture.ID, format); | ||||
|             byte[] data = new byte[0]; | ||||
| 
 | ||||
|             MemoryStream imgstream = new MemoryStream(); | ||||
|             Bitmap mTexture = null; | ||||
|             ManagedImage managedImage = null; | ||||
|             Image image = null; | ||||
|             Bitmap mTexture = new Bitmap(1, 1); | ||||
|             ManagedImage managedImage; | ||||
|             Image image = (Image)mTexture; | ||||
| 
 | ||||
|             try | ||||
|             { | ||||
|                 // Taking our jpeg2000 data, decoding it, then saving it to a byte array with regular data | ||||
| 
 | ||||
|                 imgstream = new MemoryStream(); | ||||
| 
 | ||||
|                 // Decode image to System.Drawing.Image | ||||
|                 if (OpenJPEG.DecodeToImage(texture.Data, out managedImage, out image) && image != null) | ||||
|                 if (OpenJPEG.DecodeToImage(texture.Data, out managedImage, out image)) | ||||
|                 { | ||||
|                     // Save to bitmap | ||||
|                     mTexture = new Bitmap(image); | ||||
| 
 | ||||
|                     using(EncoderParameters myEncoderParameters = new EncoderParameters()) | ||||
|                     { | ||||
|                         myEncoderParameters.Param[0] = new EncoderParameter(Encoder.Quality,95L); | ||||
|                     EncoderParameters myEncoderParameters = new EncoderParameters(); | ||||
|                     myEncoderParameters.Param[0] = new EncoderParameter(Encoder.Quality, 95L); | ||||
| 
 | ||||
|                         // Save bitmap to stream | ||||
|                         ImageCodecInfo codec = GetEncoderInfo("image/" + format); | ||||
|                         if (codec != null) | ||||
|                         { | ||||
|                             mTexture.Save(imgstream, codec, myEncoderParameters); | ||||
|                     // Save bitmap to stream | ||||
|                     ImageCodecInfo codec = GetEncoderInfo("image/" + format); | ||||
|                     if (codec != null) | ||||
|                     { | ||||
|                         mTexture.Save(imgstream, codec, myEncoderParameters); | ||||
|                         // Write the stream to a byte array for output | ||||
|                             data = imgstream.ToArray(); | ||||
|                         } | ||||
|                         else | ||||
|                             m_log.WarnFormat("[GETTEXTURE]: No such codec {0}", format); | ||||
|                         data = imgstream.ToArray(); | ||||
|                     } | ||||
|                     else | ||||
|                         m_log.WarnFormat("[GETTEXTURE]: No such codec {0}", format); | ||||
| 
 | ||||
|                 } | ||||
|             } | ||||
|             catch (Exception e) | ||||
|  | @ -340,10 +405,11 @@ namespace OpenSim.Capabilities.Handlers | |||
|                 if (image != null) | ||||
|                     image.Dispose(); | ||||
| 
 | ||||
|                 if(managedImage != null) | ||||
|                     managedImage.Clear(); | ||||
|                 if (imgstream != null) | ||||
|                 { | ||||
|                     imgstream.Close(); | ||||
|                     imgstream.Dispose(); | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|             return data; | ||||
|  | @ -362,4 +428,4 @@ namespace OpenSim.Capabilities.Handlers | |||
|             return null; | ||||
|         } | ||||
|     } | ||||
| } | ||||
| } | ||||
|  | @ -1,394 +0,0 @@ | |||
| /* | ||||
|  * Copyright (c) Contributors, http://opensimulator.org/ | ||||
|  * See CONTRIBUTORS.TXT for a full list of copyright holders. | ||||
|  * | ||||
|  * Redistribution and use in source and binary forms, with or without | ||||
|  * modification, are permitted provided that the following conditions are met: | ||||
|  *     * Redistributions of source code must retain the above copyright | ||||
|  *       notice, this list of conditions and the following disclaimer. | ||||
|  *     * Redistributions in binary form must reproduce the above copyright | ||||
|  *       notice, this list of conditions and the following disclaimer in the | ||||
|  *       documentation and/or other materials provided with the distribution. | ||||
|  *     * Neither the name of the OpenSimulator Project nor the | ||||
|  *       names of its contributors may be used to endorse or promote products | ||||
|  *       derived from this software without specific prior written permission. | ||||
|  * | ||||
|  * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY | ||||
|  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | ||||
|  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||||
|  * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY | ||||
|  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | ||||
|  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||||
|  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | ||||
|  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||||
|  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||||
|  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||
|  */ | ||||
| 
 | ||||
| using System; | ||||
| using System.Collections; | ||||
| using System.Collections.Specialized; | ||||
| using System.Drawing; | ||||
| using System.Drawing.Imaging; | ||||
| using System.Reflection; | ||||
| using System.IO; | ||||
| using System.Net; | ||||
| using System.Web; | ||||
| using log4net; | ||||
| using Nini.Config; | ||||
| using OpenMetaverse; | ||||
| using OpenMetaverse.StructuredData; | ||||
| using OpenMetaverse.Imaging; | ||||
| using OpenSim.Framework; | ||||
| using OpenSim.Framework.Servers; | ||||
| using OpenSim.Framework.Servers.HttpServer; | ||||
| using OpenSim.Region.Framework.Interfaces; | ||||
| using OpenSim.Services.Interfaces; | ||||
| using Caps = OpenSim.Framework.Capabilities.Caps; | ||||
| 
 | ||||
| namespace OpenSim.Capabilities.Handlers | ||||
| { | ||||
|     public class GetTextureRobustHandler : BaseStreamHandler | ||||
|     { | ||||
|         private static readonly ILog m_log = | ||||
|             LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | ||||
|         private IAssetService m_assetService; | ||||
| 
 | ||||
|         public const string DefaultFormat = "x-j2c"; | ||||
| 
 | ||||
|         // TODO: Change this to a config option | ||||
|         private string m_RedirectURL = null; | ||||
| 
 | ||||
|         public GetTextureRobustHandler(string path, IAssetService assService, string name, string description, string redirectURL) | ||||
|             : base("GET", path, name, description) | ||||
|         { | ||||
|             m_assetService = assService; | ||||
|             m_RedirectURL = redirectURL; | ||||
|             if (m_RedirectURL != null && !m_RedirectURL.EndsWith("/")) | ||||
|                 m_RedirectURL += "/"; | ||||
|         } | ||||
| 
 | ||||
|         protected override byte[] ProcessRequest(string path, Stream request, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) | ||||
|         { | ||||
|             // Try to parse the texture ID from the request URL | ||||
|             NameValueCollection query = HttpUtility.ParseQueryString(httpRequest.Url.Query); | ||||
|             string textureStr = query.GetOne("texture_id"); | ||||
|             string format = query.GetOne("format"); | ||||
| 
 | ||||
|             //m_log.DebugFormat("[GETTEXTURE]: called {0}", textureStr); | ||||
| 
 | ||||
|             if (m_assetService == null) | ||||
|             { | ||||
|                 m_log.Error("[GETTEXTURE]: Cannot fetch texture " + textureStr + " without an asset service"); | ||||
|                 httpResponse.StatusCode = (int)System.Net.HttpStatusCode.NotFound; | ||||
|                 return null; | ||||
|             } | ||||
| 
 | ||||
|             UUID textureID; | ||||
|             if (!String.IsNullOrEmpty(textureStr) && UUID.TryParse(textureStr, out textureID)) | ||||
|             { | ||||
| //                m_log.DebugFormat("[GETTEXTURE]: Received request for texture id {0}", textureID); | ||||
| 
 | ||||
|                 string[] formats; | ||||
|                 if (!string.IsNullOrEmpty(format)) | ||||
|                 { | ||||
|                     formats = new string[1] { format.ToLower() }; | ||||
|                 } | ||||
|                 else | ||||
|                 { | ||||
|                     formats = WebUtil.GetPreferredImageTypes(httpRequest.Headers.Get("Accept")); | ||||
|                     if (formats.Length == 0) | ||||
|                         formats = new string[1] { DefaultFormat }; // default | ||||
| 
 | ||||
|                 } | ||||
|                 // OK, we have an array with preferred formats, possibly with only one entry | ||||
| 
 | ||||
|                 httpResponse.StatusCode = (int)System.Net.HttpStatusCode.NotFound; | ||||
|                 foreach (string f in formats) | ||||
|                 { | ||||
|                     if (FetchTexture(httpRequest, httpResponse, textureID, f)) | ||||
|                         break; | ||||
|                 } | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 m_log.Warn("[GETTEXTURE]: Failed to parse a texture_id from GetTexture request: " + httpRequest.Url); | ||||
|             } | ||||
| 
 | ||||
| //            m_log.DebugFormat( | ||||
| //                "[GETTEXTURE]: For texture {0} sending back response {1}, data length {2}", | ||||
| //                textureID, httpResponse.StatusCode, httpResponse.ContentLength); | ||||
| 
 | ||||
|             return null; | ||||
|         } | ||||
| 
 | ||||
|         /// <summary> | ||||
|         /// | ||||
|         /// </summary> | ||||
|         /// <param name="httpRequest"></param> | ||||
|         /// <param name="httpResponse"></param> | ||||
|         /// <param name="textureID"></param> | ||||
|         /// <param name="format"></param> | ||||
|         /// <returns>False for "caller try another codec"; true otherwise</returns> | ||||
|         private bool FetchTexture(IOSHttpRequest httpRequest, IOSHttpResponse httpResponse, UUID textureID, string format) | ||||
|         { | ||||
|             // m_log.DebugFormat("[GETTEXTURE]: {0} with requested format {1}", textureID, format); | ||||
|             if(!String.IsNullOrEmpty(m_RedirectURL)) | ||||
|             { | ||||
|                 string textureUrl = m_RedirectURL + "?texture_id=" + textureID.ToString(); | ||||
|                 m_log.Debug("[GETTEXTURE]: Redirecting texture request to " + textureUrl); | ||||
|                 httpResponse.StatusCode = (int)HttpStatusCode.Moved; | ||||
|                 httpResponse.AddHeader("Location:", textureUrl); | ||||
|                 return true; | ||||
|             } | ||||
| 
 | ||||
|             // Fetch,  Misses or invalid return a 404 | ||||
|             AssetBase texture = m_assetService.Get(textureID.ToString()); | ||||
|             if (texture != null) | ||||
|             { | ||||
|                 if (texture.Type != (sbyte)AssetType.Texture) | ||||
|                 { | ||||
|                     httpResponse.StatusCode = (int)System.Net.HttpStatusCode.NotFound; | ||||
|                     return true; | ||||
|                 } | ||||
|                 if (format == DefaultFormat) | ||||
|                 { | ||||
|                     WriteTextureData(httpRequest, httpResponse, texture, format); | ||||
|                     return true; | ||||
|                 } | ||||
| 
 | ||||
|                 // need to convert format | ||||
|                 AssetBase newTexture = new AssetBase(texture.ID + "-" + format, texture.Name, (sbyte)AssetType.Texture, texture.Metadata.CreatorID); | ||||
|                 newTexture.Data = ConvertTextureData(texture, format); | ||||
|                 if (newTexture.Data.Length == 0) | ||||
|                     return false; // !!! Caller try another codec, please! | ||||
| 
 | ||||
|                 newTexture.Flags = AssetFlags.Collectable; | ||||
|                 newTexture.Temporary = true; | ||||
|                 newTexture.Local = true; | ||||
|                 WriteTextureData(httpRequest, httpResponse, newTexture, format); | ||||
|                 return true; | ||||
|             } | ||||
| 
 | ||||
|             // not found | ||||
|             // m_log.Warn("[GETTEXTURE]: Texture " + textureID + " not found"); | ||||
|             httpResponse.StatusCode = (int)System.Net.HttpStatusCode.NotFound; | ||||
|             return true; | ||||
|         } | ||||
| 
 | ||||
|         private void WriteTextureData(IOSHttpRequest request, IOSHttpResponse response, AssetBase texture, string format) | ||||
|         { | ||||
|             string range = request.Headers.GetOne("Range"); | ||||
| 
 | ||||
|             if (!String.IsNullOrEmpty(range)) // JP2's only | ||||
|             { | ||||
|                 // Range request | ||||
|                 int start, end; | ||||
|                 if (TryParseRange(range, out start, out end)) | ||||
|                 { | ||||
|                     // Before clamping start make sure we can satisfy it in order to avoid | ||||
|                     // sending back the last byte instead of an error status | ||||
|                     if (start >= texture.Data.Length) | ||||
|                     { | ||||
| //                        m_log.DebugFormat( | ||||
| //                            "[GETTEXTURE]: Client requested range for texture {0} starting at {1} but texture has end of {2}", | ||||
| //                            texture.ID, start, texture.Data.Length); | ||||
| 
 | ||||
|                         // Stricly speaking, as per http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html, we should be sending back | ||||
|                         // Requested Range Not Satisfiable (416) here.  However, it appears that at least recent implementations | ||||
|                         // of the Linden Lab viewer (3.2.1 and 3.3.4 and probably earlier), a viewer that has previously | ||||
|                         // received a very small texture  may attempt to fetch bytes from the server past the | ||||
|                         // range of data that it received originally.  Whether this happens appears to depend on whether | ||||
|                         // the viewer's estimation of how large a request it needs to make for certain discard levels | ||||
|                         // (http://wiki.secondlife.com/wiki/Image_System#Discard_Level_and_Mip_Mapping), chiefly discard | ||||
|                         // level 2.  If this estimate is greater than the total texture size, returning a RequestedRangeNotSatisfiable | ||||
|                         // here will cause the viewer to treat the texture as bad and never display the full resolution | ||||
|                         // However, if we return PartialContent (or OK) instead, the viewer will display that resolution. | ||||
| 
 | ||||
| //                        response.StatusCode = (int)System.Net.HttpStatusCode.RequestedRangeNotSatisfiable; | ||||
| //                        response.AddHeader("Content-Range", String.Format("bytes */{0}", texture.Data.Length)); | ||||
| //                        response.StatusCode = (int)System.Net.HttpStatusCode.OK; | ||||
|                         response.StatusCode = (int)System.Net.HttpStatusCode.PartialContent; | ||||
|                         response.ContentType = texture.Metadata.ContentType; | ||||
|                     } | ||||
|                     else | ||||
|                     { | ||||
|                         // Handle the case where no second range value was given.  This is equivalent to requesting | ||||
|                         // the rest of the entity. | ||||
|                         if (end == -1) | ||||
|                             end = int.MaxValue; | ||||
| 
 | ||||
|                         end = Utils.Clamp(end, 0, texture.Data.Length - 1); | ||||
|                         start = Utils.Clamp(start, 0, end); | ||||
|                         int len = end - start + 1; | ||||
| 
 | ||||
| //                        m_log.Debug("Serving " + start + " to " + end + " of " + texture.Data.Length + " bytes for texture " + texture.ID); | ||||
| 
 | ||||
|                         // Always return PartialContent, even if the range covered the entire data length | ||||
|                         // We were accidentally sending back 404 before in this situation | ||||
|                         // https://issues.apache.org/bugzilla/show_bug.cgi?id=51878 supports sending 206 even if the | ||||
|                         // entire range is requested, and viewer 3.2.2 (and very probably earlier) seems fine with this. | ||||
|                         // | ||||
|                         // We also do not want to send back OK even if the whole range was satisfiable since this causes | ||||
|                         // HTTP textures on at least Imprudence 1.4.0-beta2 to never display the final texture quality. | ||||
| //                        if (end > maxEnd) | ||||
| //                            response.StatusCode = (int)System.Net.HttpStatusCode.OK; | ||||
| //                        else | ||||
|                         response.StatusCode = (int)System.Net.HttpStatusCode.PartialContent; | ||||
| 
 | ||||
|                         response.ContentLength = len; | ||||
|                         response.ContentType = texture.Metadata.ContentType; | ||||
|                         response.AddHeader("Content-Range", String.Format("bytes {0}-{1}/{2}", start, end, texture.Data.Length)); | ||||
|                         response.RawBuffer = texture.Data; | ||||
|                         response.RawBufferStart = start; | ||||
|                         response.RawBufferLen = len; | ||||
|                     } | ||||
|                 } | ||||
|                 else | ||||
|                 { | ||||
|                     m_log.Warn("[GETTEXTURE]: Malformed Range header: " + range); | ||||
|                     response.StatusCode = (int)System.Net.HttpStatusCode.BadRequest; | ||||
|                 } | ||||
|             } | ||||
|             else // JP2's or other formats | ||||
|             { | ||||
|                 // Full content request | ||||
|                 response.StatusCode = (int)System.Net.HttpStatusCode.OK; | ||||
|                 response.ContentLength = texture.Data.Length; | ||||
|                 if (format == DefaultFormat) | ||||
|                     response.ContentType = texture.Metadata.ContentType; | ||||
|                 else | ||||
|                     response.ContentType = "image/" + format; | ||||
|                 response.RawBuffer = texture.Data; | ||||
|                 response.RawBufferStart = 0; | ||||
|                 response.RawBufferLen = texture.Data.Length; | ||||
|             } | ||||
| 
 | ||||
|             //            if (response.StatusCode < 200 || response.StatusCode > 299) | ||||
|             //                m_log.WarnFormat( | ||||
|             //                    "[GETTEXTURE]: For texture {0} requested range {1} responded {2} with content length {3} (actual {4})", | ||||
|             //                    texture.FullID, range, response.StatusCode, response.ContentLength, texture.Data.Length); | ||||
|             //            else | ||||
|             //                m_log.DebugFormat( | ||||
|             //                    "[GETTEXTURE]: For texture {0} requested range {1} responded {2} with content length {3} (actual {4})", | ||||
|             //                    texture.FullID, range, response.StatusCode, response.ContentLength, texture.Data.Length); | ||||
|         } | ||||
| 
 | ||||
|         /// <summary> | ||||
|         /// Parse a range header. | ||||
|         /// </summary> | ||||
|         /// <remarks> | ||||
|         /// As per http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html, | ||||
|         /// this obeys range headers with two values (e.g. 533-4165) and no second value (e.g. 533-). | ||||
|         /// Where there is no value, -1 is returned. | ||||
|         /// FIXME: Need to cover the case where only a second value is specified (e.g. -4165), probably by returning -1 | ||||
|         /// for start.</remarks> | ||||
|         /// <returns></returns> | ||||
|         /// <param name='header'></param> | ||||
|         /// <param name='start'>Start of the range.  Undefined if this was not a number.</param> | ||||
|         /// <param name='end'>End of the range.  Will be -1 if no end specified.  Undefined if there was a raw string but this was not a number.</param> | ||||
|         private bool TryParseRange(string header, out int start, out int end) | ||||
|         { | ||||
|             start = end = 0; | ||||
| 
 | ||||
|             if (header.StartsWith("bytes=")) | ||||
|             { | ||||
|                 string[] rangeValues = header.Substring(6).Split('-'); | ||||
| 
 | ||||
|                 if (rangeValues.Length == 2) | ||||
|                 { | ||||
|                     if (!Int32.TryParse(rangeValues[0], out start)) | ||||
|                         return false; | ||||
| 
 | ||||
|                     string rawEnd = rangeValues[1]; | ||||
| 
 | ||||
|                     if (rawEnd == "") | ||||
|                     { | ||||
|                         end = -1; | ||||
|                         return true; | ||||
|                     } | ||||
|                     else if (Int32.TryParse(rawEnd, out end)) | ||||
|                     { | ||||
|                         return true; | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|             start = end = 0; | ||||
|             return false; | ||||
|         } | ||||
| 
 | ||||
|         private byte[] ConvertTextureData(AssetBase texture, string format) | ||||
|         { | ||||
|             m_log.DebugFormat("[GETTEXTURE]: Converting texture {0} to {1}", texture.ID, format); | ||||
|             byte[] data = new byte[0]; | ||||
| 
 | ||||
|             MemoryStream imgstream = new MemoryStream(); | ||||
|             Bitmap mTexture = null; | ||||
|             ManagedImage managedImage = null; | ||||
|             Image image = null; | ||||
| 
 | ||||
|             try | ||||
|             { | ||||
|                 // Taking our jpeg2000 data, decoding it, then saving it to a byte array with regular data | ||||
|                 // Decode image to System.Drawing.Image | ||||
|                 if (OpenJPEG.DecodeToImage(texture.Data, out managedImage, out image) && image != null) | ||||
|                 { | ||||
|                     // Save to bitmap | ||||
|                     mTexture = new Bitmap(image); | ||||
| 
 | ||||
|                     using(EncoderParameters myEncoderParameters = new EncoderParameters()) | ||||
|                     { | ||||
|                         myEncoderParameters.Param[0] = new EncoderParameter(Encoder.Quality,95L); | ||||
| 
 | ||||
|                         // Save bitmap to stream | ||||
|                         ImageCodecInfo codec = GetEncoderInfo("image/" + format); | ||||
|                         if (codec != null) | ||||
|                         { | ||||
|                             mTexture.Save(imgstream, codec, myEncoderParameters); | ||||
|                             // Write the stream to a byte array for output | ||||
|                             data = imgstream.ToArray(); | ||||
|                         } | ||||
|                         else | ||||
|                             m_log.WarnFormat("[GETTEXTURE]: No such codec {0}", format); | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|             catch (Exception e) | ||||
|             { | ||||
|                 m_log.WarnFormat("[GETTEXTURE]: Unable to convert texture {0} to {1}: {2}", texture.ID, format, e.Message); | ||||
|             } | ||||
|             finally | ||||
|             { | ||||
|                 // Reclaim memory, these are unmanaged resources | ||||
|                 // If we encountered an exception, one or more of these will be null | ||||
|                 if (mTexture != null) | ||||
|                     mTexture.Dispose(); | ||||
| 
 | ||||
|                 if (image != null) | ||||
|                     image.Dispose(); | ||||
| 
 | ||||
|                 if(managedImage != null) | ||||
|                     managedImage.Clear(); | ||||
| 
 | ||||
|                 if (imgstream != null) | ||||
|                     imgstream.Dispose(); | ||||
|             } | ||||
| 
 | ||||
|             return data; | ||||
|         } | ||||
| 
 | ||||
|         // From msdn | ||||
|         private static ImageCodecInfo GetEncoderInfo(String mimeType) | ||||
|         { | ||||
|             ImageCodecInfo[] encoders; | ||||
|             encoders = ImageCodecInfo.GetImageEncoders(); | ||||
|             for (int j = 0; j < encoders.Length; ++j) | ||||
|             { | ||||
|                 if (encoders[j].MimeType == mimeType) | ||||
|                     return encoders[j]; | ||||
|             } | ||||
|             return null; | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | @ -33,7 +33,6 @@ using OpenSim.Framework.Servers.HttpServer; | |||
| using OpenSim.Server.Handlers.Base; | ||||
| using OpenMetaverse; | ||||
| 
 | ||||
| 
 | ||||
| namespace OpenSim.Capabilities.Handlers | ||||
| { | ||||
|     public class GetTextureServerConnector : ServiceConnector | ||||
|  | @ -66,8 +65,7 @@ namespace OpenSim.Capabilities.Handlers | |||
|             string rurl = serverConfig.GetString("GetTextureRedirectURL"); | ||||
|             ; | ||||
|             server.AddStreamHandler( | ||||
|                 new GetTextureRobustHandler("/CAPS/GetTexture", m_AssetService, "GetTexture", null, rurl)); | ||||
|                 new GetTextureHandler("/CAPS/GetTexture/" /*+ UUID.Random() */, m_AssetService, "GetTexture", null, rurl)); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| } | ||||
|  | @ -38,7 +38,6 @@ using OpenSim.Framework.Servers.HttpServer; | |||
| using OpenSim.Region.Framework.Scenes; | ||||
| using OpenSim.Tests.Common; | ||||
| 
 | ||||
| /* | ||||
| namespace OpenSim.Capabilities.Handlers.GetTexture.Tests | ||||
| { | ||||
|     [TestFixture] | ||||
|  | @ -60,5 +59,4 @@ namespace OpenSim.Capabilities.Handlers.GetTexture.Tests | |||
|             Assert.That(resp.StatusCode, Is.EqualTo((int)System.Net.HttpStatusCode.NotFound)); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| */ | ||||
| } | ||||
|  | @ -2,7 +2,7 @@ | |||
| using System.Runtime.CompilerServices; | ||||
| using System.Runtime.InteropServices; | ||||
| 
 | ||||
| // General Information about an assembly is controlled through the following | ||||
| // General Information about an assembly is controlled through the following  | ||||
| // set of attributes. Change these attribute values to modify the information | ||||
| // associated with an assembly. | ||||
| [assembly: AssemblyTitle("OpenSim.Capabilities.Handlers")] | ||||
|  | @ -14,8 +14,8 @@ using System.Runtime.InteropServices; | |||
| [assembly: AssemblyTrademark("")] | ||||
| [assembly: AssemblyCulture("")] | ||||
| 
 | ||||
| // Setting ComVisible to false makes the types in this assembly not visible | ||||
| // to COM components.  If you need to access a type in this assembly from | ||||
| // Setting ComVisible to false makes the types in this assembly not visible  | ||||
| // to COM components.  If you need to access a type in this assembly from  | ||||
| // COM, set the ComVisible attribute to true on that type. | ||||
| [assembly: ComVisible(false)] | ||||
| 
 | ||||
|  | @ -25,9 +25,9 @@ using System.Runtime.InteropServices; | |||
| // Version information for an assembly consists of the following four values: | ||||
| // | ||||
| //      Major Version | ||||
| //      Minor Version | ||||
| //      Minor Version  | ||||
| //      Build Number | ||||
| //      Revision | ||||
| // | ||||
| [assembly: AssemblyVersion(OpenSim.VersionInfo.AssemblyVersionNumber)] | ||||
| [assembly: AssemblyVersion("0.8.1.*")] | ||||
| 
 | ||||
|  |  | |||
|  | @ -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; | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | @ -25,40 +25,52 @@ | |||
|  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||
|  */ | ||||
| 
 | ||||
| 
 | ||||
| using System; | ||||
| using Nini.Config; | ||||
| using OpenSim.Server.Base; | ||||
| using OpenSim.Services.Interfaces; | ||||
| using OpenSim.Framework.ServiceAuth; | ||||
| using OpenSim.Framework.Servers.HttpServer; | ||||
| using OpenSim.Server.Handlers.Base; | ||||
| using OpenMetaverse; | ||||
| 
 | ||||
| namespace OpenSim.Server.Handlers.AgentPreferences | ||||
| namespace OpenSim.Capabilities.Handlers | ||||
| { | ||||
|     public class AgentPreferencesServiceConnector : ServiceConnector | ||||
|     public class UploadBakedTextureServerConnector : ServiceConnector | ||||
|     { | ||||
|         private IAgentPreferencesService m_AgentPreferencesService; | ||||
|         private string m_ConfigName = "AgentPreferencesService"; | ||||
|         private IAssetService m_AssetService; | ||||
|         private string m_ConfigName = "CapsService"; | ||||
| 
 | ||||
|         public AgentPreferencesServiceConnector(IConfigSource config, IHttpServer server, string configName) : | ||||
|         public UploadBakedTextureServerConnector(IConfigSource config, IHttpServer server, string configName) : | ||||
|                 base(config, server, configName) | ||||
|         { | ||||
|             if (configName != String.Empty) | ||||
|                 m_ConfigName = configName; | ||||
| 
 | ||||
|             IConfig serverConfig = config.Configs[m_ConfigName]; | ||||
|             if (serverConfig == null) | ||||
|                 throw new Exception(String.Format("No section {0} in config file", m_ConfigName)); | ||||
|                 throw new Exception(String.Format("No section '{0}' in config file", m_ConfigName)); | ||||
| 
 | ||||
|             string service = serverConfig.GetString("LocalServiceModule", String.Empty); | ||||
|             string assetService = serverConfig.GetString("AssetService", String.Empty); | ||||
| 
 | ||||
|             if (String.IsNullOrWhiteSpace(service)) | ||||
|                 throw new Exception("No LocalServiceModule in config file"); | ||||
|             if (assetService == String.Empty) | ||||
|                 throw new Exception("No AssetService in config file"); | ||||
| 
 | ||||
|             Object[] args = new Object[] { config }; | ||||
|             m_AgentPreferencesService = ServerUtils.LoadPlugin<IAgentPreferencesService>(service, args); | ||||
|             m_AssetService = | ||||
|                     ServerUtils.LoadPlugin<IAssetService>(assetService, args); | ||||
| 
 | ||||
|             IServiceAuth auth = ServiceAuth.Create(config, m_ConfigName); ; | ||||
|             if (m_AssetService == null) | ||||
|                 throw new Exception(String.Format("Failed to load AssetService from {0}; config is {1}", assetService, m_ConfigName)); | ||||
| 
 | ||||
|             server.AddStreamHandler(new AgentPreferencesServerPostHandler(m_AgentPreferencesService, auth)); | ||||
|         } | ||||
|             // NEED TO FIX THIS | ||||
|             OpenSim.Framework.Capabilities.Caps caps = new OpenSim.Framework.Capabilities.Caps(server, "", server.Port, "", UUID.Zero, ""); | ||||
|             server.AddStreamHandler(new RestStreamHandler( | ||||
|                         "POST", | ||||
|                         "/CAPS/UploadBakedTexture/", | ||||
|                         new UploadBakedTextureHandler(caps, m_AssetService, true).UploadBakedTexture, | ||||
|                         "UploadBakedTexture", | ||||
|                         "Upload Baked Texture Capability")); | ||||
| 
 | ||||
|          } | ||||
|     } | ||||
| } | ||||
| } | ||||
|  | @ -0,0 +1,446 @@ | |||
| /* | ||||
|  * Copyright (c) Contributors, http://opensimulator.org/ | ||||
|  * See CONTRIBUTORS.TXT for a full list of copyright holders. | ||||
|  * | ||||
|  * Redistribution and use in source and binary forms, with or without | ||||
|  * modification, are permitted provided that the following conditions are met: | ||||
|  *     * Redistributions of source code must retain the above copyright | ||||
|  *       notice, this list of conditions and the following disclaimer. | ||||
|  *     * Redistributions in binary form must reproduce the above copyright | ||||
|  *       notice, this list of conditions and the following disclaimer in the | ||||
|  *       documentation and/or other materials provided with the distribution. | ||||
|  *     * Neither the name of the OpenSimulator Project nor the | ||||
|  *       names of its contributors may be used to endorse or promote products | ||||
|  *       derived from this software without specific prior written permission. | ||||
|  * | ||||
|  * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY | ||||
|  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | ||||
|  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||||
|  * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY | ||||
|  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | ||||
|  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||||
|  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | ||||
|  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||||
|  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||||
|  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||
|  */ | ||||
| 
 | ||||
| using System; | ||||
| using System.Collections; | ||||
| using System.Collections.Generic; | ||||
| using System.Reflection; | ||||
| using log4net; | ||||
| using Nini.Config; | ||||
| using OpenMetaverse; | ||||
| using OpenMetaverse.StructuredData; | ||||
| using OpenSim.Framework; | ||||
| using OpenSim.Framework.Capabilities; | ||||
| using OpenSim.Region.Framework.Interfaces; | ||||
| using OpenSim.Framework.Servers.HttpServer; | ||||
| using OpenSim.Services.Interfaces; | ||||
| using Caps = OpenSim.Framework.Capabilities.Caps; | ||||
| 
 | ||||
| namespace OpenSim.Capabilities.Handlers | ||||
| { | ||||
|     public class WebFetchInvDescHandler  | ||||
|     { | ||||
|         private static readonly ILog m_log = | ||||
|             LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | ||||
| 
 | ||||
|         private IInventoryService m_InventoryService; | ||||
|         private ILibraryService m_LibraryService; | ||||
| //        private object m_fetchLock = new Object(); | ||||
| 
 | ||||
|         public WebFetchInvDescHandler(IInventoryService invService, ILibraryService libService)  | ||||
|         { | ||||
|             m_InventoryService = invService; | ||||
|             m_LibraryService = libService; | ||||
|         } | ||||
| 
 | ||||
|         public string FetchInventoryDescendentsRequest(string request, string path, string param, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) | ||||
|         { | ||||
| //            lock (m_fetchLock) | ||||
| //            { | ||||
| //                m_log.DebugFormat("[WEB FETCH INV DESC HANDLER]: Received request {0}", request); | ||||
|      | ||||
|                 // nasty temporary hack here, the linden client falsely | ||||
|                 // identifies the uuid 00000000-0000-0000-0000-000000000000 | ||||
|                 // as a string which breaks us | ||||
|                 // | ||||
|                 // correctly mark it as a uuid | ||||
|                 // | ||||
|                 request = request.Replace("<string>00000000-0000-0000-0000-000000000000</string>", "<uuid>00000000-0000-0000-0000-000000000000</uuid>"); | ||||
|      | ||||
|                 // another hack <integer>1</integer> results in a | ||||
|                 // System.ArgumentException: Object type System.Int32 cannot | ||||
|                 // be converted to target type: System.Boolean | ||||
|                 // | ||||
|                 request = request.Replace("<key>fetch_folders</key><integer>0</integer>", "<key>fetch_folders</key><boolean>0</boolean>"); | ||||
|                 request = request.Replace("<key>fetch_folders</key><integer>1</integer>", "<key>fetch_folders</key><boolean>1</boolean>"); | ||||
|      | ||||
|                 Hashtable hash = new Hashtable(); | ||||
|                 try | ||||
|                 { | ||||
|                     hash = (Hashtable)LLSD.LLSDDeserialize(Utils.StringToBytes(request)); | ||||
|                 } | ||||
|                 catch (LLSD.LLSDParseException e) | ||||
|                 { | ||||
|                     m_log.ErrorFormat("[WEB FETCH INV DESC HANDLER]: Fetch error: {0}{1}" + e.Message, e.StackTrace); | ||||
|                     m_log.Error("Request: " + request); | ||||
|                 } | ||||
|      | ||||
|                 ArrayList foldersrequested = (ArrayList)hash["folders"]; | ||||
|      | ||||
|                 string response = ""; | ||||
| 
 | ||||
|                 for (int i = 0; i < foldersrequested.Count; i++) | ||||
|                 { | ||||
|                     string inventoryitemstr = ""; | ||||
|                     Hashtable inventoryhash = (Hashtable)foldersrequested[i]; | ||||
| 
 | ||||
|                     LLSDFetchInventoryDescendents llsdRequest = new LLSDFetchInventoryDescendents(); | ||||
| 
 | ||||
|                     try | ||||
|                     { | ||||
|                         LLSDHelpers.DeserialiseOSDMap(inventoryhash, llsdRequest); | ||||
|                     } | ||||
|                     catch (Exception e) | ||||
|                     { | ||||
|                         m_log.Debug("[WEB FETCH INV DESC HANDLER]: caught exception doing OSD deserialize" + e); | ||||
|                     } | ||||
|                     LLSDInventoryDescendents reply = FetchInventoryReply(llsdRequest); | ||||
| 
 | ||||
|                     inventoryitemstr = LLSDHelpers.SerialiseLLSDReply(reply); | ||||
|                     inventoryitemstr = inventoryitemstr.Replace("<llsd><map><key>folders</key><array>", ""); | ||||
|                     inventoryitemstr = inventoryitemstr.Replace("</array></map></llsd>", ""); | ||||
| 
 | ||||
|                     response += inventoryitemstr; | ||||
|                 } | ||||
| 
 | ||||
|                 if (response.Length == 0) | ||||
|                 { | ||||
|                     // Ter-guess: If requests fail a lot, the client seems to stop requesting descendants. | ||||
|                     // Therefore, I'm concluding that the client only has so many threads available to do requests | ||||
|                     // and when a thread stalls..   is stays stalled. | ||||
|                     // Therefore we need to return something valid | ||||
|                     response = "<llsd><map><key>folders</key><array /></map></llsd>"; | ||||
|                 } | ||||
|                 else | ||||
|                 { | ||||
|                     response = "<llsd><map><key>folders</key><array>" + response + "</array></map></llsd>"; | ||||
|                 } | ||||
| 
 | ||||
| //                m_log.DebugFormat("[WEB FETCH INV DESC HANDLER]: Replying to CAPS fetch inventory request"); | ||||
|                 //m_log.Debug("[WEB FETCH INV DESC HANDLER] "+response); | ||||
| 
 | ||||
|                 return response; | ||||
| 
 | ||||
| //            } | ||||
|         } | ||||
| 
 | ||||
|         /// <summary> | ||||
|         /// Construct an LLSD reply packet to a CAPS inventory request | ||||
|         /// </summary> | ||||
|         /// <param name="invFetch"></param> | ||||
|         /// <returns></returns> | ||||
|         private LLSDInventoryDescendents FetchInventoryReply(LLSDFetchInventoryDescendents invFetch) | ||||
|         { | ||||
|             LLSDInventoryDescendents reply = new LLSDInventoryDescendents(); | ||||
|             LLSDInventoryFolderContents contents = new LLSDInventoryFolderContents(); | ||||
|             contents.agent_id = invFetch.owner_id; | ||||
|             contents.owner_id = invFetch.owner_id; | ||||
|             contents.folder_id = invFetch.folder_id; | ||||
| 
 | ||||
|             reply.folders.Array.Add(contents); | ||||
|             InventoryCollection inv = new InventoryCollection(); | ||||
|             inv.Folders = new List<InventoryFolderBase>(); | ||||
|             inv.Items = new List<InventoryItemBase>(); | ||||
|             int version = 0; | ||||
|             int descendents = 0; | ||||
| 
 | ||||
|             inv | ||||
|                 = Fetch( | ||||
|                     invFetch.owner_id, invFetch.folder_id, invFetch.owner_id, | ||||
|                     invFetch.fetch_folders, invFetch.fetch_items, invFetch.sort_order, out version, out descendents); | ||||
| 
 | ||||
|             if (inv != null && inv.Folders != null) | ||||
|             { | ||||
|                 foreach (InventoryFolderBase invFolder in inv.Folders) | ||||
|                 { | ||||
|                     contents.categories.Array.Add(ConvertInventoryFolder(invFolder)); | ||||
|                 } | ||||
| 
 | ||||
|                 descendents += inv.Folders.Count; | ||||
|             } | ||||
| 
 | ||||
|             if (inv != null && inv.Items != null) | ||||
|             { | ||||
|                 foreach (InventoryItemBase invItem in inv.Items) | ||||
|                 { | ||||
|                     contents.items.Array.Add(ConvertInventoryItem(invItem)); | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|             contents.descendents = descendents; | ||||
|             contents.version = version; | ||||
| 
 | ||||
| //            m_log.DebugFormat( | ||||
| //                "[WEB FETCH INV DESC HANDLER]: Replying to request for folder {0} (fetch items {1}, fetch folders {2}) with {3} items and {4} folders for agent {5}", | ||||
| //                invFetch.folder_id, | ||||
| //                invFetch.fetch_items, | ||||
| //                invFetch.fetch_folders, | ||||
| //                contents.items.Array.Count, | ||||
| //                contents.categories.Array.Count, | ||||
| //                invFetch.owner_id); | ||||
| 
 | ||||
|             return reply; | ||||
|         } | ||||
| 
 | ||||
|         /// <summary> | ||||
|         /// Handle the caps inventory descendents fetch. | ||||
|         /// </summary> | ||||
|         /// <param name="agentID"></param> | ||||
|         /// <param name="folderID"></param> | ||||
|         /// <param name="ownerID"></param> | ||||
|         /// <param name="fetchFolders"></param> | ||||
|         /// <param name="fetchItems"></param> | ||||
|         /// <param name="sortOrder"></param> | ||||
|         /// <param name="version"></param> | ||||
|         /// <returns>An empty InventoryCollection if the inventory look up failed</returns> | ||||
|         private InventoryCollection Fetch( | ||||
|             UUID agentID, UUID folderID, UUID ownerID, | ||||
|             bool fetchFolders, bool fetchItems, int sortOrder, out int version, out int descendents) | ||||
|         { | ||||
| //            m_log.DebugFormat( | ||||
| //                "[WEB FETCH INV DESC HANDLER]: Fetching folders ({0}), items ({1}) from {2} for agent {3}", | ||||
| //                fetchFolders, fetchItems, folderID, agentID); | ||||
| 
 | ||||
|             // FIXME MAYBE: We're not handling sortOrder! | ||||
| 
 | ||||
|             version = 0; | ||||
|             descendents = 0; | ||||
| 
 | ||||
|             InventoryFolderImpl fold; | ||||
|             if (m_LibraryService != null && m_LibraryService.LibraryRootFolder != null && agentID == m_LibraryService.LibraryRootFolder.Owner) | ||||
|             { | ||||
|                 if ((fold = m_LibraryService.LibraryRootFolder.FindFolder(folderID)) != null) | ||||
|                 { | ||||
|                     InventoryCollection ret = new InventoryCollection(); | ||||
|                     ret.Folders = new List<InventoryFolderBase>(); | ||||
|                     ret.Items = fold.RequestListOfItems(); | ||||
|                     descendents = ret.Folders.Count + ret.Items.Count; | ||||
| 
 | ||||
|                     return ret; | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|             InventoryCollection contents = new InventoryCollection(); | ||||
| 
 | ||||
|             if (folderID != UUID.Zero) | ||||
|             { | ||||
|                 InventoryCollection fetchedContents = m_InventoryService.GetFolderContent(agentID, folderID); | ||||
| 
 | ||||
|                 if (fetchedContents == null) | ||||
|                 { | ||||
|                     m_log.WarnFormat("[WEB FETCH INV DESC HANDLER]: Could not get contents of folder {0} for user {1}", folderID, agentID); | ||||
|                     return contents; | ||||
|                 } | ||||
| 
 | ||||
|                 contents = fetchedContents; | ||||
|                 InventoryFolderBase containingFolder = new InventoryFolderBase(); | ||||
|                 containingFolder.ID = folderID; | ||||
|                 containingFolder.Owner = agentID; | ||||
|                 containingFolder = m_InventoryService.GetFolder(containingFolder); | ||||
| 
 | ||||
|                 if (containingFolder != null) | ||||
|                 { | ||||
| //                    m_log.DebugFormat( | ||||
| //                        "[WEB FETCH INV DESC HANDLER]: Retrieved folder {0} {1} for agent id {2}", | ||||
| //                        containingFolder.Name, containingFolder.ID, agentID); | ||||
| 
 | ||||
|                     version = containingFolder.Version; | ||||
| 
 | ||||
|                     if (fetchItems) | ||||
|                     { | ||||
|                         List<InventoryItemBase> itemsToReturn = contents.Items; | ||||
|                         List<InventoryItemBase> originalItems = new List<InventoryItemBase>(itemsToReturn); | ||||
| 
 | ||||
|                         // descendents must only include the links, not the linked items we add | ||||
|                         descendents = originalItems.Count; | ||||
| 
 | ||||
|                         // Add target items for links in this folder before the links themselves. | ||||
|                         foreach (InventoryItemBase item in originalItems) | ||||
|                         { | ||||
|                             if (item.AssetType == (int)AssetType.Link) | ||||
|                             { | ||||
|                                 InventoryItemBase linkedItem = m_InventoryService.GetItem(new InventoryItemBase(item.AssetID)); | ||||
| 
 | ||||
|                                 // Take care of genuinely broken links where the target doesn't exist | ||||
|                                 // HACK: Also, don't follow up links that just point to other links.  In theory this is legitimate, | ||||
|                                 // but no viewer has been observed to set these up and this is the lazy way of avoiding cycles | ||||
|                                 // rather than having to keep track of every folder requested in the recursion. | ||||
|                                 if (linkedItem != null && linkedItem.AssetType != (int)AssetType.Link) | ||||
|                                     itemsToReturn.Insert(0, linkedItem); | ||||
|                             } | ||||
|                         } | ||||
| 
 | ||||
|                         // Now scan for folder links and insert the items they target and those links at the head of the return data | ||||
|                         foreach (InventoryItemBase item in originalItems) | ||||
|                         { | ||||
|                             if (item.AssetType == (int)AssetType.LinkFolder) | ||||
|                             { | ||||
|                                 InventoryCollection linkedFolderContents = m_InventoryService.GetFolderContent(ownerID, item.AssetID); | ||||
|                                 List<InventoryItemBase> links = linkedFolderContents.Items; | ||||
| 
 | ||||
|                                 itemsToReturn.InsertRange(0, links); | ||||
| 
 | ||||
|                                 foreach (InventoryItemBase link in linkedFolderContents.Items) | ||||
|                                 { | ||||
|                                     // Take care of genuinely broken links where the target doesn't exist | ||||
|                                     // HACK: Also, don't follow up links that just point to other links.  In theory this is legitimate, | ||||
|                                     // but no viewer has been observed to set these up and this is the lazy way of avoiding cycles | ||||
|                                     // rather than having to keep track of every folder requested in the recursion. | ||||
|                                     if (link != null) | ||||
|                                     { | ||||
| //                                        m_log.DebugFormat( | ||||
| //                                            "[WEB FETCH INV DESC HANDLER]: Adding item {0} {1} from folder {2} linked from {3}", | ||||
| //                                            link.Name, (AssetType)link.AssetType, item.AssetID, containingFolder.Name); | ||||
| 
 | ||||
|                                         InventoryItemBase linkedItem | ||||
|                                             = m_InventoryService.GetItem(new InventoryItemBase(link.AssetID)); | ||||
| 
 | ||||
|                                         if (linkedItem != null) | ||||
|                                             itemsToReturn.Insert(0, linkedItem); | ||||
|                                     } | ||||
|                                 } | ||||
|                             } | ||||
|                         } | ||||
|                     } | ||||
| 
 | ||||
| //                    foreach (InventoryItemBase item in contents.Items) | ||||
| //                    { | ||||
| //                        m_log.DebugFormat( | ||||
| //                            "[WEB FETCH INV DESC HANDLER]: Returning item {0}, type {1}, parent {2} in {3} {4}", | ||||
| //                            item.Name, (AssetType)item.AssetType, item.Folder, containingFolder.Name, containingFolder.ID); | ||||
| //                    } | ||||
| 
 | ||||
|                     // ===== | ||||
| 
 | ||||
| // | ||||
| //                        foreach (InventoryItemBase linkedItem in linkedItemsToAdd) | ||||
| //                        { | ||||
| //                            m_log.DebugFormat( | ||||
| //                                "[WEB FETCH INV DESC HANDLER]: Inserted linked item {0} for link in folder {1} for agent {2}", | ||||
| //                                linkedItem.Name, folderID, agentID); | ||||
| // | ||||
| //                            contents.Items.Add(linkedItem); | ||||
| //                        } | ||||
| // | ||||
| //                        // If the folder requested contains links, then we need to send those folders first, otherwise the links | ||||
| //                        // will be broken in the viewer. | ||||
| //                        HashSet<UUID> linkedItemFolderIdsToSend = new HashSet<UUID>(); | ||||
| //                        foreach (InventoryItemBase item in contents.Items) | ||||
| //                        { | ||||
| //                            if (item.AssetType == (int)AssetType.Link) | ||||
| //                            { | ||||
| //                                InventoryItemBase linkedItem = m_InventoryService.GetItem(new InventoryItemBase(item.AssetID)); | ||||
| // | ||||
| //                                // Take care of genuinely broken links where the target doesn't exist | ||||
| //                                // HACK: Also, don't follow up links that just point to other links.  In theory this is legitimate, | ||||
| //                                // but no viewer has been observed to set these up and this is the lazy way of avoiding cycles | ||||
| //                                // rather than having to keep track of every folder requested in the recursion. | ||||
| //                                if (linkedItem != null && linkedItem.AssetType != (int)AssetType.Link) | ||||
| //                                { | ||||
| //                                    // We don't need to send the folder if source and destination of the link are in the same | ||||
| //                                    // folder. | ||||
| //                                    if (linkedItem.Folder != containingFolder.ID) | ||||
| //                                        linkedItemFolderIdsToSend.Add(linkedItem.Folder); | ||||
| //                                } | ||||
| //                            } | ||||
| //                        } | ||||
| //     | ||||
| //                        foreach (UUID linkedItemFolderId in linkedItemFolderIdsToSend) | ||||
| //                        { | ||||
| //                            m_log.DebugFormat( | ||||
| //                                "[WEB FETCH INV DESC HANDLER]: Recursively fetching folder {0} linked by item in folder {1} for agent {2}", | ||||
| //                                linkedItemFolderId, folderID, agentID); | ||||
| // | ||||
| //                            int dummyVersion; | ||||
| //                            InventoryCollection linkedCollection | ||||
| //                                = Fetch( | ||||
| //                                    agentID, linkedItemFolderId, ownerID, fetchFolders, fetchItems, sortOrder, out dummyVersion); | ||||
| // | ||||
| //                            InventoryFolderBase linkedFolder = new InventoryFolderBase(linkedItemFolderId); | ||||
| //                            linkedFolder.Owner = agentID; | ||||
| //                            linkedFolder = m_InventoryService.GetFolder(linkedFolder); | ||||
| // | ||||
| ////                            contents.Folders.AddRange(linkedCollection.Folders); | ||||
| // | ||||
| //                            contents.Folders.Add(linkedFolder); | ||||
| //                            contents.Items.AddRange(linkedCollection.Items); | ||||
| //                        } | ||||
| //                    } | ||||
|                 } | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 // Lost items don't really need a version | ||||
|                 version = 1; | ||||
|             } | ||||
| 
 | ||||
|             return contents; | ||||
| 
 | ||||
|         } | ||||
|         /// <summary> | ||||
|         /// Convert an internal inventory folder object into an LLSD object. | ||||
|         /// </summary> | ||||
|         /// <param name="invFolder"></param> | ||||
|         /// <returns></returns> | ||||
|         private LLSDInventoryFolder ConvertInventoryFolder(InventoryFolderBase invFolder) | ||||
|         { | ||||
|             LLSDInventoryFolder llsdFolder = new LLSDInventoryFolder(); | ||||
|             llsdFolder.folder_id = invFolder.ID; | ||||
|             llsdFolder.parent_id = invFolder.ParentID; | ||||
|             llsdFolder.name = invFolder.Name; | ||||
|             llsdFolder.type = invFolder.Type; | ||||
|             llsdFolder.preferred_type = -1; | ||||
| 
 | ||||
|             return llsdFolder; | ||||
|         } | ||||
| 
 | ||||
|         /// <summary> | ||||
|         /// Convert an internal inventory item object into an LLSD object. | ||||
|         /// </summary> | ||||
|         /// <param name="invItem"></param> | ||||
|         /// <returns></returns> | ||||
|         private LLSDInventoryItem ConvertInventoryItem(InventoryItemBase invItem) | ||||
|         { | ||||
|             LLSDInventoryItem llsdItem = new LLSDInventoryItem(); | ||||
|             llsdItem.asset_id = invItem.AssetID; | ||||
|             llsdItem.created_at = invItem.CreationDate; | ||||
|             llsdItem.desc = invItem.Description; | ||||
|             llsdItem.flags = (int)invItem.Flags; | ||||
|             llsdItem.item_id = invItem.ID; | ||||
|             llsdItem.name = invItem.Name; | ||||
|             llsdItem.parent_id = invItem.Folder; | ||||
|             llsdItem.type = invItem.AssetType; | ||||
|             llsdItem.inv_type = invItem.InvType; | ||||
| 
 | ||||
|             llsdItem.permissions = new LLSDPermissions(); | ||||
|             llsdItem.permissions.creator_id = invItem.CreatorIdAsUuid; | ||||
|             llsdItem.permissions.base_mask = (int)invItem.CurrentPermissions; | ||||
|             llsdItem.permissions.everyone_mask = (int)invItem.EveryOnePermissions; | ||||
|             llsdItem.permissions.group_id = invItem.GroupID; | ||||
|             llsdItem.permissions.group_mask = (int)invItem.GroupPermissions; | ||||
|             llsdItem.permissions.is_owner_group = invItem.GroupOwned; | ||||
|             llsdItem.permissions.next_owner_mask = (int)invItem.NextPermissions; | ||||
|             llsdItem.permissions.owner_id = invItem.Owner; | ||||
|             llsdItem.permissions.owner_mask = (int)invItem.CurrentPermissions; | ||||
|             llsdItem.sale_info = new LLSDSaleInfo(); | ||||
|             llsdItem.sale_info.sale_price = invItem.SalePrice; | ||||
|             llsdItem.sale_info.sale_type = invItem.SaleType; | ||||
| 
 | ||||
|             return llsdItem; | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | @ -29,22 +29,19 @@ using System; | |||
| using Nini.Config; | ||||
| using OpenSim.Server.Base; | ||||
| using OpenSim.Services.Interfaces; | ||||
| using OpenSim.Framework; | ||||
| using OpenSim.Framework.Servers.HttpServer; | ||||
| using OpenSim.Server.Handlers.Base; | ||||
| using OpenMetaverse; | ||||
| using OpenMetaverse.StructuredData; | ||||
| 
 | ||||
| 
 | ||||
| namespace OpenSim.Capabilities.Handlers | ||||
| { | ||||
|     public class FetchInvDescServerConnector : ServiceConnector | ||||
|     public class WebFetchInvDescServerConnector : ServiceConnector | ||||
|     { | ||||
|         private IInventoryService m_InventoryService; | ||||
|         private ILibraryService m_LibraryService; | ||||
|         private string m_ConfigName = "CapsService"; | ||||
| 
 | ||||
|         public FetchInvDescServerConnector(IConfigSource config, IHttpServer server, string configName) : | ||||
|         public WebFetchInvDescServerConnector(IConfigSource config, IHttpServer server, string configName) : | ||||
|                 base(config, server, configName) | ||||
|         { | ||||
|             if (configName != String.Empty) | ||||
|  | @ -70,16 +67,16 @@ namespace OpenSim.Capabilities.Handlers | |||
|             m_LibraryService = | ||||
|                     ServerUtils.LoadPlugin<ILibraryService>(libService, args); | ||||
| 
 | ||||
|             ExpiringKey<UUID> m_badRequests = new ExpiringKey<UUID>(30000); | ||||
| 
 | ||||
|             FetchInvDescHandler webFetchHandler = new FetchInvDescHandler(m_InventoryService, m_LibraryService, null); | ||||
|             ISimpleStreamHandler reqHandler | ||||
|                 = new SimpleStreamHandler("/CAPS/WebFetchInvDesc/", delegate(IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) | ||||
|                 {  | ||||
|                     webFetchHandler.FetchInventoryDescendentsRequest(httpRequest, httpResponse, m_badRequests); | ||||
|                 }); | ||||
| 
 | ||||
|             server.AddSimpleStreamHandler(reqHandler); | ||||
|             WebFetchInvDescHandler webFetchHandler = new WebFetchInvDescHandler(m_InventoryService, m_LibraryService); | ||||
|             IRequestHandler reqHandler | ||||
|                 = new RestStreamHandler( | ||||
|                     "POST", | ||||
|                     "/CAPS/WebFetchInvDesc/" /*+ UUID.Random()*/, | ||||
|                     webFetchHandler.FetchInventoryDescendentsRequest, | ||||
|                     "WebFetchInvDesc", | ||||
|                     null); | ||||
|             server.AddStreamHandler(reqHandler); | ||||
|         } | ||||
| 
 | ||||
|     } | ||||
| } | ||||
|  | @ -107,17 +107,17 @@ namespace OpenSim.Framework.Capabilities | |||
|         /// <returns></returns> | ||||
|         public static byte[] LLSDSerialize(object obj) | ||||
|         { | ||||
|             using(StringWriter sw = new StringWriter()) | ||||
|             using(XmlTextWriter writer = new XmlTextWriter(sw)) | ||||
|             { | ||||
|                 writer.Formatting = Formatting.None; | ||||
|             StringWriter sw = new StringWriter(); | ||||
|             XmlTextWriter writer = new XmlTextWriter(sw); | ||||
|             writer.Formatting = Formatting.None; | ||||
| 
 | ||||
|                 writer.WriteStartElement(String.Empty, "llsd", String.Empty); | ||||
|                 LLSDWriteOne(writer, obj); | ||||
|                 writer.WriteEndElement(); | ||||
|                 writer.Flush(); | ||||
|                 return Util.UTF8.GetBytes(sw.ToString()); | ||||
|             }            | ||||
|             writer.WriteStartElement(String.Empty, "llsd", String.Empty); | ||||
|             LLSDWriteOne(writer, obj); | ||||
|             writer.WriteEndElement(); | ||||
| 
 | ||||
|             writer.Close(); | ||||
| 
 | ||||
|             return Util.UTF8.GetBytes(sw.ToString()); | ||||
|         } | ||||
| 
 | ||||
|         /// <summary> | ||||
|  | @ -566,7 +566,7 @@ namespace OpenSim.Framework.Capabilities | |||
|                         endPos = FindEnd(llsd, 1); | ||||
| 
 | ||||
|                         if (Double.TryParse(llsd.Substring(1, endPos - 1), NumberStyles.Float, | ||||
|                                             Culture.NumberFormatInfo, out value)) | ||||
|                                             Utils.EnUsCulture.NumberFormat, out value)) | ||||
|                             return value; | ||||
|                         else | ||||
|                             throw new LLSDParseException("Failed to parse double value type"); | ||||
|  |  | |||
|  | @ -30,20 +30,13 @@ using OpenMetaverse; | |||
| 
 | ||||
| namespace OpenSim.Framework.Capabilities | ||||
| { | ||||
| 
 | ||||
|     [LLSDType("MAP")] | ||||
|     public class LLSDAssetUploadComplete | ||||
|     { | ||||
|         public string new_asset = String.Empty; | ||||
|         public UUID new_inventory_item = UUID.Zero; | ||||
| //        public UUID new_texture_folder_id = UUID.Zero; | ||||
|         public string state = String.Empty; | ||||
|         public LLSDAssetUploadError error = null; | ||||
|         //public bool success = false; | ||||
|         public int new_next_owner_mask = 0; | ||||
|         public int new_group_mask = 0; | ||||
|         public int new_everyone_mask = 0; | ||||
|         public int inventory_item_flags = 0; | ||||
| 
 | ||||
|         public LLSDAssetUploadComplete() | ||||
|         { | ||||
|  |  | |||
|  | @ -30,28 +30,15 @@ using OpenMetaverse; | |||
| 
 | ||||
| namespace OpenSim.Framework.Capabilities | ||||
| { | ||||
|     [OSDMap] | ||||
|     public class LLSDAssetResource | ||||
|     { | ||||
|         public OSDArray instance_list = new OSDArray(); | ||||
|         public OSDArray texture_list = new OSDArray(); | ||||
|         public OSDArray mesh_list = new OSDArray(); | ||||
|         public string metric = String.Empty; | ||||
|     } | ||||
| 
 | ||||
|     [OSDMap] | ||||
|     public class LLSDAssetUploadRequest | ||||
|     { | ||||
|         public string asset_type = String.Empty; | ||||
|         public string description = String.Empty; | ||||
|         public UUID folder_id = UUID.Zero; | ||||
|         public UUID texture_folder_id = UUID.Zero; | ||||
|         public int next_owner_mask = 0; | ||||
|         public int group_mask = 0; | ||||
|         public int everyone_mask = 0; | ||||
|         public string inventory_type = String.Empty; | ||||
|         public string name = String.Empty; | ||||
|         public LLSDAssetResource asset_resources = new LLSDAssetResource(); | ||||
| 
 | ||||
|         public LLSDAssetUploadRequest() | ||||
|         { | ||||
|         } | ||||
|  |  | |||
|  | @ -26,51 +26,20 @@ | |||
|  */ | ||||
| 
 | ||||
| using System; | ||||
| using OpenMetaverse; | ||||
| 
 | ||||
| namespace OpenSim.Framework.Capabilities | ||||
| { | ||||
|     [OSDMap] | ||||
|     public class LLSDAssetUploadError | ||||
|     { | ||||
|         public string message = String.Empty; | ||||
|         public UUID identifier = UUID.Zero; | ||||
|     } | ||||
| 
 | ||||
|     [OSDMap] | ||||
|     public class LLSDAssetUploadResponsePricebrkDown | ||||
|     { | ||||
|         public int mesh_streaming; | ||||
|         public int mesh_physics; | ||||
|         public int mesh_instance; | ||||
|         public int texture; | ||||
|         public int model; | ||||
|     } | ||||
| 
 | ||||
|     [OSDMap] | ||||
|     public class LLSDAssetUploadResponseData | ||||
|     { | ||||
|         public double resource_cost; | ||||
|         public double model_streaming_cost; | ||||
|         public double simulation_cost; | ||||
|         public double physics_cost; | ||||
|         public LLSDAssetUploadResponsePricebrkDown upload_price_breakdown = new LLSDAssetUploadResponsePricebrkDown(); | ||||
|     } | ||||
| 
 | ||||
|     [OSDMap] | ||||
|     public class LLSDAssetUploadResponse | ||||
|     { | ||||
|         public string uploader = String.Empty; | ||||
|         public string state = String.Empty; | ||||
|         public int upload_price = 0; | ||||
|         public LLSDAssetUploadResponseData data = null; | ||||
|         public LLSDAssetUploadError error = null; | ||||
| 
 | ||||
|         public LLSDAssetUploadResponse() | ||||
|         { | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     [OSDMap] | ||||
|     public class LLSDNewFileAngentInventoryVariablePriceReplyResponse | ||||
|     { | ||||
|  | @ -78,7 +47,7 @@ namespace OpenSim.Framework.Capabilities | |||
|         public string state; | ||||
|         public int upload_price; | ||||
|         public string rsvp; | ||||
| 
 | ||||
|          | ||||
|         public LLSDNewFileAngentInventoryVariablePriceReplyResponse() | ||||
|         { | ||||
|             state = "confirm_upload"; | ||||
|  |  | |||
|  | @ -42,7 +42,7 @@ namespace OpenSim.Framework.Capabilities | |||
|     { | ||||
|         public string username; | ||||
|         public string display_name; | ||||
|         //'display_name_next_update':d"1970-01-01T00:00:00Z" | ||||
|         //'display_name_next_update':d"1970-01-01T00:00:00Z"  | ||||
|         public string legacy_first_name; | ||||
|         public string legacy_last_name; | ||||
|         public UUID id; | ||||
|  |  | |||
|  | @ -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); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
| } | ||||
|  | @ -30,7 +30,6 @@ using System.Collections; | |||
| using System.IO; | ||||
| using System.Reflection; | ||||
| using System.Xml; | ||||
| using OpenMetaverse; | ||||
| 
 | ||||
| namespace OpenSim.Framework.Capabilities | ||||
| { | ||||
|  | @ -41,32 +40,17 @@ namespace OpenSim.Framework.Capabilities | |||
| 
 | ||||
|         public static string SerialiseLLSDReply(object obj) | ||||
|         { | ||||
|             using(StringWriter sw = new StringWriter()) | ||||
|             using(XmlTextWriter writer = new XmlTextWriter(sw)) | ||||
|             { | ||||
|                 writer.Formatting = Formatting.None; | ||||
|                 writer.WriteStartElement(String.Empty, "llsd", String.Empty); | ||||
|                 SerializeOSDType(writer, obj); | ||||
|                 writer.WriteEndElement(); | ||||
|                 writer.Flush(); | ||||
|             StringWriter sw = new StringWriter(); | ||||
|             XmlTextWriter writer = new XmlTextWriter(sw); | ||||
|             writer.Formatting = Formatting.None; | ||||
|             writer.WriteStartElement(String.Empty, "llsd", String.Empty); | ||||
|             SerializeOSDType(writer, obj); | ||||
|             writer.WriteEndElement(); | ||||
|             writer.Close(); | ||||
| 
 | ||||
|             //m_log.DebugFormat("[LLSD Helpers]: Generated serialized LLSD reply {0}", sw.ToString()); | ||||
| 
 | ||||
|                 return sw.ToString(); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         public static string SerialiseLLSDReplyNoHeader(object obj) | ||||
|         { | ||||
|             using(StringWriter sw = new StringWriter()) | ||||
|             using(XmlTextWriter writer = new XmlTextWriter(sw)) | ||||
|             { | ||||
|                 writer.Formatting = Formatting.None; | ||||
|                 SerializeOSDType(writer, obj); | ||||
|                 writer.Flush(); | ||||
|             //m_log.DebugFormat("[LLSD Helpers]: Generated serialized LLSD reply {0}", sw.ToString()); | ||||
| 
 | ||||
|                 return sw.ToString(); | ||||
|             } | ||||
|             return sw.ToString(); | ||||
|         } | ||||
| 
 | ||||
|         private static void SerializeOSDType(XmlTextWriter writer, object obj) | ||||
|  | @ -173,22 +157,6 @@ namespace OpenSim.Framework.Capabilities | |||
|                                     // the LLSD map/array types in the array need to be deserialised | ||||
|                                     // but first we need to know the right class to deserialise them into. | ||||
|                                 } | ||||
|                                 else if(enumerator.Value is Boolean && field.FieldType == typeof(int) ) | ||||
|                                 { | ||||
|                                     int i = (bool)enumerator.Value ? 1 : 0; | ||||
|                                     field.SetValue(obj, i); | ||||
|                                 } | ||||
|                                 else if(field.FieldType == typeof(bool) &&  enumerator.Value is int) | ||||
|                                 { | ||||
|                                     bool b = (int)enumerator.Value != 0; | ||||
|                                     field.SetValue(obj, b); | ||||
|                                 } | ||||
|                                 else if(field.FieldType == typeof(UUID) &&  enumerator.Value is string) | ||||
|                                 { | ||||
|                                     UUID u; | ||||
|                                     UUID.TryParse((string)enumerator.Value, out u); | ||||
|                                     field.SetValue(obj, u); | ||||
|                                 } | ||||
|                                 else | ||||
|                                 { | ||||
|                                     field.SetValue(obj, enumerator.Value); | ||||
|  |  | |||
|  | @ -37,6 +37,5 @@ namespace OpenSim.Framework.Capabilities | |||
|         public string name; | ||||
|         public int type; | ||||
|         public int preferred_type; | ||||
|         public int version; | ||||
|     } | ||||
| } | ||||
|  |  | |||
|  | @ -87,12 +87,12 @@ namespace OpenSim.Framework.Capabilities | |||
|     [OSDMap] | ||||
|     public class LLSDInventoryFolderContents | ||||
|     { | ||||
|         public UUID agent_id; | ||||
|         public UUID agent_id;  | ||||
|         public int descendents; | ||||
|         public UUID folder_id; | ||||
|         public UUID folder_id;  | ||||
|         public OSDArray categories = new OSDArray(); | ||||
|         public OSDArray items = new OSDArray(); | ||||
|         public UUID owner_id; | ||||
|         public UUID owner_id;  | ||||
|         public int version; | ||||
|     } | ||||
| 
 | ||||
|  |  | |||
|  | @ -25,11 +25,17 @@ | |||
|  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||
|  */ | ||||
| 
 | ||||
| using OpenSim.Region.Framework.Scenes; | ||||
| using OpenMetaverse; | ||||
| 
 | ||||
| public interface IUserAccountCacheModule | ||||
| namespace OpenSim.Framework.Capabilities | ||||
| { | ||||
|     void Remove(string name); | ||||
|     void Remove(UUID id); | ||||
|     [OSDMap] | ||||
|     public class LLSDItemUpdate | ||||
|     { | ||||
|         public UUID item_id; | ||||
| 
 | ||||
|         public LLSDItemUpdate() | ||||
|         { | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | @ -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; | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | @ -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() | ||||
|         { | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | @ -61,9 +61,6 @@ namespace OpenSim.Framework.Capabilities | |||
|             //    OpenMetaverse.StructuredData.LLSDParser.DeserializeXml(new XmlTextReader(request)); | ||||
| 
 | ||||
|             Hashtable hash = (Hashtable) LLSD.LLSDDeserialize(request); | ||||
|             if(hash == null) | ||||
|                 return new byte[0]; | ||||
| 
 | ||||
|             TRequest llsdRequest = new TRequest(); | ||||
|             LLSDHelpers.DeserialiseOSDMap(hash, llsdRequest); | ||||
| 
 | ||||
|  |  | |||
|  | @ -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; | ||||
|     } | ||||
| } | ||||
|  | @ -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; | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | @ -2,7 +2,7 @@ | |||
| using System.Runtime.CompilerServices; | ||||
| using System.Runtime.InteropServices; | ||||
| 
 | ||||
| // General Information about an assembly is controlled through the following | ||||
| // General Information about an assembly is controlled through the following  | ||||
| // set of attributes. Change these attribute values to modify the information | ||||
| // associated with an assembly. | ||||
| [assembly: AssemblyTitle("OpenSim.Capabilities")] | ||||
|  | @ -14,8 +14,8 @@ using System.Runtime.InteropServices; | |||
| [assembly: AssemblyTrademark("")] | ||||
| [assembly: AssemblyCulture("")] | ||||
| 
 | ||||
| // Setting ComVisible to false makes the types in this assembly not visible | ||||
| // to COM components.  If you need to access a type in this assembly from | ||||
| // Setting ComVisible to false makes the types in this assembly not visible  | ||||
| // to COM components.  If you need to access a type in this assembly from  | ||||
| // COM, set the ComVisible attribute to true on that type. | ||||
| [assembly: ComVisible(false)] | ||||
| 
 | ||||
|  | @ -25,7 +25,7 @@ using System.Runtime.InteropServices; | |||
| // Version information for an assembly consists of the following four values: | ||||
| // | ||||
| //      Major Version | ||||
| //      Minor Version | ||||
| //      Minor Version  | ||||
| //      Build Number | ||||
| //      Revision | ||||
| // | ||||
|  |  | |||
|  | @ -80,7 +80,7 @@ namespace OpenSim.ConsoleClient | |||
|             while (m_Server.Running) | ||||
|             { | ||||
|                 System.Threading.Thread.Sleep(500); | ||||
|                 MainConsole.Instance.Prompt(); | ||||
|                 // MainConsole.Instance.Prompt(); | ||||
|             } | ||||
| 
 | ||||
|             if (pidFile != String.Empty) | ||||
|  | @ -178,7 +178,7 @@ namespace OpenSim.ConsoleClient | |||
|                 Requester.MakeRequest(requestUrl, requestData, ReadResponses); | ||||
|                 return; | ||||
|             } | ||||
| 
 | ||||
|              | ||||
|             List<string> lines = new List<string>(); | ||||
| 
 | ||||
|             foreach (XmlNode part in rootNodeL[0].ChildNodes) | ||||
|  | @ -202,7 +202,7 @@ namespace OpenSim.ConsoleClient | |||
|                 string[] parts = l.Split(new char[] {':'}, 3); | ||||
|                 if (parts.Length != 3) | ||||
|                     continue; | ||||
| 
 | ||||
|                  | ||||
|                 if (parts[2].StartsWith("+++") || parts[2].StartsWith("-++")) | ||||
|                     prompt = parts[2]; | ||||
|                 else | ||||
|  |  | |||
|  | @ -2,7 +2,7 @@ | |||
| using System.Runtime.CompilerServices; | ||||
| using System.Runtime.InteropServices; | ||||
| 
 | ||||
| // General Information about an assembly is controlled through the following | ||||
| // General Information about an assembly is controlled through the following  | ||||
| // set of attributes. Change these attribute values to modify the information | ||||
| // associated with an assembly. | ||||
| [assembly: AssemblyTitle("OpenSim.ConsoleClient")] | ||||
|  | @ -14,8 +14,8 @@ using System.Runtime.InteropServices; | |||
| [assembly: AssemblyTrademark("")] | ||||
| [assembly: AssemblyCulture("")] | ||||
| 
 | ||||
| // Setting ComVisible to false makes the types in this assembly not visible | ||||
| // to COM components.  If you need to access a type in this assembly from | ||||
| // Setting ComVisible to false makes the types in this assembly not visible  | ||||
| // to COM components.  If you need to access a type in this assembly from  | ||||
| // COM, set the ComVisible attribute to true on that type. | ||||
| [assembly: ComVisible(false)] | ||||
| 
 | ||||
|  | @ -25,7 +25,7 @@ using System.Runtime.InteropServices; | |||
| // Version information for an assembly consists of the following four values: | ||||
| // | ||||
| //      Major Version | ||||
| //      Minor Version | ||||
| //      Minor Version  | ||||
| //      Build Number | ||||
| //      Revision | ||||
| // | ||||
|  |  | |||
|  | @ -37,7 +37,7 @@ namespace OpenSim.Data | |||
|     public abstract class AssetDataBase : IAssetDataPlugin | ||||
|     { | ||||
|         public abstract AssetBase GetAsset(UUID uuid); | ||||
|         public abstract bool StoreAsset(AssetBase asset); | ||||
|         public abstract void StoreAsset(AssetBase asset); | ||||
|         public abstract bool[] AssetsExist(UUID[] uuids); | ||||
| 
 | ||||
|         public abstract List<AssetMetadata> FetchAssetMetadataSet(int start, int count); | ||||
|  |  | |||
|  | @ -38,7 +38,7 @@ namespace OpenSim.Data | |||
|         /// <summary>This function converts a value returned from the database in one of the | ||||
|         /// supported formats into a UUID.  This function is not actually DBMS-specific right | ||||
|         /// now | ||||
|         /// | ||||
|         ///  | ||||
|         /// </summary> | ||||
|         /// <param name="id"></param> | ||||
|         /// <returns></returns> | ||||
|  | @ -47,25 +47,24 @@ namespace OpenSim.Data | |||
|             if ((id == null) || (id == DBNull.Value)) | ||||
|                 return UUID.Zero; | ||||
| 
 | ||||
|             Type idtype = id.GetType(); | ||||
| 
 | ||||
|             if (idtype == typeof(Guid)) | ||||
|             if (id.GetType() == typeof(Guid)) | ||||
|                 return new UUID((Guid)id); | ||||
| 
 | ||||
|             if (id.GetType() == typeof(string)) | ||||
|             if (id.GetType() == typeof(byte[])) | ||||
|             { | ||||
|                 Guid gg;  | ||||
|                 if (Guid.TryParse((string)id, out gg)) | ||||
|                     return new UUID(gg); | ||||
|                 return UUID.Zero; | ||||
|                 if (((byte[])id).Length == 0) | ||||
|                     return UUID.Zero; | ||||
|                 else if (((byte[])id).Length == 16) | ||||
|                     return new UUID((byte[])id, 0); | ||||
|             } | ||||
|             else if (id.GetType() == typeof(string)) | ||||
|             { | ||||
|                 if (((string)id).Length == 0) | ||||
|                     return UUID.Zero; | ||||
|                 else if (((string)id).Length == 36) | ||||
|                     return new UUID((string)id); | ||||
|             } | ||||
| 
 | ||||
|             if (idtype == typeof(byte[])) | ||||
|             { | ||||
|                 if (((byte[])id).Length < 16) | ||||
|                     return UUID.Zero; | ||||
|                 return new UUID((byte[])id, 0); | ||||
|             } | ||||
|             throw new Exception("Failed to convert db value to UUID: " + id.ToString()); | ||||
|         } | ||||
|     } | ||||
|  |  | |||
|  | @ -34,7 +34,7 @@ namespace OpenSim.Data | |||
|     public interface IAssetDataPlugin : IPlugin | ||||
|     { | ||||
|         AssetBase GetAsset(UUID uuid); | ||||
|         bool StoreAsset(AssetBase asset); | ||||
|         void StoreAsset(AssetBase asset); | ||||
|         bool[] AssetsExist(UUID[] uuids); | ||||
|         List<AssetMetadata> FetchAssetMetadataSet(int start, int count); | ||||
|         void Initialise(string connect); | ||||
|  |  | |||
|  | @ -39,7 +39,7 @@ namespace OpenSim.Data | |||
|         public Dictionary<string, string> Data; | ||||
|     } | ||||
| 
 | ||||
|     public interface IAvatarData | ||||
|     public interface IAvatarData  | ||||
|     { | ||||
|         AvatarBaseData[] Get(string field, string val); | ||||
|         bool Store(AvatarBaseData data); | ||||
|  |  | |||
|  | @ -46,14 +46,14 @@ namespace OpenSim.Data | |||
|         /// <param name="create">If true, then an estate is created if one is not found.</param> | ||||
|         /// <returns></returns> | ||||
|         EstateSettings LoadEstateSettings(UUID regionID, bool create); | ||||
| 
 | ||||
|          | ||||
|         /// <summary> | ||||
|         /// Load estate settings for an estate ID. | ||||
|         /// </summary> | ||||
|         /// <param name="estateID"></param> | ||||
|         /// <returns></returns> | ||||
|         EstateSettings LoadEstateSettings(int estateID); | ||||
| 
 | ||||
|          | ||||
|         /// <summary> | ||||
|         /// Create a new estate. | ||||
|         /// </summary> | ||||
|  | @ -67,7 +67,7 @@ namespace OpenSim.Data | |||
|         /// </summary> | ||||
|         /// <returns>An empty list if no estates were found.</returns> | ||||
|         List<EstateSettings> LoadEstateSettingsAll(); | ||||
| 
 | ||||
|          | ||||
|         /// <summary> | ||||
|         /// Store estate settings. | ||||
|         /// </summary> | ||||
|  | @ -75,7 +75,7 @@ namespace OpenSim.Data | |||
|         /// This is also called by EstateSettings.Save()</remarks> | ||||
|         /// <param name="es"></param> | ||||
|         void StoreEstateSettings(EstateSettings es); | ||||
| 
 | ||||
|          | ||||
|         /// <summary> | ||||
|         /// Get estate IDs. | ||||
|         /// </summary> | ||||
|  | @ -88,13 +88,13 @@ namespace OpenSim.Data | |||
|         /// </summary> | ||||
|         /// <returns>An empty list if no estates were found.</returns> | ||||
|         List<int> GetEstatesByOwner(UUID ownerID); | ||||
| 
 | ||||
|          | ||||
|         /// <summary> | ||||
|         /// Get the IDs of all estates. | ||||
|         /// </summary> | ||||
|         /// <returns>An empty list if no estates were found.</returns> | ||||
|         List<int> GetEstatesAll(); | ||||
| 
 | ||||
|          | ||||
|         /// <summary> | ||||
|         /// Link a region to an estate. | ||||
|         /// </summary> | ||||
|  | @ -102,14 +102,14 @@ namespace OpenSim.Data | |||
|         /// <param name="estateID"></param> | ||||
|         /// <returns>true if the link succeeded, false otherwise</returns> | ||||
|         bool LinkRegion(UUID regionID, int estateID); | ||||
| 
 | ||||
|          | ||||
|         /// <summary> | ||||
|         /// Get the UUIDs of all the regions in an estate. | ||||
|         /// </summary> | ||||
|         /// <param name="estateID"></param> | ||||
|         /// <returns></returns> | ||||
|         List<UUID> GetRegions(int estateID); | ||||
| 
 | ||||
|          | ||||
|         /// <summary> | ||||
|         /// Delete an estate | ||||
|         /// </summary> | ||||
|  |  | |||
|  | @ -1,47 +0,0 @@ | |||
| /* | ||||
|  * Copyright (c) Contributors, http://opensimulator.org/ | ||||
|  * See CONTRIBUTORS.TXT for a full list of copyright holders. | ||||
|  * | ||||
|  * Redistribution and use in source and binary forms, with or without | ||||
|  * modification, are permitted provided that the following conditions are met: | ||||
|  *     * Redistributions of source code must retain the above copyright | ||||
|  *       notice, this list of conditions and the following disclaimer. | ||||
|  *     * Redistributions in binary form must reproduce the above copyright | ||||
|  *       notice, this list of conditions and the following disclaimer in the | ||||
|  *       documentation and/or other materials provided with the distribution. | ||||
|  *     * Neither the name of the OpenSimulator Project nor the | ||||
|  *       names of its contributors may be used to endorse or promote products | ||||
|  *       derived from this software without specific prior written permission. | ||||
|  * | ||||
|  * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY | ||||
|  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | ||||
|  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||||
|  * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY | ||||
|  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | ||||
|  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||||
|  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | ||||
|  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||||
|  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||||
|  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||
|  */ | ||||
| 
 | ||||
| using System.Collections.Generic; | ||||
| using OpenMetaverse; | ||||
| using OpenSim.Framework; | ||||
| 
 | ||||
| namespace OpenSim.Data | ||||
| { | ||||
|     public delegate string FSStoreDelegate(AssetBase asset, bool force); | ||||
| 
 | ||||
|     public interface IFSAssetDataPlugin : IPlugin | ||||
|     { | ||||
|         bool[]          AssetsExist(UUID[] uuids); | ||||
|         void            Initialise(string connect, string realm, int SkipAccessTimeDays); | ||||
|         bool            Delete(string id); | ||||
| 
 | ||||
|         AssetMetadata   Get(string id, out string hash); | ||||
|         bool            Store(AssetMetadata metadata, string hash); | ||||
|         void            Import(string conn, string table, int start, int count, bool force, FSStoreDelegate store); | ||||
|         int             Count(); | ||||
|     } | ||||
| } | ||||
|  | @ -47,7 +47,7 @@ namespace OpenSim.Data | |||
|     /// <summary> | ||||
|     /// An interface for connecting to the user grid datastore | ||||
|     /// </summary> | ||||
|     public interface IGridUserData | ||||
|     public interface IGridUserData  | ||||
|     { | ||||
|         GridUserData Get(string userID); | ||||
|         GridUserData[] GetAll(string query); | ||||
|  |  | |||
|  | @ -81,7 +81,7 @@ namespace OpenSim.Data | |||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     public interface IGroupsData | ||||
|     public interface IGroupsData  | ||||
|     { | ||||
|         // groups table | ||||
|         bool StoreGroup(GroupData data); | ||||
|  |  | |||
|  | @ -48,7 +48,7 @@ namespace OpenSim.Data | |||
|     /// <summary> | ||||
|     /// An interface for connecting to the user grid datastore | ||||
|     /// </summary> | ||||
|     public interface IHGTravelingData | ||||
|     public interface IHGTravelingData  | ||||
|     { | ||||
|         HGTravelingData Get(UUID sessionID); | ||||
|         HGTravelingData[] GetSessions(UUID userID); | ||||
|  |  | |||
|  | @ -39,7 +39,7 @@ namespace OpenSim.Data | |||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     public interface IOfflineIMData | ||||
|     public interface IOfflineIMData  | ||||
|     { | ||||
|         OfflineIMData[] Get(string field, string val); | ||||
|         long GetCount(string field, string key); | ||||
|  |  | |||
|  | @ -44,7 +44,7 @@ namespace OpenSim.Data | |||
|     /// <summary> | ||||
|     /// An interface for connecting to the presence datastore | ||||
|     /// </summary> | ||||
|     public interface IPresenceData | ||||
|     public interface IPresenceData  | ||||
|     { | ||||
|         bool Store(PresenceData data); | ||||
| 
 | ||||
|  |  | |||
|  | @ -48,7 +48,7 @@ namespace OpenSim.Data | |||
|         bool UpdateAvatarProperties(ref UserProfileProperties props, ref string result); | ||||
|         bool UpdateAvatarInterests(UserProfileProperties up, ref string result); | ||||
|         bool GetClassifiedInfo(ref UserClassifiedAdd ad, ref string result); | ||||
|         bool UpdateUserPreferences(ref UserPreferences pref, ref string result); | ||||
|         bool UpdateUserPreferences(ref UserPreferences pref,  ref string result); | ||||
|         bool GetUserPreferences(ref UserPreferences pref, ref string result); | ||||
|         bool GetUserAppData(ref UserAppData props, ref string result); | ||||
|         bool SetUserAppData(UserAppData props, ref string result); | ||||
|  |  | |||
|  | @ -67,12 +67,10 @@ namespace OpenSim.Data | |||
|     /// <summary> | ||||
|     /// An interface for connecting to the authentication datastore | ||||
|     /// </summary> | ||||
|     public interface IRegionData | ||||
|     public interface IRegionData  | ||||
|     { | ||||
|         RegionData Get(UUID regionID, UUID ScopeID); | ||||
|         List<RegionData> Get(string regionName, UUID ScopeID); | ||||
|         RegionData GetSpecific(string regionName, UUID ScopeID); | ||||
| 
 | ||||
|         RegionData Get(int x, int y, UUID ScopeID); | ||||
|         List<RegionData> Get(int xStart, int yStart, int xEnd, int yEnd, UUID ScopeID); | ||||
| 
 | ||||
|  |  | |||
|  | @ -50,6 +50,5 @@ namespace OpenSim.Data | |||
|         bool Store(UserAccountData data); | ||||
|         bool Delete(string field, string val); | ||||
|         UserAccountData[] GetUsers(UUID scopeID, string query); | ||||
|         UserAccountData[] GetUsersWhere(UUID scopeID, string where); | ||||
|     } | ||||
| } | ||||
|  |  | |||
|  | @ -38,12 +38,12 @@ namespace OpenSim.Data | |||
|         public UUID ownerRoleID; | ||||
|         public string name; | ||||
|         public string charter; | ||||
|         public bool showInList; | ||||
|         public UUID insigniaID; | ||||
|         public bool showInList;  | ||||
|         public UUID insigniaID;  | ||||
|         public int membershipFee; | ||||
|         public bool openEnrollment; | ||||
|         public bool allowPublish; | ||||
|         public bool maturePublish; | ||||
|         public bool maturePublish;  | ||||
|         public UUID founderID; | ||||
|         public ulong everyonePowers; | ||||
|         public ulong ownersPowers; | ||||
|  |  | |||
|  | @ -80,10 +80,10 @@ namespace OpenSim.Data | |||
| 
 | ||||
|         /// <summary>Have the parameterless constructor just so we can specify it as a generic parameter with the new() constraint. | ||||
|         /// Currently this is only used in the tests. A Migration instance created this way must be then | ||||
|         /// initialized with Initialize(). Regular creation should be through the parameterized constructors. | ||||
|         /// initialized with Initialize(). Regular creation should be through the parameterized constructors.  | ||||
|         /// </summary> | ||||
|         public Migration() | ||||
|         { | ||||
|         {  | ||||
|         } | ||||
| 
 | ||||
|         public Migration(DbConnection conn, Assembly assem, string subtype, string type) | ||||
|  | @ -91,7 +91,7 @@ namespace OpenSim.Data | |||
|             Initialize(conn, assem, type, subtype); | ||||
|         } | ||||
| 
 | ||||
|         public Migration(DbConnection conn, Assembly assem, string type) | ||||
|         public Migration(DbConnection conn, Assembly assem, string type)  | ||||
|         { | ||||
|             Initialize(conn, assem, type, ""); | ||||
|         } | ||||
|  | @ -191,7 +191,7 @@ namespace OpenSim.Data | |||
|                 int newversion = kvp.Key; | ||||
|                 // we need to up the command timeout to infinite as we might be doing long migrations. | ||||
| 
 | ||||
|                 /* [AlexRa 01-May-10]: We can't always just run any SQL in a single batch (= ExecuteNonQuery()). Things like | ||||
|                 /* [AlexRa 01-May-10]: We can't always just run any SQL in a single batch (= ExecuteNonQuery()). Things like  | ||||
|                  * stored proc definitions might have to be sent to the server each in a separate batch. | ||||
|                  * This is certainly so for MS SQL; not sure how the MySQL connector sorts out the mess | ||||
|                  * with 'delimiter @@'/'delimiter ;' around procs.  So each "script" this code executes now is not | ||||
|  | @ -276,7 +276,7 @@ namespace OpenSim.Data | |||
|         private delegate void FlushProc(); | ||||
| 
 | ||||
|         /// <summary>Scans for migration resources in either old-style "scattered" (one file per version) | ||||
|         /// or new-style "integrated" format (single file with ":VERSION nnn" sections). | ||||
|         /// or new-style "integrated" format (single file with ":VERSION nnn" sections).  | ||||
|         /// In the new-style migrations it also recognizes ':GO' separators for parts of the SQL script | ||||
|         /// that must be sent to the server separately.  The old-style migrations are loaded each in one piece | ||||
|         /// and don't support the ':GO' feature. | ||||
|  | @ -301,12 +301,12 @@ namespace OpenSim.Data | |||
|             { | ||||
|                 /* The filename should be '<StoreName>.migrations[.NNN]' where NNN | ||||
|                  * is the last version number defined in the file. If the '.NNN' part is recognized, the code can skip | ||||
|                  * the file without looking inside if we have a higher version already. Without the suffix we read | ||||
|                  * the file without looking inside if we have a higher version already. Without the suffix we read  | ||||
|                  * the file anyway and use the version numbers inside.  Any unrecognized suffix (such as '.sql') | ||||
|                  * is valid but ignored. | ||||
|                  * | ||||
|                  *  NOTE that we expect only one 'merged' migration file. If there are several, we take the last one. | ||||
|                  *  If you are numbering them, leave only the latest one in the project or at least make sure they numbered | ||||
|                  *  | ||||
|                  *  NOTE that we expect only one 'merged' migration file. If there are several, we take the last one.  | ||||
|                  *  If you are numbering them, leave only the latest one in the project or at least make sure they numbered  | ||||
|                  *  to come up in the correct order (e.g. 'SomeStore.migrations.001' rather than 'SomeStore.migrations.1') | ||||
|                  */ | ||||
| 
 | ||||
|  | @ -351,7 +351,7 @@ namespace OpenSim.Data | |||
|                         if (sLine.Trim().Equals(":GO", StringComparison.InvariantCultureIgnoreCase)) | ||||
|                         { | ||||
|                             if (sb.Length == 0) continue; | ||||
|                             if (nVersion > after) | ||||
|                             if (nVersion > after)  | ||||
|                                 script.Add(sb.ToString()); | ||||
|                             sb.Length = 0; | ||||
|                             continue; | ||||
|  | @ -405,10 +405,10 @@ scan_old_style: | |||
|                     } | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|             if (migrations.Count < 1) | ||||
|              | ||||
|             if (migrations.Count < 1)  | ||||
|                 m_log.DebugFormat("[MIGRATIONS]: {0} data tables already up to date at revision {1}", _type, after); | ||||
| 
 | ||||
|              | ||||
|             return migrations; | ||||
|         } | ||||
|     } | ||||
|  |  | |||
|  | @ -75,7 +75,6 @@ namespace OpenSim.Data.MySQL | |||
|                 dbcon.Open(); | ||||
|                 Migration m = new Migration(dbcon, Assembly, "AssetStore"); | ||||
|                 m.Update(); | ||||
|                 dbcon.Close(); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|  | @ -145,7 +144,6 @@ namespace OpenSim.Data.MySQL | |||
|                             string.Format("[ASSETS DB]: MySql failure fetching asset {0}.  Exception  ", assetID), e); | ||||
|                     } | ||||
|                 } | ||||
|                 dbcon.Close(); | ||||
|             } | ||||
| 
 | ||||
|             return asset; | ||||
|  | @ -156,62 +154,65 @@ namespace OpenSim.Data.MySQL | |||
|         /// </summary> | ||||
|         /// <param name="asset">Asset UUID to create</param> | ||||
|         /// <remarks>On failure : Throw an exception and attempt to reconnect to database</remarks> | ||||
|         override public bool StoreAsset(AssetBase asset) | ||||
|         override public void StoreAsset(AssetBase asset) | ||||
|         { | ||||
|             string assetName = asset.Name; | ||||
|             if (asset.Name.Length > AssetBase.MAX_ASSET_NAME) | ||||
|             { | ||||
|                 assetName = asset.Name.Substring(0, AssetBase.MAX_ASSET_NAME); | ||||
|                 m_log.WarnFormat( | ||||
|                     "[ASSET DB]: Name '{0}' for asset {1} truncated from {2} to {3} characters on add", | ||||
|                     asset.Name, asset.ID, asset.Name.Length, assetName.Length); | ||||
|             } | ||||
| 
 | ||||
|             string assetDescription = asset.Description; | ||||
|             if (asset.Description.Length > AssetBase.MAX_ASSET_DESC) | ||||
|             { | ||||
|                 assetDescription = asset.Description.Substring(0, AssetBase.MAX_ASSET_DESC); | ||||
|                 m_log.WarnFormat( | ||||
|                     "[ASSET DB]: Description '{0}' for asset {1} truncated from {2} to {3} characters on add", | ||||
|                     asset.Description, asset.ID, asset.Description.Length, assetDescription.Length); | ||||
|             } | ||||
| 
 | ||||
|             using (MySqlConnection dbcon = new MySqlConnection(m_connectionString)) | ||||
|             { | ||||
|                 dbcon.Open(); | ||||
| 
 | ||||
|                 using (MySqlCommand cmd = | ||||
|                     new MySqlCommand( | ||||
|                         "replace INTO assets(id, name, description, assetType, local, temporary, create_time, access_time, asset_flags, CreatorID, data)" + | ||||
|                         "VALUES(?id, ?name, ?description, ?assetType, ?local, ?temporary, ?create_time, ?access_time, ?asset_flags, ?CreatorID, ?data)", | ||||
|                         dbcon)) | ||||
|                 { | ||||
|                     string assetName = asset.Name; | ||||
|                     if (asset.Name.Length > AssetBase.MAX_ASSET_NAME) | ||||
|                     { | ||||
|                         assetName = asset.Name.Substring(0, AssetBase.MAX_ASSET_NAME); | ||||
|                         m_log.WarnFormat( | ||||
|                             "[ASSET DB]: Name '{0}' for asset {1} truncated from {2} to {3} characters on add",  | ||||
|                             asset.Name, asset.ID, asset.Name.Length, assetName.Length); | ||||
|                     } | ||||
| 
 | ||||
|                     string assetDescription = asset.Description; | ||||
|                     if (asset.Description.Length > AssetBase.MAX_ASSET_DESC) | ||||
|                     { | ||||
|                         assetDescription = asset.Description.Substring(0, AssetBase.MAX_ASSET_DESC); | ||||
|                         m_log.WarnFormat( | ||||
|                             "[ASSET DB]: Description '{0}' for asset {1} truncated from {2} to {3} characters on add",  | ||||
|                             asset.Description, asset.ID, asset.Description.Length, assetDescription.Length); | ||||
|                     } | ||||
| 
 | ||||
|                     try | ||||
|                     { | ||||
|                         // create unix epoch time | ||||
|                         int now = (int)Utils.DateTimeToUnixTime(DateTime.UtcNow); | ||||
|                         cmd.Parameters.AddWithValue("?id", asset.ID); | ||||
|                         cmd.Parameters.AddWithValue("?name", assetName); | ||||
|                         cmd.Parameters.AddWithValue("?description", assetDescription); | ||||
|                         cmd.Parameters.AddWithValue("?assetType", asset.Type); | ||||
|                         cmd.Parameters.AddWithValue("?local", asset.Local); | ||||
|                         cmd.Parameters.AddWithValue("?temporary", asset.Temporary); | ||||
|                         cmd.Parameters.AddWithValue("?create_time", now); | ||||
|                         cmd.Parameters.AddWithValue("?access_time", now); | ||||
|                         cmd.Parameters.AddWithValue("?CreatorID", asset.Metadata.CreatorID); | ||||
|                         cmd.Parameters.AddWithValue("?asset_flags", (int)asset.Flags); | ||||
|                         cmd.Parameters.AddWithValue("?data", asset.Data); | ||||
|                         cmd.ExecuteNonQuery(); | ||||
|                         dbcon.Close(); | ||||
|                         return true; | ||||
|                         using (cmd) | ||||
|                         { | ||||
|                             // create unix epoch time | ||||
|                             int now = (int)Utils.DateTimeToUnixTime(DateTime.UtcNow); | ||||
|                             cmd.Parameters.AddWithValue("?id", asset.ID); | ||||
|                             cmd.Parameters.AddWithValue("?name", assetName); | ||||
|                             cmd.Parameters.AddWithValue("?description", assetDescription); | ||||
|                             cmd.Parameters.AddWithValue("?assetType", asset.Type); | ||||
|                             cmd.Parameters.AddWithValue("?local", asset.Local); | ||||
|                             cmd.Parameters.AddWithValue("?temporary", asset.Temporary); | ||||
|                             cmd.Parameters.AddWithValue("?create_time", now); | ||||
|                             cmd.Parameters.AddWithValue("?access_time", now); | ||||
|                             cmd.Parameters.AddWithValue("?CreatorID", asset.Metadata.CreatorID); | ||||
|                             cmd.Parameters.AddWithValue("?asset_flags", (int)asset.Flags); | ||||
|                             cmd.Parameters.AddWithValue("?data", asset.Data); | ||||
|                             cmd.ExecuteNonQuery(); | ||||
|                         } | ||||
|                     } | ||||
|                     catch (Exception e) | ||||
|                     { | ||||
|                         m_log.ErrorFormat("[ASSET DB]: MySQL failure creating asset {0} with name \"{1}\". Error: {2}", | ||||
|                             asset.FullID, asset.Name, e.Message); | ||||
|                         dbcon.Close(); | ||||
|                         return false; | ||||
|                         m_log.Error( | ||||
|                             string.Format( | ||||
|                                 "[ASSET DB]: MySQL failure creating asset {0} with name {1}.  Exception  ", | ||||
|                                 asset.FullID, asset.Name) | ||||
|                             , e); | ||||
|                     } | ||||
|                 }                | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|  | @ -226,22 +227,24 @@ namespace OpenSim.Data.MySQL | |||
|                 { | ||||
|                     try | ||||
|                     { | ||||
|                         // create unix epoch time | ||||
|                         int now = (int)Utils.DateTimeToUnixTime(DateTime.UtcNow); | ||||
|                         cmd.Parameters.AddWithValue("?id", asset.ID); | ||||
|                         cmd.Parameters.AddWithValue("?access_time", now); | ||||
|                         cmd.ExecuteNonQuery(); | ||||
|                         using (cmd) | ||||
|                         { | ||||
|                             // create unix epoch time | ||||
|                             int now = (int)Utils.DateTimeToUnixTime(DateTime.UtcNow); | ||||
|                             cmd.Parameters.AddWithValue("?id", asset.ID); | ||||
|                             cmd.Parameters.AddWithValue("?access_time", now); | ||||
|                             cmd.ExecuteNonQuery(); | ||||
|                         } | ||||
|                     } | ||||
|                     catch (Exception e) | ||||
|                     { | ||||
|                         m_log.Error( | ||||
|                             string.Format( | ||||
|                                 "[ASSETS DB]: Failure updating access_time for asset {0} with name {1}.  Exception  ", | ||||
|                                 asset.FullID, asset.Name), | ||||
|                                 "[ASSETS DB]: Failure updating access_time for asset {0} with name {1}.  Exception  ",  | ||||
|                                 asset.FullID, asset.Name),  | ||||
|                             e); | ||||
|                     } | ||||
|                 } | ||||
|                 dbcon.Close(); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|  | @ -274,7 +277,6 @@ namespace OpenSim.Data.MySQL | |||
|                         } | ||||
|                     } | ||||
|                 } | ||||
|                 dbcon.Close(); | ||||
|             } | ||||
| 
 | ||||
|             bool[] results = new bool[uuids.Length]; | ||||
|  | @ -334,12 +336,11 @@ namespace OpenSim.Data.MySQL | |||
|                     { | ||||
|                         m_log.Error( | ||||
|                             string.Format( | ||||
|                                 "[ASSETS DB]: MySql failure fetching asset set from {0}, count {1}.  Exception  ", | ||||
|                                 start, count), | ||||
|                                 "[ASSETS DB]: MySql failure fetching asset set from {0}, count {1}.  Exception  ",  | ||||
|                                 start, count),  | ||||
|                             e); | ||||
|                     } | ||||
|                 } | ||||
|                 dbcon.Close(); | ||||
|             } | ||||
| 
 | ||||
|             return retList; | ||||
|  | @ -356,7 +357,6 @@ namespace OpenSim.Data.MySQL | |||
|                     cmd.Parameters.AddWithValue("?id", id); | ||||
|                     cmd.ExecuteNonQuery(); | ||||
|                 } | ||||
|                 dbcon.Close(); | ||||
|             } | ||||
| 
 | ||||
|             return true; | ||||
|  | @ -364,4 +364,4 @@ namespace OpenSim.Data.MySQL | |||
| 
 | ||||
|         #endregion | ||||
|     } | ||||
| } | ||||
| } | ||||
|  | @ -59,7 +59,6 @@ namespace OpenSim.Data.MySQL | |||
|                 dbcon.Open(); | ||||
|                 Migration m = new Migration(dbcon, Assembly, "AuthStore"); | ||||
|                 m.Update(); | ||||
|                 dbcon.Close(); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|  | @ -77,30 +76,27 @@ namespace OpenSim.Data.MySQL | |||
|                 { | ||||
|                     cmd.Parameters.AddWithValue("?principalID", principalID.ToString()); | ||||
| 
 | ||||
|                     using(IDataReader result = cmd.ExecuteReader()) | ||||
|                     IDataReader result = cmd.ExecuteReader(); | ||||
|      | ||||
|                     if (result.Read()) | ||||
|                     { | ||||
|                          if(result.Read()) | ||||
|                         ret.PrincipalID = principalID; | ||||
|      | ||||
|                         CheckColumnNames(result); | ||||
|      | ||||
|                         foreach (string s in m_ColumnNames) | ||||
|                         { | ||||
|                             ret.PrincipalID = principalID; | ||||
| 
 | ||||
|                             CheckColumnNames(result); | ||||
| 
 | ||||
|                             foreach(string s in m_ColumnNames) | ||||
|                             { | ||||
|                                 if(s == "UUID") | ||||
|                                     continue; | ||||
| 
 | ||||
|                                 ret.Data[s] = result[s].ToString(); | ||||
|                             } | ||||
| 
 | ||||
|                             dbcon.Close(); | ||||
|                             return ret; | ||||
|                         } | ||||
|                         else | ||||
|                         { | ||||
|                             dbcon.Close(); | ||||
|                             return null; | ||||
|                             if (s == "UUID") | ||||
|                                 continue; | ||||
|      | ||||
|                             ret.Data[s] = result[s].ToString(); | ||||
|                         } | ||||
|      | ||||
|                         return ret; | ||||
|                     } | ||||
|                     else | ||||
|                     { | ||||
|                         return null; | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|  | @ -136,25 +132,25 @@ namespace OpenSim.Data.MySQL | |||
|                     if (!first) | ||||
|                         update += ", "; | ||||
|                     update += "`" + field + "` = ?"+field; | ||||
| 
 | ||||
|      | ||||
|                     first = false; | ||||
| 
 | ||||
|      | ||||
|                     cmd.Parameters.AddWithValue("?"+field, data.Data[field]); | ||||
|                 } | ||||
| 
 | ||||
|      | ||||
|                 update += " where UUID = ?principalID"; | ||||
| 
 | ||||
|      | ||||
|                 cmd.CommandText = update; | ||||
|                 cmd.Parameters.AddWithValue("?principalID", data.PrincipalID.ToString()); | ||||
| 
 | ||||
|      | ||||
|                 if (ExecuteNonQuery(cmd) < 1) | ||||
|                 { | ||||
|                     string insert = "insert into `" + m_Realm + "` (`UUID`, `" + | ||||
|                             String.Join("`, `", fields) + | ||||
|                             "`) values (?principalID, ?" + String.Join(", ?", fields) + ")"; | ||||
| 
 | ||||
|      | ||||
|                     cmd.CommandText = insert; | ||||
| 
 | ||||
|      | ||||
|                     if (ExecuteNonQuery(cmd) < 1) | ||||
|                         return false; | ||||
|                 } | ||||
|  | @ -170,7 +166,7 @@ namespace OpenSim.Data.MySQL | |||
|             { | ||||
|                 cmd.Parameters.AddWithValue("?"+item, value); | ||||
|                 cmd.Parameters.AddWithValue("?UUID", principalID.ToString()); | ||||
| 
 | ||||
|      | ||||
|                 if (ExecuteNonQuery(cmd) > 0) | ||||
|                     return true; | ||||
|             } | ||||
|  | @ -190,7 +186,7 @@ namespace OpenSim.Data.MySQL | |||
|                 cmd.Parameters.AddWithValue("?principalID", principalID.ToString()); | ||||
|                 cmd.Parameters.AddWithValue("?token", token); | ||||
|                 cmd.Parameters.AddWithValue("?lifetime", lifetime.ToString()); | ||||
| 
 | ||||
|      | ||||
|                 if (ExecuteNonQuery(cmd) > 0) | ||||
|                     return true; | ||||
|             } | ||||
|  |  | |||
|  | @ -57,7 +57,7 @@ namespace OpenSim.Data.MySQL | |||
|                 cmd.CommandText = String.Format("delete from {0} where `PrincipalID` = ?PrincipalID and `Name` = ?Name", m_Realm); | ||||
|                 cmd.Parameters.AddWithValue("?PrincipalID", principalID.ToString()); | ||||
|                 cmd.Parameters.AddWithValue("?Name", name); | ||||
| 
 | ||||
|      | ||||
|                 if (ExecuteNonQuery(cmd) > 0) | ||||
|                     return true; | ||||
|             } | ||||
|  |  | |||
|  | @ -43,7 +43,12 @@ namespace OpenSim.Data.MySQL | |||
|         private static readonly ILog m_log = | ||||
|             LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | ||||
| 
 | ||||
|         private const string m_waitTimeoutSelect = "select @@wait_timeout"; | ||||
| 
 | ||||
|         private string m_connectionString; | ||||
|         private long m_waitTimeout; | ||||
|         private long m_waitTimeoutLeeway = 60 * TimeSpan.TicksPerSecond; | ||||
| //        private long m_lastConnectionUse; | ||||
| 
 | ||||
|         private FieldInfo[] m_Fields; | ||||
|         private Dictionary<string, FieldInfo> m_FieldMap = | ||||
|  | @ -76,13 +81,14 @@ namespace OpenSim.Data.MySQL | |||
|                 m_log.Debug("Exception: password not found in connection string\n" + e.ToString()); | ||||
|             } | ||||
| 
 | ||||
|             GetWaitTimeout(); | ||||
| 
 | ||||
|             using (MySqlConnection dbcon = new MySqlConnection(m_connectionString)) | ||||
|             { | ||||
|                 dbcon.Open(); | ||||
| 
 | ||||
|                 Migration m = new Migration(dbcon, Assembly, "EstateStore"); | ||||
|                 m.Update(); | ||||
|                 dbcon.Close(); | ||||
| 
 | ||||
|                 Type t = typeof(EstateSettings); | ||||
|                 m_Fields = t.GetFields(BindingFlags.NonPublic | | ||||
|  | @ -102,6 +108,33 @@ namespace OpenSim.Data.MySQL | |||
|             get { return new List<string>(m_FieldMap.Keys).ToArray(); } | ||||
|         } | ||||
| 
 | ||||
|         protected void GetWaitTimeout() | ||||
|         { | ||||
|             using (MySqlConnection dbcon = new MySqlConnection(m_connectionString)) | ||||
|             { | ||||
|                 dbcon.Open(); | ||||
| 
 | ||||
|                 using (MySqlCommand cmd = new MySqlCommand(m_waitTimeoutSelect, dbcon)) | ||||
|                 { | ||||
|                     using (MySqlDataReader dbReader = cmd.ExecuteReader(CommandBehavior.SingleRow)) | ||||
|                     { | ||||
|                         if (dbReader.Read()) | ||||
|                         { | ||||
|                             m_waitTimeout | ||||
|                                 = Convert.ToInt32(dbReader["@@wait_timeout"]) * | ||||
|                                 TimeSpan.TicksPerSecond + m_waitTimeoutLeeway; | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
| 
 | ||||
| //                m_lastConnectionUse = DateTime.Now.Ticks; | ||||
| 
 | ||||
|                 m_log.DebugFormat( | ||||
|                     "[REGION DB]: Connection wait timeout {0} seconds", | ||||
|                     m_waitTimeout / TimeSpan.TicksPerSecond); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         public EstateSettings LoadEstateSettings(UUID regionID, bool create) | ||||
|         { | ||||
|             string sql = "select estate_settings." + String.Join(",estate_settings.", FieldList) + | ||||
|  | @ -144,6 +177,7 @@ namespace OpenSim.Data.MySQL | |||
|             using (MySqlConnection dbcon = new MySqlConnection(m_connectionString)) | ||||
|             { | ||||
|                 dbcon.Open(); | ||||
| 
 | ||||
|                 cmd.Connection = dbcon; | ||||
| 
 | ||||
|                 bool found = false; | ||||
|  | @ -171,8 +205,6 @@ namespace OpenSim.Data.MySQL | |||
|                         } | ||||
|                     } | ||||
|                 } | ||||
|                 dbcon.Close(); | ||||
|                 cmd.Connection = null; | ||||
| 
 | ||||
|                 if (!found && create) | ||||
|                 { | ||||
|  | @ -233,7 +265,6 @@ namespace OpenSim.Data.MySQL | |||
| 
 | ||||
|                     es.Save(); | ||||
|                 } | ||||
|                 dbcon.Close(); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|  | @ -266,7 +297,6 @@ namespace OpenSim.Data.MySQL | |||
| 
 | ||||
|                     cmd.ExecuteNonQuery(); | ||||
|                 } | ||||
|                 dbcon.Close(); | ||||
|             } | ||||
| 
 | ||||
|             SaveBanList(es); | ||||
|  | @ -285,7 +315,7 @@ namespace OpenSim.Data.MySQL | |||
| 
 | ||||
|                 using (MySqlCommand cmd = dbcon.CreateCommand()) | ||||
|                 { | ||||
|                     cmd.CommandText = "select *  from estateban where EstateID = ?EstateID"; | ||||
|                     cmd.CommandText = "select bannedUUID from estateban where EstateID = ?EstateID"; | ||||
|                     cmd.Parameters.AddWithValue("?EstateID", es.EstateID); | ||||
| 
 | ||||
|                     using (IDataReader r = cmd.ExecuteReader()) | ||||
|  | @ -293,16 +323,17 @@ namespace OpenSim.Data.MySQL | |||
|                         while (r.Read()) | ||||
|                         { | ||||
|                             EstateBan eb = new EstateBan(); | ||||
|                             eb.BannedUserID = DBGuid.FromDB(r["bannedUUID"]); ; | ||||
| 
 | ||||
|                             UUID uuid = new UUID(); | ||||
|                             UUID.TryParse(r["bannedUUID"].ToString(), out uuid); | ||||
| 
 | ||||
|                             eb.BannedUserID = uuid; | ||||
|                             eb.BannedHostAddress = "0.0.0.0"; | ||||
|                             eb.BannedHostIPMask = "0.0.0.0"; | ||||
|                             eb.BanningUserID = DBGuid.FromDB(r["banningUUID"]); | ||||
|                             eb.BanTime = Convert.ToInt32(r["banTime"]); | ||||
|                             es.AddBan(eb); | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
|                 dbcon.Close(); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|  | @ -321,20 +352,17 @@ namespace OpenSim.Data.MySQL | |||
| 
 | ||||
|                     cmd.Parameters.Clear(); | ||||
| 
 | ||||
|                     cmd.CommandText = "insert into estateban (EstateID, bannedUUID, bannedIp, bannedIpHostMask, bannedNameMask, banningUUID, banTime) values ( ?EstateID, ?bannedUUID, '', '', '', ?banningUUID, ?banTime)"; | ||||
|                     cmd.CommandText = "insert into estateban (EstateID, bannedUUID, bannedIp, bannedIpHostMask, bannedNameMask) values ( ?EstateID, ?bannedUUID, '', '', '' )"; | ||||
| 
 | ||||
|                     foreach (EstateBan b in es.EstateBans) | ||||
|                     { | ||||
|                         cmd.Parameters.AddWithValue("?EstateID", es.EstateID.ToString()); | ||||
|                         cmd.Parameters.AddWithValue("?bannedUUID", b.BannedUserID.ToString()); | ||||
|                         cmd.Parameters.AddWithValue("?banningUUID", b.BanningUserID.ToString()); | ||||
|                         cmd.Parameters.AddWithValue("?banTime", b.BanTime); | ||||
| 
 | ||||
|                         cmd.ExecuteNonQuery(); | ||||
|                         cmd.Parameters.Clear(); | ||||
|                     } | ||||
|                 } | ||||
|                 dbcon.Close(); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|  | @ -364,7 +392,6 @@ namespace OpenSim.Data.MySQL | |||
|                         cmd.Parameters.Clear(); | ||||
|                     } | ||||
|                 } | ||||
|                 dbcon.Close(); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|  | @ -390,7 +417,6 @@ namespace OpenSim.Data.MySQL | |||
|                         } | ||||
|                     } | ||||
|                 } | ||||
|                 dbcon.Close(); | ||||
|             } | ||||
| 
 | ||||
|             return uuids.ToArray(); | ||||
|  | @ -411,19 +437,19 @@ namespace OpenSim.Data.MySQL | |||
|                 return e; | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|          | ||||
|         public List<EstateSettings> LoadEstateSettingsAll() | ||||
|         { | ||||
|             List<EstateSettings> allEstateSettings = new List<EstateSettings>(); | ||||
| 
 | ||||
|             List<EstateSettings> allEstateSettings = new List<EstateSettings>();             | ||||
|              | ||||
|             List<int> allEstateIds = GetEstatesAll(); | ||||
| 
 | ||||
|              | ||||
|             foreach (int estateId in allEstateIds) | ||||
|                 allEstateSettings.Add(LoadEstateSettings(estateId)); | ||||
| 
 | ||||
|              | ||||
|             return allEstateSettings; | ||||
|         } | ||||
| 
 | ||||
|          | ||||
|         public List<int> GetEstatesAll() | ||||
|         { | ||||
|             List<int> result = new List<int>(); | ||||
|  | @ -445,10 +471,11 @@ namespace OpenSim.Data.MySQL | |||
|                         reader.Close(); | ||||
|                     } | ||||
|                 } | ||||
| 
 | ||||
|                 dbcon.Close(); | ||||
|             } | ||||
| 
 | ||||
|             return result; | ||||
|             return result;             | ||||
|         } | ||||
| 
 | ||||
|         public List<int> GetEstates(string search) | ||||
|  | @ -473,6 +500,7 @@ namespace OpenSim.Data.MySQL | |||
|                         reader.Close(); | ||||
|                     } | ||||
|                 } | ||||
| 
 | ||||
|                 dbcon.Close(); | ||||
|             } | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,433 +0,0 @@ | |||
| /* | ||||
|  * Copyright (c) Contributors, http://opensimulator.org/ | ||||
|  * See CONTRIBUTORS.TXT for a full list of copyright holders. | ||||
|  * | ||||
|  * Redistribution and use in source and binary forms, with or without | ||||
|  * modification, are permitted provided that the following conditions are met: | ||||
|  *     * Redistributions of source code must retain the above copyright | ||||
|  *       notice, this list of conditions and the following disclaimer. | ||||
|  *     * Redistributions in binary form must reproduce the above copyright | ||||
|  *       notice, this list of conditions and the following disclaimer in the | ||||
|  *       documentation and/or other materials provided with the distribution. | ||||
|  *     * Neither the name of the OpenSimulator Project nor the | ||||
|  *       names of its contributors may be used to endorse or promote products | ||||
|  *       derived from this software without specific prior written permission. | ||||
|  * | ||||
|  * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY | ||||
|  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | ||||
|  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||||
|  * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY | ||||
|  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | ||||
|  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||||
|  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | ||||
|  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||||
|  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||||
|  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||
|  */ | ||||
| 
 | ||||
| using System; | ||||
| using System.Reflection; | ||||
| using System.Collections.Generic; | ||||
| using System.Data; | ||||
| using OpenSim.Framework; | ||||
| using OpenSim.Framework.Console; | ||||
| using log4net; | ||||
| using MySql.Data.MySqlClient; | ||||
| using OpenMetaverse; | ||||
| 
 | ||||
| namespace OpenSim.Data.MySQL | ||||
| { | ||||
|     public class MySQLFSAssetData : IFSAssetDataPlugin | ||||
|     { | ||||
|         private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | ||||
| 
 | ||||
|         protected string m_ConnectionString; | ||||
|         protected string m_Table; | ||||
| 
 | ||||
|         /// <summary> | ||||
|         /// Number of days that must pass before we update the access time on an asset when it has been fetched | ||||
|         /// Config option to change this is "DaysBetweenAccessTimeUpdates" | ||||
|         /// </summary> | ||||
|         private int DaysBetweenAccessTimeUpdates = 0; | ||||
| 
 | ||||
|         protected virtual Assembly Assembly | ||||
|         { | ||||
|             get { return GetType().Assembly; } | ||||
|         } | ||||
| 
 | ||||
|         public MySQLFSAssetData() | ||||
|         { | ||||
|         } | ||||
| 
 | ||||
|         #region IPlugin Members | ||||
| 
 | ||||
|         public string Version { get { return "1.0.0.0"; } } | ||||
| 
 | ||||
|         // Loads and initialises the MySQL storage plugin and checks for migrations | ||||
|         public void Initialise(string connect, string realm, int UpdateAccessTime) | ||||
|         { | ||||
|             m_ConnectionString = connect; | ||||
|             m_Table = realm; | ||||
| 
 | ||||
|             DaysBetweenAccessTimeUpdates = UpdateAccessTime; | ||||
| 
 | ||||
|             try | ||||
|             { | ||||
|                 using (MySqlConnection conn = new MySqlConnection(m_ConnectionString)) | ||||
|                 { | ||||
|                     conn.Open(); | ||||
|                     Migration m = new Migration(conn, Assembly, "FSAssetStore"); | ||||
|                     m.Update(); | ||||
|                     conn.Close(); | ||||
|                 } | ||||
|             } | ||||
|             catch (MySqlException e) | ||||
|             { | ||||
|                 m_log.ErrorFormat("[FSASSETS]: Can't connect to database: {0}", e.Message.ToString()); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         public void Initialise() | ||||
|         { | ||||
|             throw new NotImplementedException(); | ||||
|         } | ||||
| 
 | ||||
|         public void Dispose() { } | ||||
| 
 | ||||
|         public string Name | ||||
|         { | ||||
|             get { return "MySQL FSAsset storage engine"; } | ||||
|         } | ||||
| 
 | ||||
|         #endregion | ||||
| 
 | ||||
|         private bool ExecuteNonQuery(MySqlCommand cmd) | ||||
|         { | ||||
|             using (MySqlConnection conn = new MySqlConnection(m_ConnectionString)) | ||||
|             { | ||||
|                 try | ||||
|                 { | ||||
|                     conn.Open(); | ||||
|                 } | ||||
|                 catch (MySqlException e) | ||||
|                 { | ||||
|                     m_log.ErrorFormat("[FSASSETS]: Database open failed with {0}", e.ToString()); | ||||
|                     return false; | ||||
|                 } | ||||
| 
 | ||||
|                 cmd.Connection = conn; | ||||
|                 try | ||||
|                 { | ||||
|                     cmd.ExecuteNonQuery(); | ||||
|                 } | ||||
|                 catch (MySqlException e) | ||||
|                 { | ||||
|                     cmd.Connection = null; | ||||
|                     conn.Close(); | ||||
|                     m_log.ErrorFormat("[FSASSETS]: Query {0} failed with {1}", cmd.CommandText, e.ToString()); | ||||
|                     return false; | ||||
|                 } | ||||
|                 conn.Close(); | ||||
|                 cmd.Connection = null; | ||||
|             } | ||||
| 
 | ||||
|             return true; | ||||
|         } | ||||
| 
 | ||||
|         #region IFSAssetDataPlugin Members | ||||
| 
 | ||||
|         public AssetMetadata Get(string id, out string hash) | ||||
|         { | ||||
|             hash = String.Empty; | ||||
| 
 | ||||
|             AssetMetadata meta = new AssetMetadata(); | ||||
| 
 | ||||
|             using (MySqlConnection conn = new MySqlConnection(m_ConnectionString)) | ||||
|             { | ||||
|                 try | ||||
|                 { | ||||
|                     conn.Open(); | ||||
|                 } | ||||
|                 catch (MySqlException e) | ||||
|                 { | ||||
|                     m_log.ErrorFormat("[FSASSETS]: Database open failed with {0}", e.ToString()); | ||||
|                     return null; | ||||
|                 } | ||||
| 
 | ||||
|                 using (MySqlCommand cmd = conn.CreateCommand()) | ||||
|                 { | ||||
|                     cmd.CommandText = String.Format("select id, name, description, type, hash, create_time, asset_flags, access_time from {0} where id = ?id", m_Table); | ||||
|                     cmd.Parameters.AddWithValue("?id", id); | ||||
| 
 | ||||
|                     using (IDataReader reader = cmd.ExecuteReader()) | ||||
|                     { | ||||
|                         if (!reader.Read()) | ||||
|                             return null; | ||||
| 
 | ||||
|                         hash = reader["hash"].ToString(); | ||||
| 
 | ||||
|                         meta.ID = id; | ||||
|                         meta.FullID = new UUID(id); | ||||
| 
 | ||||
|                         meta.Name = reader["name"].ToString(); | ||||
|                         meta.Description = reader["description"].ToString(); | ||||
|                         meta.Type = (sbyte)Convert.ToInt32(reader["type"]); | ||||
|                         meta.ContentType = SLUtil.SLAssetTypeToContentType(meta.Type); | ||||
|                         meta.CreationDate = Util.ToDateTime(Convert.ToInt32(reader["create_time"])); | ||||
|                         meta.Flags = (AssetFlags)Convert.ToInt32(reader["asset_flags"]); | ||||
| 
 | ||||
|                         int AccessTime = Convert.ToInt32(reader["access_time"]); | ||||
|                         UpdateAccessTime(id, AccessTime); | ||||
|                     } | ||||
|                 } | ||||
|                 conn.Close(); | ||||
|             } | ||||
| 
 | ||||
|             return meta; | ||||
|         } | ||||
| 
 | ||||
|         private void UpdateAccessTime(string AssetID, int AccessTime) | ||||
|         { | ||||
|             // Reduce DB work by only updating access time if asset hasn't recently been accessed | ||||
|             // 0 By Default, Config option is "DaysBetweenAccessTimeUpdates" | ||||
|             if (DaysBetweenAccessTimeUpdates > 0 && (DateTime.UtcNow - Utils.UnixTimeToDateTime(AccessTime)).TotalDays < DaysBetweenAccessTimeUpdates) | ||||
|                 return; | ||||
| 
 | ||||
|             using (MySqlConnection conn = new MySqlConnection(m_ConnectionString)) | ||||
|             { | ||||
|                 try | ||||
|                 { | ||||
|                     conn.Open(); | ||||
|                 } | ||||
|                 catch (MySqlException e) | ||||
|                 { | ||||
|                     m_log.ErrorFormat("[FSASSETS]: Database open failed with {0}", e.ToString()); | ||||
|                     return; | ||||
|                 } | ||||
| 
 | ||||
|                 using (MySqlCommand cmd = conn.CreateCommand()) | ||||
|                 { | ||||
|                     cmd.CommandText = String.Format("UPDATE {0} SET `access_time` = UNIX_TIMESTAMP() WHERE `id` = ?id", m_Table); | ||||
|                     cmd.Parameters.AddWithValue("?id", AssetID); | ||||
|                     cmd.ExecuteNonQuery(); | ||||
|                 } | ||||
|                 conn.Close(); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         public bool Store(AssetMetadata meta, string hash) | ||||
|         { | ||||
|             try | ||||
|             { | ||||
|                 string oldhash; | ||||
|                 AssetMetadata existingAsset = Get(meta.ID, out oldhash); | ||||
| 
 | ||||
|                 using (MySqlCommand cmd = new MySqlCommand()) | ||||
|                 { | ||||
|                     cmd.Parameters.AddWithValue("?id", meta.ID); | ||||
|                     cmd.Parameters.AddWithValue("?name", meta.Name); | ||||
|                     cmd.Parameters.AddWithValue("?description", meta.Description); | ||||
| //                    cmd.Parameters.AddWithValue("?type", meta.Type.ToString()); | ||||
|                     cmd.Parameters.AddWithValue("?type", meta.Type); | ||||
|                     cmd.Parameters.AddWithValue("?hash", hash); | ||||
|                     cmd.Parameters.AddWithValue("?asset_flags", meta.Flags); | ||||
| 
 | ||||
|                     if (existingAsset == null) | ||||
|                     { | ||||
|                         cmd.CommandText = String.Format("insert into {0} (id, name, description, type, hash, asset_flags, create_time, access_time) values ( ?id, ?name, ?description, ?type, ?hash, ?asset_flags, UNIX_TIMESTAMP(), UNIX_TIMESTAMP())", m_Table); | ||||
| 
 | ||||
|                         ExecuteNonQuery(cmd); | ||||
| 
 | ||||
|                         return true; | ||||
|                     } | ||||
| 
 | ||||
|                     //cmd.CommandText = String.Format("update {0} set hash = ?hash, access_time = UNIX_TIMESTAMP() where id = ?id", m_Table); | ||||
| 
 | ||||
|                     //ExecuteNonQuery(cmd); | ||||
| 
 | ||||
|                 } | ||||
| 
 | ||||
| //                return false; | ||||
|                 // if the asset already exits | ||||
|                 // assume it was already correctly stored | ||||
|                 // or regions will keep retry. | ||||
|                 return true; | ||||
|             } | ||||
|             catch(Exception e) | ||||
|             { | ||||
|                 m_log.Error("[FSAssets] Failed to store asset with ID " + meta.ID); | ||||
|         m_log.Error(e.ToString()); | ||||
|                 return false; | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         /// <summary> | ||||
|         /// Check if the assets exist in the database. | ||||
|         /// </summary> | ||||
|         /// <param name="uuids">The asset UUID's</param> | ||||
|         /// <returns>For each asset: true if it exists, false otherwise</returns> | ||||
|         public bool[] AssetsExist(UUID[] uuids) | ||||
|         { | ||||
|             if (uuids.Length == 0) | ||||
|                 return new bool[0]; | ||||
| 
 | ||||
|             bool[] results = new bool[uuids.Length]; | ||||
|             for (int i = 0; i < uuids.Length; i++) | ||||
|                 results[i] = false; | ||||
| 
 | ||||
|             HashSet<UUID> exists = new HashSet<UUID>(); | ||||
| 
 | ||||
|             string ids = "'" + string.Join("','", uuids) + "'"; | ||||
|             string sql = string.Format("select id from {1} where id in ({0})", ids, m_Table); | ||||
| 
 | ||||
|             using (MySqlConnection conn = new MySqlConnection(m_ConnectionString)) | ||||
|             { | ||||
|                 try | ||||
|                 { | ||||
|                     conn.Open(); | ||||
|                 } | ||||
|                 catch (MySqlException e) | ||||
|                 { | ||||
|                     m_log.ErrorFormat("[FSASSETS]: Failed to open database: {0}", e.ToString()); | ||||
|                     return results; | ||||
|                 } | ||||
| 
 | ||||
|                 using (MySqlCommand cmd = conn.CreateCommand()) | ||||
|                 { | ||||
|                     cmd.CommandText = sql; | ||||
| 
 | ||||
|                     using (MySqlDataReader dbReader = cmd.ExecuteReader()) | ||||
|                     { | ||||
|                         while (dbReader.Read()) | ||||
|                         { | ||||
|                             UUID id = DBGuid.FromDB(dbReader["ID"]); | ||||
|                             exists.Add(id); | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
|                 conn.Close(); | ||||
|             } | ||||
| 
 | ||||
|             for (int i = 0; i < uuids.Length; i++) | ||||
|                 results[i] = exists.Contains(uuids[i]); | ||||
|             return results; | ||||
|         } | ||||
| 
 | ||||
|         public int Count() | ||||
|         { | ||||
|             int count = 0; | ||||
| 
 | ||||
|             using (MySqlConnection conn = new MySqlConnection(m_ConnectionString)) | ||||
|             { | ||||
|                 try | ||||
|                 { | ||||
|                     conn.Open(); | ||||
|                 } | ||||
|                 catch (MySqlException e) | ||||
|                 { | ||||
|                     m_log.ErrorFormat("[FSASSETS]: Failed to open database: {0}", e.ToString()); | ||||
|                     return 0; | ||||
|                 } | ||||
| 
 | ||||
|                 using(MySqlCommand cmd = conn.CreateCommand()) | ||||
|                 { | ||||
|                     cmd.CommandText = String.Format("select count(*) as count from {0}",m_Table); | ||||
| 
 | ||||
|                     using (IDataReader reader = cmd.ExecuteReader()) | ||||
|                     { | ||||
|                         reader.Read(); | ||||
| 
 | ||||
|                         count = Convert.ToInt32(reader["count"]); | ||||
|                     } | ||||
|                 } | ||||
|                 conn.Close(); | ||||
|             } | ||||
| 
 | ||||
|             return count; | ||||
|         } | ||||
| 
 | ||||
|         public bool Delete(string id) | ||||
|         { | ||||
|             using(MySqlCommand cmd = new MySqlCommand()) | ||||
|             { | ||||
| 
 | ||||
|                 cmd.CommandText = String.Format("delete from {0} where id = ?id",m_Table); | ||||
| 
 | ||||
|                 cmd.Parameters.AddWithValue("?id", id); | ||||
| 
 | ||||
|                 ExecuteNonQuery(cmd); | ||||
|             } | ||||
| 
 | ||||
|             return true; | ||||
|         } | ||||
| 
 | ||||
|         public void Import(string conn, string table, int start, int count, bool force, FSStoreDelegate store) | ||||
|         { | ||||
|             int imported = 0; | ||||
| 
 | ||||
|             using (MySqlConnection importConn = new MySqlConnection(conn)) | ||||
|             { | ||||
|                 try | ||||
|                 { | ||||
|                     importConn.Open(); | ||||
|                 } | ||||
|                 catch (MySqlException e) | ||||
|                 { | ||||
|                     m_log.ErrorFormat("[FSASSETS]: Can't connect to database: {0}", | ||||
|                             e.Message.ToString()); | ||||
| 
 | ||||
|                     return; | ||||
|                 } | ||||
| 
 | ||||
|                 using (MySqlCommand cmd = importConn.CreateCommand()) | ||||
|                 { | ||||
|                     string limit = String.Empty; | ||||
|                     if (count != -1) | ||||
|                     { | ||||
|                         limit = String.Format(" limit {0},{1}", start, count); | ||||
|                     } | ||||
| 
 | ||||
|                     cmd.CommandText = String.Format("select * from {0}{1}", table, limit); | ||||
| 
 | ||||
|                     MainConsole.Instance.Output("Querying database"); | ||||
|                     using (IDataReader reader = cmd.ExecuteReader()) | ||||
|                     { | ||||
|                         MainConsole.Instance.Output("Reading data"); | ||||
| 
 | ||||
|                         while (reader.Read()) | ||||
|                         { | ||||
|                             if ((imported % 100) == 0) | ||||
|                             { | ||||
|                                 MainConsole.Instance.Output(String.Format("{0} assets imported so far", imported)); | ||||
|                             } | ||||
| 
 | ||||
|                             AssetBase asset = new AssetBase(); | ||||
|                             AssetMetadata meta = new AssetMetadata(); | ||||
| 
 | ||||
|                             meta.ID = reader["id"].ToString(); | ||||
|                             meta.FullID = new UUID(meta.ID); | ||||
| 
 | ||||
|                             meta.Name = reader["name"].ToString(); | ||||
|                             meta.Description = reader["description"].ToString(); | ||||
|                             meta.Type = (sbyte)Convert.ToInt32(reader["assetType"]); | ||||
|                             meta.ContentType = SLUtil.SLAssetTypeToContentType(meta.Type); | ||||
|                             meta.CreationDate = Util.ToDateTime(Convert.ToInt32(reader["create_time"])); | ||||
| 
 | ||||
|                             asset.Metadata = meta; | ||||
|                             asset.Data = (byte[])reader["data"]; | ||||
| 
 | ||||
|                             store(asset, force); | ||||
| 
 | ||||
|                             imported++; | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
|                 importConn.Close(); | ||||
|             } | ||||
| 
 | ||||
|             MainConsole.Instance.Output(String.Format("Import done, {0} assets imported", imported)); | ||||
|         } | ||||
| 
 | ||||
|         #endregion | ||||
|     } | ||||
| } | ||||
|  | @ -36,7 +36,7 @@ using MySql.Data.MySqlClient; | |||
| namespace OpenSim.Data.MySQL | ||||
| { | ||||
|     /// <summary> | ||||
|     /// Common code for a number of database modules | ||||
|     /// A database interface class to a user profile storage system | ||||
|     /// </summary> | ||||
|     public class MySqlFramework | ||||
|     { | ||||
|  | @ -44,78 +44,30 @@ namespace OpenSim.Data.MySQL | |||
|                 log4net.LogManager.GetLogger( | ||||
|                 System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); | ||||
| 
 | ||||
|         protected string m_connectionString = String.Empty; | ||||
|         protected MySqlTransaction m_trans = null; | ||||
|         protected string m_connectionString; | ||||
| 
 | ||||
|         // Constructor using a connection string. Instances constructed | ||||
|         // this way will open a new connection for each call. | ||||
|         protected MySqlFramework(string connectionString) | ||||
|         { | ||||
|             m_connectionString = connectionString; | ||||
|         } | ||||
| 
 | ||||
|         // Constructor using a connection object. Instances constructed | ||||
|         // this way will use the connection object and never create | ||||
|         // new connections. | ||||
|         protected MySqlFramework(MySqlTransaction trans) | ||||
|         { | ||||
|             m_trans = trans; | ||||
|         } | ||||
| 
 | ||||
|         ////////////////////////////////////////////////////////////// | ||||
|         // | ||||
|         // All non queries are funneled through one connection | ||||
|         // to increase performance a little | ||||
|         // | ||||
|         protected int ExecuteNonQuery(MySqlCommand cmd) | ||||
|         { | ||||
|             if (m_trans == null) | ||||
|             { | ||||
|                 using (MySqlConnection dbcon = new MySqlConnection(m_connectionString)) | ||||
|                 { | ||||
|                     dbcon.Open(); | ||||
|                     int ret = ExecuteNonQueryWithConnection(cmd, dbcon); | ||||
|                     dbcon.Close(); | ||||
|                     return ret; | ||||
|                 } | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 return ExecuteNonQueryWithTransaction(cmd, m_trans); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         private int ExecuteNonQueryWithTransaction(MySqlCommand cmd, MySqlTransaction trans) | ||||
|         { | ||||
|             cmd.Transaction = trans; | ||||
|             return ExecuteNonQueryWithConnection(cmd, trans.Connection); | ||||
|         } | ||||
| 
 | ||||
|         private int ExecuteNonQueryWithConnection(MySqlCommand cmd, MySqlConnection dbcon) | ||||
|         { | ||||
|             try | ||||
|             using (MySqlConnection dbcon = new MySqlConnection(m_connectionString)) | ||||
|             { | ||||
|                 dbcon.Open(); | ||||
|                 cmd.Connection = dbcon; | ||||
| 
 | ||||
|                 try | ||||
|                 { | ||||
|                     int ret = cmd.ExecuteNonQuery(); | ||||
|                     cmd.Connection = null; | ||||
|                     return ret; | ||||
|                     return cmd.ExecuteNonQuery(); | ||||
|                 } | ||||
|                 catch (Exception e) | ||||
|                 { | ||||
|                     m_log.Error(e.Message, e); | ||||
|                     m_log.Error(Environment.StackTrace.ToString()); | ||||
|                     cmd.Connection = null; | ||||
|                     return 0; | ||||
|                 } | ||||
|             } | ||||
|             catch (Exception e) | ||||
|             { | ||||
|                 m_log.Error(e.Message, e); | ||||
|                 return 0; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
| } | ||||
|  | @ -29,16 +29,18 @@ using System; | |||
| using System.Collections.Generic; | ||||
| using System.Data; | ||||
| using System.Reflection; | ||||
| using System.Text; | ||||
| using log4net; | ||||
| using MySql.Data.MySqlClient; | ||||
| using OpenMetaverse; | ||||
| using OpenSim.Framework; | ||||
| using OpenSim.Region.Framework.Interfaces; | ||||
| 
 | ||||
| namespace OpenSim.Data.MySQL | ||||
| { | ||||
|     public class MySQLGenericTableHandler<T> : MySqlFramework where T: class, new() | ||||
|     { | ||||
| //        private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | ||||
| 
 | ||||
|          | ||||
|         protected Dictionary<string, FieldInfo> m_Fields = | ||||
|                 new Dictionary<string, FieldInfo>(); | ||||
| 
 | ||||
|  | @ -51,27 +53,14 @@ namespace OpenSim.Data.MySQL | |||
|             get { return GetType().Assembly; } | ||||
|         } | ||||
| 
 | ||||
|         public MySQLGenericTableHandler(MySqlTransaction trans, | ||||
|                 string realm, string storeName) : base(trans) | ||||
|         { | ||||
|             m_Realm = realm; | ||||
| 
 | ||||
|             CommonConstruct(storeName); | ||||
|         } | ||||
| 
 | ||||
|         public MySQLGenericTableHandler(string connectionString, | ||||
|                 string realm, string storeName) : base(connectionString) | ||||
|         { | ||||
|             m_Realm = realm; | ||||
| 
 | ||||
|             CommonConstruct(storeName); | ||||
|         } | ||||
| 
 | ||||
|         protected void CommonConstruct(string storeName) | ||||
|         { | ||||
|             m_connectionString = connectionString; | ||||
|              | ||||
|             if (storeName != String.Empty) | ||||
|             { | ||||
|                 // We always use a new connection for any Migrations | ||||
|                 using (MySqlConnection dbcon = new MySqlConnection(m_connectionString)) | ||||
|                 { | ||||
|                     dbcon.Open(); | ||||
|  | @ -116,167 +105,102 @@ namespace OpenSim.Data.MySQL | |||
|         } | ||||
| 
 | ||||
|         public virtual T[] Get(string field, string key) | ||||
|         {    | ||||
|             using (MySqlCommand cmd = new MySqlCommand()) | ||||
|             { | ||||
|                 cmd.Parameters.AddWithValue(field, key); | ||||
|                 cmd.CommandText = string.Format("select * from {0} where `{1}` = ?{1}", m_Realm, field); | ||||
|                 return DoQuery(cmd); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         public virtual T[] Get(string field, string[] keys) | ||||
|         { | ||||
|             int flen = keys.Length; | ||||
|             if(flen == 0) | ||||
|                 return new T[0]; | ||||
| 
 | ||||
|             int flast = flen - 1; | ||||
|             StringBuilder sb = new StringBuilder(1024); | ||||
|             sb.AppendFormat("select * from {0} where {1} IN (?", m_Realm, field); | ||||
|             using (MySqlCommand cmd = new MySqlCommand()) | ||||
|             { | ||||
|                 for (int i = 0 ; i < flen ; i++) | ||||
|                 { | ||||
|                     string fname = field + i.ToString(); | ||||
|                     cmd.Parameters.AddWithValue(fname, keys[i]); | ||||
| 
 | ||||
|                     sb.Append(fname); | ||||
|                     if(i < flast) | ||||
|                         sb.Append(",?"); | ||||
|                     else | ||||
|                         sb.Append(")"); | ||||
|                 } | ||||
|                 cmd.CommandText = sb.ToString(); | ||||
|                 return DoQuery(cmd); | ||||
|             } | ||||
|             return Get(new string[] { field }, new string[] { key }); | ||||
|         } | ||||
| 
 | ||||
|         public virtual T[] Get(string[] fields, string[] keys) | ||||
|         { | ||||
|             return Get(fields, keys, String.Empty); | ||||
|         } | ||||
| 
 | ||||
|         public virtual T[] Get(string[] fields, string[] keys, string options) | ||||
|         { | ||||
|             int flen = fields.Length; | ||||
|             if (flen == 0 || flen != keys.Length) | ||||
|             if (fields.Length != keys.Length) | ||||
|                 return new T[0]; | ||||
| 
 | ||||
|             int flast = flen - 1; | ||||
|             StringBuilder sb = new StringBuilder(1024); | ||||
|             sb.AppendFormat("select * from {0} where ", m_Realm); | ||||
|             List<string> terms = new List<string>(); | ||||
| 
 | ||||
|             using (MySqlCommand cmd = new MySqlCommand()) | ||||
|             { | ||||
|                 for (int i = 0 ; i < flen ; i++) | ||||
|                 for (int i = 0 ; i < fields.Length ; i++) | ||||
|                 { | ||||
|                     cmd.Parameters.AddWithValue(fields[i], keys[i]); | ||||
|                     if(i < flast) | ||||
|                         sb.AppendFormat("`{0}` = ?{0} and ", fields[i]); | ||||
|                     else | ||||
|                         sb.AppendFormat("`{0}` = ?{0} ", fields[i]); | ||||
|                     terms.Add("`" + fields[i] + "` = ?" + fields[i]); | ||||
|                 } | ||||
| 
 | ||||
|                 sb.Append(options); | ||||
|                 cmd.CommandText = sb.ToString(); | ||||
|                 string where = String.Join(" and ", terms.ToArray()); | ||||
| 
 | ||||
|                 string query = String.Format("select * from {0} where {1}", | ||||
|                                              m_Realm, where); | ||||
| 
 | ||||
|                 cmd.CommandText = query; | ||||
|                  | ||||
|                 return DoQuery(cmd); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         protected T[] DoQuery(MySqlCommand cmd) | ||||
|         { | ||||
|             if (m_trans == null) | ||||
|             { | ||||
|                 using (MySqlConnection dbcon = new MySqlConnection(m_connectionString)) | ||||
|                 { | ||||
|                     dbcon.Open(); | ||||
|                     T[] ret = DoQueryWithConnection(cmd, dbcon); | ||||
|                     dbcon.Close(); | ||||
|                     return ret; | ||||
|                 } | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 return DoQueryWithTransaction(cmd, m_trans); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         protected T[] DoQueryWithTransaction(MySqlCommand cmd, MySqlTransaction trans) | ||||
|         { | ||||
|             cmd.Transaction = trans; | ||||
| 
 | ||||
|             return DoQueryWithConnection(cmd, trans.Connection); | ||||
|         } | ||||
| 
 | ||||
|         protected T[] DoQueryWithConnection(MySqlCommand cmd, MySqlConnection dbcon) | ||||
|         { | ||||
|             List<T> result = new List<T>(); | ||||
| 
 | ||||
|             cmd.Connection = dbcon; | ||||
| 
 | ||||
|             using (IDataReader reader = cmd.ExecuteReader()) | ||||
|             using (MySqlConnection dbcon = new MySqlConnection(m_connectionString)) | ||||
|             { | ||||
|                 if (reader == null) | ||||
|                     return new T[0]; | ||||
|                 dbcon.Open(); | ||||
|                 cmd.Connection = dbcon; | ||||
| 
 | ||||
|                 CheckColumnNames(reader); | ||||
| 
 | ||||
|                 while (reader.Read()) | ||||
|                 using (IDataReader reader = cmd.ExecuteReader()) | ||||
|                 { | ||||
|                     T row = new T(); | ||||
|                     if (reader == null) | ||||
|                         return new T[0]; | ||||
| 
 | ||||
|                     foreach (string name in m_Fields.Keys) | ||||
|                     CheckColumnNames(reader); | ||||
| 
 | ||||
|                     while (reader.Read()) | ||||
|                     { | ||||
|                         if (reader[name] is DBNull) | ||||
|                         T row = new T(); | ||||
| 
 | ||||
|                         foreach (string name in m_Fields.Keys) | ||||
|                         { | ||||
|                             continue; | ||||
|                             if (reader[name] is DBNull) | ||||
|                             { | ||||
|                                 continue; | ||||
|                             } | ||||
|                             if (m_Fields[name].FieldType == typeof(bool)) | ||||
|                             { | ||||
|                                 int v = Convert.ToInt32(reader[name]); | ||||
|                                 m_Fields[name].SetValue(row, v != 0 ? true : false); | ||||
|                             } | ||||
|                             else if (m_Fields[name].FieldType == typeof(UUID)) | ||||
|                             { | ||||
|                                 m_Fields[name].SetValue(row, DBGuid.FromDB(reader[name])); | ||||
|                             } | ||||
|                             else if (m_Fields[name].FieldType == typeof(int)) | ||||
|                             { | ||||
|                                 int v = Convert.ToInt32(reader[name]); | ||||
|                                 m_Fields[name].SetValue(row, v); | ||||
|                             } | ||||
|                             else | ||||
|                             { | ||||
|                                 m_Fields[name].SetValue(row, reader[name]); | ||||
|                             } | ||||
|                         } | ||||
|                         if (m_Fields[name].FieldType == typeof(bool)) | ||||
|                  | ||||
|                         if (m_DataField != null) | ||||
|                         { | ||||
|                             int v = Convert.ToInt32(reader[name]); | ||||
|                             m_Fields[name].SetValue(row, v != 0); | ||||
|                         } | ||||
|                         else if (m_Fields[name].FieldType == typeof(UUID)) | ||||
|                         { | ||||
|                             m_Fields[name].SetValue(row, DBGuid.FromDB(reader[name])); | ||||
|                         } | ||||
|                         else if (m_Fields[name].FieldType == typeof(int)) | ||||
|                         { | ||||
|                             int v = Convert.ToInt32(reader[name]); | ||||
|                             m_Fields[name].SetValue(row, v); | ||||
|                         } | ||||
|                         else if (m_Fields[name].FieldType == typeof(uint)) | ||||
|                         { | ||||
|                             uint v = Convert.ToUInt32(reader[name]); | ||||
|                             m_Fields[name].SetValue(row, v); | ||||
|                         } | ||||
|                         else | ||||
|                         { | ||||
|                             m_Fields[name].SetValue(row, reader[name]); | ||||
|                             Dictionary<string, string> data = | ||||
|                                 new Dictionary<string, string>(); | ||||
| 
 | ||||
|                             foreach (string col in m_ColumnNames) | ||||
|                             { | ||||
|                                 data[col] = reader[col].ToString(); | ||||
|                                 if (data[col] == null) | ||||
|                                     data[col] = String.Empty; | ||||
|                             } | ||||
| 
 | ||||
|                             m_DataField.SetValue(row, data); | ||||
|                         } | ||||
| 
 | ||||
|                         result.Add(row); | ||||
|                     } | ||||
| 
 | ||||
|                     if (m_DataField != null) | ||||
|                     { | ||||
|                         Dictionary<string, string> data = | ||||
|                             new Dictionary<string, string>(); | ||||
| 
 | ||||
|                         foreach (string col in m_ColumnNames) | ||||
|                         { | ||||
|                             data[col] = reader[col].ToString(); | ||||
|                             if (data[col] == null) | ||||
|                                 data[col] = String.Empty; | ||||
|                         } | ||||
| 
 | ||||
|                         m_DataField.SetValue(row, data); | ||||
|                     } | ||||
| 
 | ||||
|                     result.Add(row); | ||||
|                 } | ||||
|             } | ||||
|             cmd.Connection = null; | ||||
| 
 | ||||
|             return result.ToArray(); | ||||
|         } | ||||
| 
 | ||||
|  | @ -286,9 +210,9 @@ namespace OpenSim.Data.MySQL | |||
|             { | ||||
|                 string query = String.Format("select * from {0} where {1}", | ||||
|                                              m_Realm, where); | ||||
| 
 | ||||
|                  | ||||
|                 cmd.CommandText = query; | ||||
| 
 | ||||
|                  | ||||
|                 return DoQuery(cmd); | ||||
|             } | ||||
|         } | ||||
|  | @ -307,16 +231,16 @@ namespace OpenSim.Data.MySQL | |||
|                 { | ||||
|                     names.Add(fi.Name); | ||||
|                     values.Add("?" + fi.Name); | ||||
| 
 | ||||
|                      | ||||
|                     // Temporarily return more information about what field is unexpectedly null for | ||||
|                     // http://opensimulator.org/mantis/view.php?id=5403.  This might be due to a bug in the | ||||
|                     // http://opensimulator.org/mantis/view.php?id=5403.  This might be due to a bug in the  | ||||
|                     // InventoryTransferModule or we may be required to substitute a DBNull here. | ||||
|                     if (fi.GetValue(row) == null) | ||||
|                         throw new NullReferenceException( | ||||
|                             string.Format( | ||||
|                                 "[MYSQL GENERIC TABLE HANDLER]: Trying to store field {0} for {1} which is unexpectedly null", | ||||
|                                 "[MYSQL GENERIC TABLE HANDLER]: Trying to store field {0} for {1} which is unexpectedly null",  | ||||
|                                 fi.Name, row)); | ||||
| 
 | ||||
|                      | ||||
|                     cmd.Parameters.AddWithValue(fi.Name, fi.GetValue(row).ToString()); | ||||
|                 } | ||||
| 
 | ||||
|  | @ -355,26 +279,25 @@ namespace OpenSim.Data.MySQL | |||
| //                "[MYSQL GENERIC TABLE HANDLER]: Delete(string[] fields, string[] keys) invoked with {0}:{1}", | ||||
| //                string.Join(",", fields), string.Join(",", keys)); | ||||
| 
 | ||||
|             int flen = fields.Length; | ||||
|             if (flen == 0 || flen != keys.Length) | ||||
|             if (fields.Length != keys.Length) | ||||
|                 return false; | ||||
| 
 | ||||
|             int flast = flen - 1; | ||||
|             StringBuilder sb = new StringBuilder(1024); | ||||
|             sb.AppendFormat("delete from {0} where ", m_Realm); | ||||
|             List<string> terms = new List<string>(); | ||||
| 
 | ||||
|             using (MySqlCommand cmd = new MySqlCommand()) | ||||
|             { | ||||
|                 for (int i = 0 ; i < flen ; i++) | ||||
|                 for (int i = 0 ; i < fields.Length ; i++) | ||||
|                 { | ||||
|                     cmd.Parameters.AddWithValue(fields[i], keys[i]); | ||||
|                     if(i < flast) | ||||
|                         sb.AppendFormat("`{0}` = ?{0} and ", fields[i]); | ||||
|                     else | ||||
|                         sb.AppendFormat("`{0}` = ?{0}", fields[i]); | ||||
|                     terms.Add("`" + fields[i] + "` = ?" + fields[i]); | ||||
|                 } | ||||
| 
 | ||||
|                 cmd.CommandText = sb.ToString(); | ||||
|                 string where = String.Join(" and ", terms.ToArray()); | ||||
| 
 | ||||
|                 string query = String.Format("delete from {0} where {1}", m_Realm, where); | ||||
| 
 | ||||
|                 cmd.CommandText = query; | ||||
| 
 | ||||
|                 return ExecuteNonQuery(cmd) > 0; | ||||
|             } | ||||
|         } | ||||
|  | @ -386,27 +309,27 @@ namespace OpenSim.Data.MySQL | |||
| 
 | ||||
|         public long GetCount(string[] fields, string[] keys) | ||||
|         { | ||||
|             int flen = fields.Length; | ||||
|             if (flen == 0 || flen != keys.Length) | ||||
|             if (fields.Length != keys.Length) | ||||
|                 return 0; | ||||
| 
 | ||||
|             int flast = flen - 1; | ||||
|             StringBuilder sb = new StringBuilder(1024); | ||||
|             sb.AppendFormat("select count(*) from {0} where ", m_Realm); | ||||
|             List<string> terms = new List<string>(); | ||||
| 
 | ||||
|             using (MySqlCommand cmd = new MySqlCommand()) | ||||
|             { | ||||
|                 for (int i = 0 ; i < flen ; i++) | ||||
|                 for (int i = 0; i < fields.Length; i++) | ||||
|                 { | ||||
|                     cmd.Parameters.AddWithValue(fields[i], keys[i]); | ||||
|                     if(i < flast) | ||||
|                         sb.AppendFormat("`{0}` = ?{0} and ", fields[i]); | ||||
|                     else | ||||
|                         sb.AppendFormat("`{0}` = ?{0}", fields[i]); | ||||
|                     terms.Add("`" + fields[i] + "` = ?" + fields[i]); | ||||
|                 } | ||||
| 
 | ||||
|                 cmd.CommandText = sb.ToString(); | ||||
|                 object result = DoQueryScalar(cmd); | ||||
|                 string where = String.Join(" and ", terms.ToArray()); | ||||
| 
 | ||||
|                 string query = String.Format("select count(*) from {0} where {1}", | ||||
|                                              m_Realm, where); | ||||
| 
 | ||||
|                 cmd.CommandText = query; | ||||
| 
 | ||||
|                 Object result = DoQueryScalar(cmd); | ||||
| 
 | ||||
|                 return Convert.ToInt64(result); | ||||
|             } | ||||
|  | @ -429,26 +352,14 @@ namespace OpenSim.Data.MySQL | |||
| 
 | ||||
|         public object DoQueryScalar(MySqlCommand cmd) | ||||
|         { | ||||
|             if (m_trans == null) | ||||
|             using (MySqlConnection dbcon = new MySqlConnection(m_connectionString)) | ||||
|             { | ||||
|                 using (MySqlConnection dbcon = new MySqlConnection(m_connectionString)) | ||||
|                 { | ||||
|                     dbcon.Open(); | ||||
|                     cmd.Connection = dbcon; | ||||
| 
 | ||||
|                     object ret = cmd.ExecuteScalar(); | ||||
|                     cmd.Connection = null; | ||||
|                     dbcon.Close(); | ||||
|                     return ret; | ||||
|                 } | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 cmd.Connection = m_trans.Connection; | ||||
|                 cmd.Transaction = m_trans; | ||||
|                 dbcon.Open(); | ||||
|                 cmd.Connection = dbcon; | ||||
| 
 | ||||
|                 return cmd.ExecuteScalar(); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|     } | ||||
| } | ||||
| } | ||||
|  | @ -90,7 +90,7 @@ namespace OpenSim.Data.MySQL | |||
|             else | ||||
|                 pattern = string.Format("Name LIKE '%{0}%'", MySqlHelper.EscapeString(pattern)); | ||||
| 
 | ||||
|             return m_Groups.Get(string.Format("ShowInList=1 AND ({0})", pattern)); | ||||
|             return m_Groups.Get(string.Format("ShowInList=1 AND ({0}) ORDER BY Name LIMIT 100", pattern)); | ||||
|         } | ||||
| 
 | ||||
|         public bool DeleteGroup(UUID groupID) | ||||
|  | @ -133,10 +133,10 @@ namespace OpenSim.Data.MySQL | |||
| 
 | ||||
|         public bool DeleteMember(UUID groupID, string pricipalID) | ||||
|         { | ||||
|             return m_Membership.Delete(new string[] { "GroupID", "PrincipalID" }, | ||||
|             return m_Membership.Delete(new string[] { "GroupID", "PrincipalID" },  | ||||
|                                        new string[] { groupID.ToString(), pricipalID }); | ||||
|         } | ||||
| 
 | ||||
|          | ||||
|         public int MemberCount(UUID groupID) | ||||
|         { | ||||
|             return (int)m_Membership.GetCount("GroupID", groupID.ToString()); | ||||
|  | @ -168,7 +168,7 @@ namespace OpenSim.Data.MySQL | |||
| 
 | ||||
|         public bool DeleteRole(UUID groupID, UUID roleID) | ||||
|         { | ||||
|             return m_Roles.Delete(new string[] { "GroupID", "RoleID" }, | ||||
|             return m_Roles.Delete(new string[] { "GroupID", "RoleID" },  | ||||
|                                   new string[] { groupID.ToString(), roleID.ToString() }); | ||||
|         } | ||||
| 
 | ||||
|  | @ -360,7 +360,7 @@ namespace OpenSim.Data.MySQL | |||
|             get { return GetType().Assembly; } | ||||
|         } | ||||
| 
 | ||||
|         public MySqlGroupsGroupsHandler(string connectionString, string realm, string store) | ||||
|         public MySqlGroupsGroupsHandler(string connectionString, string realm, string store)  | ||||
|             : base(connectionString, realm, store) | ||||
|         { | ||||
|         } | ||||
|  | @ -375,7 +375,7 @@ namespace OpenSim.Data.MySQL | |||
|             get { return GetType().Assembly; } | ||||
|         } | ||||
| 
 | ||||
|         public MySqlGroupsMembershipHandler(string connectionString, string realm) | ||||
|         public MySqlGroupsMembershipHandler(string connectionString, string realm)  | ||||
|             : base(connectionString, realm, string.Empty) | ||||
|         { | ||||
|         } | ||||
|  | @ -390,7 +390,7 @@ namespace OpenSim.Data.MySQL | |||
|             get { return GetType().Assembly; } | ||||
|         } | ||||
| 
 | ||||
|         public MySqlGroupsRolesHandler(string connectionString, string realm) | ||||
|         public MySqlGroupsRolesHandler(string connectionString, string realm)  | ||||
|             : base(connectionString, realm, string.Empty) | ||||
|         { | ||||
|         } | ||||
|  | @ -405,7 +405,7 @@ namespace OpenSim.Data.MySQL | |||
|             get { return GetType().Assembly; } | ||||
|         } | ||||
| 
 | ||||
|         public MySqlGroupsRoleMembershipHandler(string connectionString, string realm) | ||||
|         public MySqlGroupsRoleMembershipHandler(string connectionString, string realm)  | ||||
|             : base(connectionString, realm, string.Empty) | ||||
|         { | ||||
|         } | ||||
|  | @ -420,7 +420,7 @@ namespace OpenSim.Data.MySQL | |||
|             get { return GetType().Assembly; } | ||||
|         } | ||||
| 
 | ||||
|         public MySqlGroupsInvitesHandler(string connectionString, string realm) | ||||
|         public MySqlGroupsInvitesHandler(string connectionString, string realm)  | ||||
|             : base(connectionString, realm, string.Empty) | ||||
|         { | ||||
|         } | ||||
|  | @ -431,7 +431,8 @@ namespace OpenSim.Data.MySQL | |||
| 
 | ||||
|             using (MySqlCommand cmd = new MySqlCommand()) | ||||
|             { | ||||
|                 cmd.CommandText = String.Format("delete from {0} where TMStamp < NOW() - INTERVAL 2 WEEK", m_Realm); | ||||
|                 cmd.CommandText = String.Format("delete from {0} where TMStamp < ?tstamp", m_Realm); | ||||
|                 cmd.Parameters.AddWithValue("?tstamp", now - 14 * 24 * 60 * 60); // > 2 weeks old | ||||
| 
 | ||||
|                 ExecuteNonQuery(cmd); | ||||
|             } | ||||
|  | @ -447,7 +448,7 @@ namespace OpenSim.Data.MySQL | |||
|             get { return GetType().Assembly; } | ||||
|         } | ||||
| 
 | ||||
|         public MySqlGroupsNoticesHandler(string connectionString, string realm) | ||||
|         public MySqlGroupsNoticesHandler(string connectionString, string realm)  | ||||
|             : base(connectionString, realm, string.Empty) | ||||
|         { | ||||
|         } | ||||
|  | @ -475,7 +476,7 @@ namespace OpenSim.Data.MySQL | |||
|             get { return GetType().Assembly; } | ||||
|         } | ||||
| 
 | ||||
|         public MySqlGroupsPrincipalsHandler(string connectionString, string realm) | ||||
|         public MySqlGroupsPrincipalsHandler(string connectionString, string realm)  | ||||
|             : base(connectionString, realm, string.Empty) | ||||
|         { | ||||
|         } | ||||
|  |  | |||
|  | @ -78,7 +78,6 @@ namespace OpenSim.Data.MySQL | |||
|                 dbcon.Open(); | ||||
|                 Migration m = new Migration(dbcon, assem, "InventoryStore"); | ||||
|                 m.Update(); | ||||
|                 dbcon.Close(); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|  | @ -131,7 +130,6 @@ namespace OpenSim.Data.MySQL | |||
|                                         items.Add(item); | ||||
|                                 } | ||||
| 
 | ||||
|                                 dbcon.Close(); | ||||
|                                 return items; | ||||
|                             } | ||||
|                         } | ||||
|  | @ -172,7 +170,6 @@ namespace OpenSim.Data.MySQL | |||
|                                 while (reader.Read()) | ||||
|                                     items.Add(readInventoryFolder(reader)); | ||||
| 
 | ||||
|                                 dbcon.Close(); | ||||
|                                 return items; | ||||
|                             } | ||||
|                         } | ||||
|  | @ -224,7 +221,6 @@ namespace OpenSim.Data.MySQL | |||
|                                 if (items.Count > 0) | ||||
|                                     rootFolder = items[0]; | ||||
| 
 | ||||
|                                 dbcon.Close(); | ||||
|                                 return rootFolder; | ||||
|                             } | ||||
|                         } | ||||
|  | @ -265,7 +261,6 @@ namespace OpenSim.Data.MySQL | |||
|                                 while (reader.Read()) | ||||
|                                     items.Add(readInventoryFolder(reader)); | ||||
| 
 | ||||
|                                 dbcon.Close(); | ||||
|                                 return items; | ||||
|                             } | ||||
|                         } | ||||
|  | @ -293,7 +288,7 @@ namespace OpenSim.Data.MySQL | |||
|                 // TODO: this is to handle a case where NULLs creep in there, which we are not sure is endemic to the system, or legacy.  It would be nice to live fix these. | ||||
|                 // (DBGuid.FromDB() reads db NULLs as well, returns UUID.Zero) | ||||
|                 item.CreatorId = reader["creatorID"].ToString(); | ||||
| 
 | ||||
|                  | ||||
|                 // Be a bit safer in parsing these because the | ||||
|                 // database doesn't enforce them to be not null, and | ||||
|                 // the inventory still works if these are weird in the | ||||
|  | @ -357,7 +352,6 @@ namespace OpenSim.Data.MySQL | |||
|                                 if (reader.Read()) | ||||
|                                     item = readInventoryItem(reader); | ||||
| 
 | ||||
|                                 dbcon.Close(); | ||||
|                                 return item; | ||||
|                             } | ||||
|                         } | ||||
|  | @ -423,7 +417,6 @@ namespace OpenSim.Data.MySQL | |||
|                                 if (reader.Read()) | ||||
|                                     folder = readInventoryFolder(reader); | ||||
| 
 | ||||
|                                 dbcon.Close(); | ||||
|                                 return folder; | ||||
|                             } | ||||
|                         } | ||||
|  | @ -460,7 +453,7 @@ namespace OpenSim.Data.MySQL | |||
|                 itemName = item.Name.Substring(0, 64); | ||||
|                 m_log.Warn("[INVENTORY DB]: Name field truncated from " + item.Name.Length + " to " + itemName.Length + " characters on add item"); | ||||
|             } | ||||
| 
 | ||||
|              | ||||
|             string itemDesc = item.Description; | ||||
|             if (item.Description.Length > 128) | ||||
|             { | ||||
|  | @ -497,10 +490,10 @@ namespace OpenSim.Data.MySQL | |||
|                         result.Parameters.AddWithValue("?groupID", item.GroupID); | ||||
|                         result.Parameters.AddWithValue("?groupOwned", item.GroupOwned); | ||||
|                         result.Parameters.AddWithValue("?flags", item.Flags); | ||||
| 
 | ||||
|      | ||||
|                         lock (m_dbLock) | ||||
|                             result.ExecuteNonQuery(); | ||||
| 
 | ||||
|      | ||||
|                         result.Dispose(); | ||||
|                     } | ||||
| 
 | ||||
|  | @ -511,7 +504,6 @@ namespace OpenSim.Data.MySQL | |||
|                         lock (m_dbLock) | ||||
|                             result.ExecuteNonQuery(); | ||||
|                     } | ||||
|                     dbcon.Close(); | ||||
|                 } | ||||
|             } | ||||
|             catch (MySqlException e) | ||||
|  | @ -548,7 +540,6 @@ namespace OpenSim.Data.MySQL | |||
|                         lock (m_dbLock) | ||||
|                             cmd.ExecuteNonQuery(); | ||||
|                     } | ||||
|                     dbcon.Close(); | ||||
|                 } | ||||
|             } | ||||
|             catch (MySqlException e) | ||||
|  | @ -609,7 +600,6 @@ namespace OpenSim.Data.MySQL | |||
|                         m_log.Error(e.ToString()); | ||||
|                     } | ||||
|                 } | ||||
|                 dbcon.Close(); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|  | @ -640,7 +630,7 @@ namespace OpenSim.Data.MySQL | |||
|                 { | ||||
|                     cmd.Parameters.AddWithValue("?folderID", folder.ID.ToString()); | ||||
|                     cmd.Parameters.AddWithValue("?parentFolderID", folder.ParentID.ToString()); | ||||
| 
 | ||||
|      | ||||
|                     try | ||||
|                     { | ||||
|                         lock (m_dbLock) | ||||
|  | @ -653,7 +643,6 @@ namespace OpenSim.Data.MySQL | |||
|                         m_log.Error(e.ToString()); | ||||
|                     } | ||||
|                 } | ||||
|                 dbcon.Close(); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|  | @ -817,7 +806,6 @@ namespace OpenSim.Data.MySQL | |||
|                         lock (m_dbLock) | ||||
|                             cmd.ExecuteNonQuery(); | ||||
|                     } | ||||
|                     dbcon.Close(); | ||||
|                 } | ||||
|             } | ||||
|             catch (MySqlException e) | ||||
|  | @ -845,7 +833,6 @@ namespace OpenSim.Data.MySQL | |||
|                         lock (m_dbLock) | ||||
|                             cmd.ExecuteNonQuery(); | ||||
|                     } | ||||
|                     dbcon.Close(); | ||||
|                 } | ||||
|             } | ||||
|             catch (MySqlException e) | ||||
|  | @ -873,7 +860,7 @@ namespace OpenSim.Data.MySQL | |||
|             deleteOneFolder(folderID); | ||||
|             deleteItemsInFolder(folderID); | ||||
|         } | ||||
| 
 | ||||
|          | ||||
|         public List<InventoryItemBase> fetchActiveGestures(UUID avatarID) | ||||
|         { | ||||
|             lock (m_dbLock) | ||||
|  | @ -899,7 +886,6 @@ namespace OpenSim.Data.MySQL | |||
|                                     if (item != null) | ||||
|                                         list.Add(item); | ||||
|                                 } | ||||
|                                 dbcon.Close(); | ||||
|                                 return list; | ||||
|                             } | ||||
|                         } | ||||
|  |  | |||
|  | @ -39,16 +39,16 @@ namespace OpenSim.Data.MySQL | |||
| { | ||||
|     /// <summary>This is a MySQL-customized migration processor.  The only difference is in how | ||||
|     /// it executes SQL scripts (using MySqlScript instead of MyCommand) | ||||
|     /// | ||||
|     ///  | ||||
|     /// </summary> | ||||
|     public class MySqlMigration : Migration | ||||
|     { | ||||
|         public MySqlMigration() | ||||
|             : base() | ||||
|         { | ||||
|         {  | ||||
|         } | ||||
| 
 | ||||
|         public MySqlMigration(DbConnection conn, Assembly assem, string subtype, string type) : | ||||
|         public MySqlMigration(DbConnection conn, Assembly assem, string subtype, string type) :  | ||||
|             base(conn, assem, subtype, type) | ||||
|         { | ||||
|         } | ||||
|  |  | |||
|  | @ -50,7 +50,7 @@ namespace OpenSim.Data.MySQL | |||
|             using (MySqlCommand cmd = new MySqlCommand()) | ||||
|             { | ||||
|                 cmd.CommandText = String.Format("delete from {0} where TMStamp < NOW() - INTERVAL 2 WEEK", m_Realm); | ||||
| 
 | ||||
|           | ||||
|                 ExecuteNonQuery(cmd); | ||||
|             } | ||||
| 
 | ||||
|  |  | |||
Some files were not shown because too many files have changed in this diff Show More
		Loading…
	
		Reference in New Issue