Compare commits
No commits in common. "master" and "inv-download" have entirely different histories.
master
...
inv-downlo
|
@ -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,11 +143,6 @@
|
|||
</exec>
|
||||
<fail message="Failures reported in unit tests." unless="${int::parse(testresult.opensim.services.inventoryservice.tests)==0}" />
|
||||
|
||||
<exec program="${nunitcmd}" failonerror="true" resultproperty="testresult.opensim.tests.permissions">
|
||||
<arg value="./bin/OpenSim.Tests.Permissions.dll" />
|
||||
</exec>
|
||||
<fail message="Failures reported in unit tests." unless="${int::parse(testresult.opensim.tests.permissions)==0}" />
|
||||
|
||||
<delete dir="%temp%"/>
|
||||
</target>
|
||||
|
||||
|
@ -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">
|
||||
|
|
33
BUILDING.md
33
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
|
||||
* Mono >= 2.4.3
|
||||
* Nant >= 0.85
|
||||
* On some Linux distributions you may need to install additional packages.
|
||||
* msbuild or xbuild if still supported by the mono version
|
||||
* See http://opensimulator.org/wiki/Dependencies for more information.
|
||||
See http://opensimulator.org/wiki/Dependencies for more information.
|
||||
* May also use xbuild (included in mono distributions)
|
||||
* May use Monodevelop, a cross-platform IDE
|
||||
|
||||
From the distribution type:
|
||||
|
||||
* ./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,12 @@ 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 +103,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 +111,6 @@ what it is today.
|
|||
* Imaze Rhiano
|
||||
* Intimidated
|
||||
* Jak Daniels
|
||||
* Jeff Kelly
|
||||
* Jeremy Bongio (IBM)
|
||||
* jhurliman
|
||||
* John R Sohn (XenReborn)
|
||||
|
@ -131,7 +124,6 @@ what it is today.
|
|||
* KittyLiu
|
||||
* Kurt Taylor (IBM)
|
||||
* Lani Global
|
||||
* lickx
|
||||
* lillith_xue
|
||||
* lkalif
|
||||
* LuciusSirnah
|
||||
|
@ -140,18 +132,14 @@ what it is today.
|
|||
* 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 +153,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
|
||||
|
@ -184,21 +170,14 @@ what it is today.
|
|||
* 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
|
@ -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>
|
||||
|
@ -599,16 +599,13 @@ 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
|
||||
, new UUID(msg.fromAgentID)
|
||||
, msg.message
|
||||
, AgentID
|
||||
, msg.fromAgentName
|
||||
|
@ -623,10 +620,14 @@ namespace OpenSim.Groups
|
|||
, 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
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
|
|
|
@ -38,7 +38,7 @@ using OpenSim.Framework;
|
|||
using OpenSim.Region.Framework.Interfaces;
|
||||
using OpenSim.Region.Framework.Scenes;
|
||||
using OpenSim.Services.Interfaces;
|
||||
using PermissionMask = OpenSim.Framework.PermissionMask;
|
||||
using DirFindFlags = OpenMetaverse.DirectoryManager.DirFindFlags;
|
||||
|
||||
namespace OpenSim.Groups
|
||||
{
|
||||
|
@ -127,7 +127,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);
|
||||
}
|
||||
|
||||
public void RegionLoaded(Scene scene)
|
||||
|
@ -137,6 +137,13 @@ namespace OpenSim.Groups
|
|||
|
||||
if (m_debugEnabled) m_log.DebugFormat("[Groups]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
|
||||
|
||||
scene.EventManager.OnNewClient += OnNewClient;
|
||||
scene.EventManager.OnMakeRootAgent += OnMakeRoot;
|
||||
scene.EventManager.OnMakeChildAgent += OnMakeChild;
|
||||
scene.EventManager.OnIncomingInstantMessage += OnGridInstantMessage;
|
||||
// The InstantMessageModule itself doesn't do this,
|
||||
// so lets see if things explode if we don't do it
|
||||
// scene.EventManager.OnClientClosed += OnClientClosed;
|
||||
|
||||
if (m_groupData == null)
|
||||
{
|
||||
|
@ -175,11 +182,6 @@ namespace OpenSim.Groups
|
|||
m_sceneList.Add(scene);
|
||||
}
|
||||
|
||||
scene.EventManager.OnNewClient += OnNewClient;
|
||||
scene.EventManager.OnMakeRootAgent += OnMakeRoot;
|
||||
scene.EventManager.OnMakeChildAgent += OnMakeChild;
|
||||
scene.EventManager.OnIncomingInstantMessage += OnGridInstantMessage;
|
||||
scene.EventManager.OnClientClosed += OnClientClosed;
|
||||
|
||||
}
|
||||
|
||||
|
@ -194,7 +196,6 @@ namespace OpenSim.Groups
|
|||
scene.EventManager.OnMakeRootAgent -= OnMakeRoot;
|
||||
scene.EventManager.OnMakeChildAgent -= OnMakeChild;
|
||||
scene.EventManager.OnIncomingInstantMessage -= OnGridInstantMessage;
|
||||
scene.EventManager.OnClientClosed -= OnClientClosed;
|
||||
|
||||
lock (m_sceneList)
|
||||
{
|
||||
|
@ -233,10 +234,9 @@ namespace OpenSim.Groups
|
|||
if (m_debugEnabled) m_log.DebugFormat("[Groups]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
|
||||
|
||||
client.OnAgentDataUpdateRequest += OnAgentDataUpdateRequest;
|
||||
//client.OnRequestAvatarProperties += OnRequestAvatarProperties;
|
||||
client.OnRequestAvatarProperties += OnRequestAvatarProperties;
|
||||
}
|
||||
|
||||
|
||||
private void OnMakeRoot(ScenePresence sp)
|
||||
{
|
||||
if (m_debugEnabled) m_log.DebugFormat("[Groups]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
|
||||
|
@ -245,12 +245,8 @@ namespace OpenSim.Groups
|
|||
// Used for Notices and Group Invites/Accept/Reject
|
||||
sp.ControllingClient.OnInstantMessage += OnInstantMessage;
|
||||
|
||||
// Send out group data update for compatibility.
|
||||
// There might be some problem with the thread we're generating this on but not
|
||||
// doing the update at this time causes problems (Mantis #7920 and #7915)
|
||||
// TODO: move sending this update to a later time in the rootification of the client.
|
||||
if(!sp.m_haveGroupInformation)
|
||||
SendAgentGroupDataUpdate(sp.ControllingClient, false);
|
||||
// Send client their groups information.
|
||||
SendAgentGroupDataUpdate(sp.ControllingClient, sp.UUID);
|
||||
}
|
||||
|
||||
private void OnMakeChild(ScenePresence sp)
|
||||
|
@ -261,33 +257,28 @@ namespace OpenSim.Groups
|
|||
// Used for Notices and Group Invites/Accept/Reject
|
||||
sp.ControllingClient.OnInstantMessage -= OnInstantMessage;
|
||||
}
|
||||
/*
|
||||
|
||||
private void OnRequestAvatarProperties(IClientAPI remoteClient, UUID avatarID)
|
||||
{
|
||||
if (m_debugEnabled) m_log.DebugFormat("[Groups]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
|
||||
|
||||
//GroupMembershipData[] avatarGroups = m_groupData.GetAgentGroupMemberships(GetRequestingAgentID(remoteClient), avatarID).ToArray();
|
||||
GroupMembershipData[] avatarGroups = GetProfileListedGroupMemberships(remoteClient, avatarID);
|
||||
remoteClient.SendAvatarGroupsReply(avatarID, avatarGroups);
|
||||
}
|
||||
*/
|
||||
private void OnClientClosed(UUID AgentId, Scene scene)
|
||||
{
|
||||
if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
|
||||
if (scene == null)
|
||||
return;
|
||||
|
||||
ScenePresence sp = scene.GetScenePresence(AgentId);
|
||||
IClientAPI client = sp.ControllingClient;
|
||||
if (client != null)
|
||||
{
|
||||
client.OnAgentDataUpdateRequest -= OnAgentDataUpdateRequest;
|
||||
//client.OnRequestAvatarProperties -= OnRequestAvatarProperties;
|
||||
// make child possible not called?
|
||||
client.OnUUIDGroupNameRequest -= HandleUUIDGroupNameRequest;
|
||||
client.OnInstantMessage -= OnInstantMessage;
|
||||
}
|
||||
|
||||
/*
|
||||
* This becomes very problematic in a shared module. In a shared module you may have more then one
|
||||
* reference to IClientAPI's, one for 0 or 1 root connections, and 0 or more child connections.
|
||||
* The OnClientClosed event does not provide anything to indicate which one of those should be closed
|
||||
* nor does it provide what scene it was from so that the specific reference can be looked up.
|
||||
* The InstantMessageModule.cs does not currently worry about unregistering the handles,
|
||||
* and it should be an issue, since it's the client that references us not the other way around
|
||||
* , so as long as we don't keep a reference to the client laying around, the client can still be GC'ed
|
||||
private void OnClientClosed(UUID AgentId)
|
||||
{
|
||||
if (m_debugEnabled) m_log.DebugFormat("[Groups]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
|
||||
|
||||
lock (m_ActiveClients)
|
||||
{
|
||||
if (m_ActiveClients.ContainsKey(AgentId))
|
||||
|
@ -305,22 +296,31 @@ namespace OpenSim.Groups
|
|||
if (m_debugEnabled) m_log.WarnFormat("[Groups]: Client closed that wasn't registered here.");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
}
|
||||
|
||||
private void OnAgentDataUpdateRequest(IClientAPI remoteClient, UUID dataForAgentID, UUID sessionID)
|
||||
{
|
||||
// this a private message for own agent only
|
||||
if (dataForAgentID != GetRequestingAgentID(remoteClient))
|
||||
return;
|
||||
if (m_debugEnabled) m_log.DebugFormat("[Groups]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
|
||||
|
||||
SendAgentGroupDataUpdate(remoteClient, false);
|
||||
UUID activeGroupID = UUID.Zero;
|
||||
string activeGroupTitle = string.Empty;
|
||||
string activeGroupName = string.Empty;
|
||||
ulong activeGroupPowers = (ulong)GroupPowers.None;
|
||||
|
||||
// also current viewers do ignore it and ask later on a much nicer thread
|
||||
// its a info request not a change, so nothing is sent to others
|
||||
// they do get the group title with the avatar object update on arrivel to a region
|
||||
GroupMembershipData membership = m_groupData.GetAgentActiveMembership(GetRequestingAgentIDStr(remoteClient), dataForAgentID.ToString());
|
||||
if (membership != null)
|
||||
{
|
||||
activeGroupID = membership.GroupID;
|
||||
activeGroupTitle = membership.GroupTitle;
|
||||
activeGroupPowers = membership.GroupPowers;
|
||||
}
|
||||
|
||||
SendAgentDataUpdate(remoteClient, dataForAgentID, activeGroupID, activeGroupName, activeGroupPowers, activeGroupTitle);
|
||||
|
||||
SendScenePresenceUpdate(dataForAgentID, activeGroupTitle);
|
||||
}
|
||||
|
||||
private void HandleUUIDGroupNameRequest(UUID GroupID, IClientAPI remoteClient)
|
||||
|
@ -344,24 +344,14 @@ namespace OpenSim.Groups
|
|||
|
||||
private void OnInstantMessage(IClientAPI remoteClient, GridInstantMessage im)
|
||||
{
|
||||
if (m_debugEnabled)
|
||||
m_log.DebugFormat("[Groups]: OnInstantMessage called");
|
||||
|
||||
if(remoteClient == null || !remoteClient.IsActive || remoteClient.AgentId == UUID.Zero)
|
||||
return;
|
||||
|
||||
Scene scene = (Scene)remoteClient.Scene;
|
||||
if (scene == null)
|
||||
return;
|
||||
|
||||
string remoteAgentIDstr = remoteClient.AgentId.ToString();
|
||||
if (m_debugEnabled) m_log.DebugFormat("[Groups]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
|
||||
|
||||
//m_log.DebugFormat("[Groups]: IM From {0} to {1} msg {2} type {3}", im.fromAgentID, im.toAgentID, im.message, (InstantMessageDialog)im.dialog);
|
||||
// Group invitations
|
||||
if ((im.dialog == (byte)InstantMessageDialog.GroupInvitationAccept) || (im.dialog == (byte)InstantMessageDialog.GroupInvitationDecline))
|
||||
{
|
||||
UUID inviteID = new UUID(im.imSessionID);
|
||||
GroupInviteInfo inviteInfo = m_groupData.GetAgentToGroupInvite(remoteAgentIDstr, inviteID);
|
||||
GroupInviteInfo inviteInfo = m_groupData.GetAgentToGroupInvite(GetRequestingAgentIDStr(remoteClient), inviteID);
|
||||
|
||||
if (inviteInfo == null)
|
||||
{
|
||||
|
@ -384,7 +374,7 @@ namespace OpenSim.Groups
|
|||
|
||||
// and the sessionid is the role
|
||||
string reason = string.Empty;
|
||||
if (!m_groupData.AddAgentToGroup(remoteAgentIDstr, invitee.ToString(), inviteInfo.GroupID, inviteInfo.RoleID, string.Empty, out reason))
|
||||
if (!m_groupData.AddAgentToGroup(GetRequestingAgentIDStr(remoteClient), invitee.ToString(), inviteInfo.GroupID, inviteInfo.RoleID, string.Empty, out reason))
|
||||
remoteClient.SendAgentAlertMessage("Unable to add you to the group: " + reason, false);
|
||||
else
|
||||
{
|
||||
|
@ -404,162 +394,111 @@ namespace OpenSim.Groups
|
|||
msg.binaryBucket = new byte[0];
|
||||
|
||||
OutgoingInstantMessage(msg, invitee);
|
||||
IClientAPI inviteeClient = GetActiveRootClient(invitee);
|
||||
if(inviteeClient !=null)
|
||||
{
|
||||
SendAgentGroupDataUpdate(inviteeClient,true);
|
||||
}
|
||||
|
||||
UpdateAllClientsWithGroupInfo(invitee);
|
||||
}
|
||||
|
||||
m_groupData.RemoveAgentToGroupInvite(remoteAgentIDstr, inviteID);
|
||||
m_groupData.RemoveAgentToGroupInvite(GetRequestingAgentIDStr(remoteClient), inviteID);
|
||||
|
||||
}
|
||||
|
||||
// Reject
|
||||
if (im.dialog == (byte)InstantMessageDialog.GroupInvitationDecline)
|
||||
{
|
||||
if (m_debugEnabled)
|
||||
m_log.DebugFormat("[Groups]: Received a reject invite notice.");
|
||||
if (m_debugEnabled) m_log.DebugFormat("[Groups]: Received a reject invite notice.");
|
||||
m_groupData.RemoveAgentToGroupInvite(GetRequestingAgentIDStr(remoteClient), inviteID);
|
||||
|
||||
m_groupData.RemoveAgentToGroupInvite(remoteAgentIDstr, inviteID);
|
||||
m_groupData.RemoveAgentFromGroup(remoteAgentIDstr, inviteInfo.AgentID, inviteInfo.GroupID);
|
||||
m_groupData.RemoveAgentFromGroup(GetRequestingAgentIDStr(remoteClient), inviteInfo.AgentID, inviteInfo.GroupID);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Group notices
|
||||
else if ((im.dialog == (byte)InstantMessageDialog.GroupNotice))
|
||||
if ((im.dialog == (byte)InstantMessageDialog.GroupNotice))
|
||||
{
|
||||
if (!m_groupNoticesEnabled)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
UUID GroupID = new UUID(im.toAgentID);
|
||||
GroupMembershipData grpMemberData = m_groupData.GetAgentGroupMembership(remoteAgentIDstr, remoteAgentIDstr, GroupID);
|
||||
if (grpMemberData == null)
|
||||
if (m_groupData.GetGroupRecord(GetRequestingAgentIDStr(remoteClient), GroupID, null) != null)
|
||||
{
|
||||
remoteClient.SendAgentAlertMessage("Group membership not found", false);
|
||||
return;
|
||||
}
|
||||
|
||||
if ((grpMemberData.GroupPowers & (ulong)GroupPowers.SendNotices) == 0)
|
||||
{
|
||||
remoteClient.SendAgentAlertMessage("No permission to send notice to group", false);
|
||||
return;
|
||||
}
|
||||
|
||||
int index = im.message.IndexOf('|');
|
||||
if (index < 0)
|
||||
return;
|
||||
|
||||
string Subject = im.message.Substring(0, index);
|
||||
string Message = im.message.Substring(index + 1);
|
||||
|
||||
UUID NoticeID = UUID.Random();
|
||||
string Subject = im.message.Substring(0, im.message.IndexOf('|'));
|
||||
string Message = im.message.Substring(Subject.Length + 1);
|
||||
|
||||
InventoryItemBase item = null;
|
||||
bool hasAttachment = false;
|
||||
|
||||
if (im.binaryBucket.Length >= 1 && im.binaryBucket[0] > 0)
|
||||
{
|
||||
UUID itemID = UUID.Zero;
|
||||
UUID ownerID = UUID.Zero;
|
||||
try
|
||||
{
|
||||
string binBucket = Utils.BytesToString(im.binaryBucket);
|
||||
binBucket = binBucket.Substring(15); // remove extra LLSD pre header
|
||||
|
||||
OSDMap binBucketMAP = (OSDMap)OSDParser.DeserializeLLSDXml(binBucket);
|
||||
itemID = binBucketMAP["item_id"].AsUUID();
|
||||
ownerID = binBucketMAP["owner_id"].AsUUID();
|
||||
}
|
||||
catch
|
||||
{
|
||||
m_log.DebugFormat("[GROUPS]: failed to decode group notice bucket");
|
||||
return;
|
||||
}
|
||||
|
||||
if (itemID != UUID.Zero && ownerID != UUID.Zero)
|
||||
{
|
||||
item = scene.InventoryService.GetItem(ownerID, itemID);
|
||||
if(item != null)
|
||||
{
|
||||
if ((item.CurrentPermissions & (uint)(PermissionMask.Transfer | PermissionMask.Copy)) !=
|
||||
(uint)(PermissionMask.Transfer | PermissionMask.Copy))
|
||||
{
|
||||
remoteClient.SendAgentAlertMessage("Item must be have Copy and Transfer rights to attach to group notice", false);
|
||||
return;
|
||||
}
|
||||
}
|
||||
hasAttachment = true;
|
||||
string binBucket = OpenMetaverse.Utils.BytesToString(im.binaryBucket);
|
||||
binBucket = binBucket.Remove(0, 14).Trim();
|
||||
|
||||
OSD binBucketOSD = OSDParser.DeserializeLLSDXml(binBucket);
|
||||
if (binBucketOSD is OSDMap)
|
||||
{
|
||||
OSDMap binBucketMap = (OSDMap)binBucketOSD;
|
||||
|
||||
UUID itemID = binBucketMap["item_id"].AsUUID();
|
||||
UUID ownerID = binBucketMap["owner_id"].AsUUID();
|
||||
item = new InventoryItemBase(itemID, ownerID);
|
||||
item = m_sceneList[0].InventoryService.GetItem(item);
|
||||
}
|
||||
else
|
||||
m_log.DebugFormat("[Groups]: Received OSD with unexpected type: {0}", binBucketOSD.GetType());
|
||||
}
|
||||
|
||||
if (m_groupData.AddGroupNotice(remoteAgentIDstr, GroupID, NoticeID, im.fromAgentName, Subject, Message,
|
||||
if (m_groupData.AddGroupNotice(GetRequestingAgentIDStr(remoteClient), GroupID, NoticeID, im.fromAgentName, Subject, Message,
|
||||
hasAttachment,
|
||||
(byte)(item == null ? 0 : item.AssetType),
|
||||
item == null ? null : item.Name,
|
||||
item == null ? UUID.Zero : item.ID,
|
||||
item == null ? UUID.Zero.ToString() : item.Owner.ToString()))
|
||||
{
|
||||
OnNewGroupNotice?.Invoke(GroupID, NoticeID);
|
||||
if (OnNewGroupNotice != null)
|
||||
{
|
||||
OnNewGroupNotice(GroupID, NoticeID);
|
||||
}
|
||||
|
||||
|
||||
// Send notice out to everyone that wants notices
|
||||
foreach (GroupMembersData member in m_groupData.GetGroupMembers(remoteAgentIDstr, GroupID))
|
||||
foreach (GroupMembersData member in m_groupData.GetGroupMembers(GetRequestingAgentIDStr(remoteClient), GroupID))
|
||||
{
|
||||
GridInstantMessage msg = CreateGroupNoticeIM(UUID.Zero, NoticeID, (byte)InstantMessageDialog.GroupNotice);
|
||||
if (member.AcceptNotices)
|
||||
{
|
||||
// Build notice IIM, one of reach, because the sending may be async
|
||||
GridInstantMessage msg = CreateGroupNoticeIM(UUID.Zero, NoticeID, (byte)OpenMetaverse.InstantMessageDialog.GroupNotice);
|
||||
msg.toAgentID = member.AgentID.Guid;
|
||||
OutgoingInstantMessage(msg, member.AgentID);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (im.dialog == (byte)InstantMessageDialog.GroupNoticeInventoryAccepted)
|
||||
{
|
||||
if (!m_groupNoticesEnabled)
|
||||
if (im.binaryBucket.Length < 16) // Invalid
|
||||
return;
|
||||
|
||||
//// 16 bytes are the UUID. Maybe.
|
||||
// UUID folderID = new UUID(im.binaryBucket, 0);
|
||||
UUID noticeID = new UUID(im.imSessionID);
|
||||
|
||||
if (m_debugEnabled)
|
||||
m_log.DebugFormat("[xmlGROUPS]: Accepted notice {0} for {1}", noticeID, remoteClient.AgentId);
|
||||
|
||||
if (noticeID == UUID.Zero)
|
||||
return;
|
||||
|
||||
UUID folderID = UUID.Zero;
|
||||
try
|
||||
GroupNoticeInfo notice = m_groupData.GetGroupNotice(remoteClient.AgentId.ToString(), noticeID);
|
||||
if (notice != null)
|
||||
{
|
||||
if (im.binaryBucket != null && im.binaryBucket.Length >= 16)
|
||||
folderID = new UUID(im.binaryBucket, 0);
|
||||
}
|
||||
catch
|
||||
{
|
||||
m_log.DebugFormat("[xmlGROUPS]: GroupNoticeInventoryAccepted failed to decode target folder");
|
||||
return;
|
||||
}
|
||||
|
||||
GroupNoticeInfo notice = m_groupData.GetGroupNotice(remoteAgentIDstr, noticeID);
|
||||
if (notice == null)
|
||||
{
|
||||
if (m_debugEnabled)
|
||||
m_log.DebugFormat(
|
||||
"[GROUPS]: Could not find notice {0} for {1} on GroupNoticeInventoryAccepted.",
|
||||
noticeID, remoteClient.AgentId);
|
||||
return;
|
||||
}
|
||||
|
||||
string tmp;
|
||||
UUID giver = new UUID(im.toAgentID);
|
||||
string tmp = string.Empty;
|
||||
Util.ParseUniversalUserIdentifier(notice.noticeData.AttachmentOwnerID, out giver, out tmp, out tmp, out tmp, out tmp);
|
||||
|
||||
m_log.DebugFormat("[Groups]: Giving inventory from {0} to {1}", giver, remoteClient.AgentId);
|
||||
|
||||
string message = "Could not find group notice attached item";
|
||||
InventoryItemBase itemCopy = scene.GiveInventoryItem(remoteClient.AgentId,
|
||||
giver, notice.noticeData.AttachmentItemID, folderID, out message);
|
||||
string message;
|
||||
InventoryItemBase itemCopy = ((Scene)(remoteClient.Scene)).GiveInventoryItem(remoteClient.AgentId,
|
||||
giver, notice.noticeData.AttachmentItemID, out message);
|
||||
|
||||
if (itemCopy == null)
|
||||
{
|
||||
|
@ -570,78 +509,14 @@ namespace OpenSim.Groups
|
|||
remoteClient.SendInventoryItemCreateUpdate(itemCopy, 0);
|
||||
}
|
||||
|
||||
else if (im.dialog == (byte)InstantMessageDialog.GroupNoticeInventoryDeclined)
|
||||
{
|
||||
if (!m_groupNoticesEnabled)
|
||||
return;
|
||||
|
||||
UUID noticeID = new UUID(im.imSessionID);
|
||||
|
||||
if (m_debugEnabled)
|
||||
m_log.DebugFormat("[GROUPS]: Accepted notice {0} for {1}", noticeID, remoteAgentIDstr);
|
||||
|
||||
if (noticeID == UUID.Zero)
|
||||
return;
|
||||
|
||||
UUID remoteAgentID = remoteClient.AgentId;
|
||||
|
||||
GroupNoticeInfo notice = m_groupData.GetGroupNotice(remoteAgentIDstr, noticeID);
|
||||
if (notice == null)
|
||||
{
|
||||
if (m_debugEnabled)
|
||||
m_log.DebugFormat(
|
||||
"[GROUPS]: Could not find notice {0} for {1} on GroupNoticeInventoryAccepted.",
|
||||
noticeID, remoteClient.AgentId);
|
||||
return;
|
||||
}
|
||||
string giver = notice.noticeData.AttachmentOwnerID;
|
||||
UUID attachmentUUID = notice.noticeData.AttachmentItemID;
|
||||
|
||||
if (attachmentUUID == null ||
|
||||
attachmentUUID == UUID.Zero ||
|
||||
giver == null ||
|
||||
giver == UUID.Zero.ToString()
|
||||
)
|
||||
return;
|
||||
|
||||
if (m_debugEnabled)
|
||||
m_log.DebugFormat("[xmlGroups]: Deny inventory from {0} to {1}", giver, remoteAgentIDstr);
|
||||
|
||||
string message = String.Empty;
|
||||
|
||||
InventoryItemBase itemCopy = scene.InventoryService.GetItem(remoteAgentID, attachmentUUID);
|
||||
if (itemCopy == null)
|
||||
return;
|
||||
|
||||
InventoryFolderBase trash = scene.InventoryService.GetFolderForType(remoteAgentID, FolderType.Trash);
|
||||
if (trash == null)
|
||||
{
|
||||
m_log.DebugFormat("[GROUPS]: failed to find trash folder for {0} ", remoteAgentID);
|
||||
return;
|
||||
}
|
||||
|
||||
if (itemCopy.Folder == trash.ID || remoteAgentIDstr == notice.noticeData.AttachmentOwnerID)
|
||||
return;
|
||||
|
||||
itemCopy.Folder = trash.ID;
|
||||
scene.InventoryService.MoveItems(itemCopy.Owner, new List<InventoryItemBase>() { itemCopy });
|
||||
|
||||
if (itemCopy == null)
|
||||
{
|
||||
remoteClient.SendAgentAlertMessage(message, false);
|
||||
return;
|
||||
}
|
||||
|
||||
remoteClient.SendInventoryItemCreateUpdate(itemCopy, 0);
|
||||
}
|
||||
|
||||
|
||||
// Interop, received special 210 code for ejecting a group member
|
||||
// this only works within the comms servers domain, and won't work hypergrid
|
||||
// TODO:FIXME: Use a presense server of some kind to find out where the
|
||||
// client actually is, and try contacting that region directly to notify them,
|
||||
// or provide the notification via xmlrpc update queue
|
||||
else if ((im.dialog == 210))
|
||||
if ((im.dialog == 210))
|
||||
{
|
||||
// This is sent from the region that the ejectee was ejected from
|
||||
// if it's being delivered here, then the ejectee is here
|
||||
|
@ -649,16 +524,14 @@ namespace OpenSim.Groups
|
|||
|
||||
UUID ejecteeID = new UUID(im.toAgentID);
|
||||
|
||||
im.imSessionID = UUID.Zero.Guid;
|
||||
im.dialog = (byte)InstantMessageDialog.MessageFromAgent;
|
||||
OutgoingInstantMessage(im, ejecteeID);
|
||||
|
||||
IClientAPI ejectee = GetActiveRootClient(ejecteeID);
|
||||
IClientAPI ejectee = GetActiveClient(ejecteeID);
|
||||
if (ejectee != null)
|
||||
{
|
||||
UUID groupID = new UUID(im.imSessionID);
|
||||
ejectee.SendAgentDropGroup(groupID);
|
||||
SendAgentGroupDataUpdate(ejectee,true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -678,7 +551,7 @@ namespace OpenSim.Groups
|
|||
case (byte)InstantMessageDialog.GroupInvitation:
|
||||
case (byte)InstantMessageDialog.GroupNotice:
|
||||
UUID toAgentID = new UUID(msg.toAgentID);
|
||||
IClientAPI localClient = GetActiveRootClient(toAgentID);
|
||||
IClientAPI localClient = GetActiveClient(toAgentID);
|
||||
if (localClient != null)
|
||||
{
|
||||
localClient.SendInstantMessage(msg);
|
||||
|
@ -714,7 +587,7 @@ namespace OpenSim.Groups
|
|||
// anyone who is in any region that can see this client, should probably be
|
||||
// updated with new group info. At a minimum, they should get ScenePresence
|
||||
// updated with new title.
|
||||
SendAgentGroupDataUpdate(remoteClient, true);
|
||||
UpdateAllClientsWithGroupInfo(remoteClient.AgentId);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -761,6 +634,7 @@ namespace OpenSim.Groups
|
|||
}
|
||||
|
||||
return data;
|
||||
|
||||
}
|
||||
|
||||
public List<GroupRolesData> GroupRoleDataRequest(IClientAPI remoteClient, UUID groupID)
|
||||
|
@ -840,12 +714,6 @@ namespace OpenSim.Groups
|
|||
return m_groupData.GetAgentGroupMembership(UUID.Zero.ToString(), agentID.ToString(), groupID);
|
||||
}
|
||||
|
||||
public GroupMembershipData GetActiveMembershipData(UUID agentID)
|
||||
{
|
||||
string agentIDstr = agentID.ToString();
|
||||
return m_groupData.GetAgentActiveMembership(agentIDstr, agentIDstr);
|
||||
}
|
||||
|
||||
public void UpdateGroupInfo(IClientAPI remoteClient, UUID groupID, string charter, bool showInList, UUID insigniaID, int membershipFee, bool openEnrollment, bool allowPublish, bool maturePublish)
|
||||
{
|
||||
if (m_debugEnabled) m_log.DebugFormat("[Groups]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
|
||||
|
@ -882,7 +750,7 @@ namespace OpenSim.Groups
|
|||
|
||||
if (avatar != null)
|
||||
{
|
||||
if (avatar.GodController.UserLevel < m_levelGroupCreate)
|
||||
if (avatar.UserLevel < m_levelGroupCreate)
|
||||
{
|
||||
remoteClient.SendCreateGroupReply(UUID.Zero, false, String.Format("Insufficient permissions to create a group. Requires level {0}", m_levelGroupCreate));
|
||||
return UUID.Zero;
|
||||
|
@ -890,7 +758,7 @@ namespace OpenSim.Groups
|
|||
}
|
||||
|
||||
// check funds
|
||||
// is there a money module present ?
|
||||
// is there is a money module present ?
|
||||
IMoneyModule money = scene.RequestModuleInterface<IMoneyModule>();
|
||||
if (money != null)
|
||||
{
|
||||
|
@ -907,13 +775,13 @@ namespace OpenSim.Groups
|
|||
|
||||
if (groupID != UUID.Zero)
|
||||
{
|
||||
if (money != null && money.GroupCreationCharge > 0)
|
||||
money.ApplyCharge(remoteClient.AgentId, money.GroupCreationCharge, MoneyTransactionType.GroupCreate, name);
|
||||
if (money != null)
|
||||
money.ApplyCharge(remoteClient.AgentId, money.GroupCreationCharge, MoneyTransactionType.GroupCreate);
|
||||
|
||||
remoteClient.SendCreateGroupReply(groupID, true, "Group created successfully");
|
||||
remoteClient.SendCreateGroupReply(groupID, true, "Group created successfullly");
|
||||
|
||||
// Update the founder with new group information.
|
||||
SendAgentGroupDataUpdate(remoteClient, true);
|
||||
SendAgentGroupDataUpdate(remoteClient, GetRequestingAgentID(remoteClient));
|
||||
}
|
||||
else
|
||||
remoteClient.SendCreateGroupReply(groupID, false, reason);
|
||||
|
@ -966,7 +834,7 @@ namespace OpenSim.Groups
|
|||
// the client currently has set active, then we need to do a scene presence update too
|
||||
// if (m_groupData.GetAgentActiveMembership(GetRequestingAgentID(remoteClient)).GroupID == GroupID)
|
||||
|
||||
SendDataUpdate(remoteClient, true);
|
||||
UpdateAllClientsWithGroupInfo(GetRequestingAgentID(remoteClient));
|
||||
}
|
||||
|
||||
|
||||
|
@ -1007,7 +875,7 @@ namespace OpenSim.Groups
|
|||
}
|
||||
|
||||
// TODO: This update really should send out updates for everyone in the role that just got changed.
|
||||
SendDataUpdate(remoteClient, true);
|
||||
SendAgentGroupDataUpdate(remoteClient, GetRequestingAgentID(remoteClient));
|
||||
}
|
||||
|
||||
public void GroupRoleChanges(IClientAPI remoteClient, UUID groupID, UUID roleID, UUID memberID, uint changes)
|
||||
|
@ -1033,7 +901,7 @@ namespace OpenSim.Groups
|
|||
}
|
||||
|
||||
// TODO: This update really should send out updates for everyone in the role that just got changed.
|
||||
SendDataUpdate(remoteClient, true);
|
||||
SendAgentGroupDataUpdate(remoteClient, GetRequestingAgentID(remoteClient));
|
||||
}
|
||||
|
||||
public void GroupNoticeRequest(IClientAPI remoteClient, UUID groupNoticeID)
|
||||
|
@ -1075,7 +943,6 @@ namespace OpenSim.Groups
|
|||
bucket = new byte[19 + name.Length];
|
||||
bucket[0] = 1; // has attachment?
|
||||
bucket[1] = info.noticeData.AttachmentType; // attachment type
|
||||
info.GroupID.ToBytes(bucket, 2);
|
||||
name.CopyTo(bucket, 18);
|
||||
}
|
||||
else
|
||||
|
@ -1086,6 +953,7 @@ namespace OpenSim.Groups
|
|||
bucket[18] = 0; // null terminated
|
||||
}
|
||||
|
||||
info.GroupID.ToBytes(bucket, 2);
|
||||
msg.binaryBucket = bucket;
|
||||
}
|
||||
else
|
||||
|
@ -1101,37 +969,27 @@ namespace OpenSim.Groups
|
|||
return msg;
|
||||
}
|
||||
|
||||
public void SendAgentGroupDataUpdate(IClientAPI remoteClient)
|
||||
{
|
||||
if (m_debugEnabled) m_log.DebugFormat("[Groups]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
|
||||
|
||||
// Send agent information about his groups
|
||||
SendAgentGroupDataUpdate(remoteClient, GetRequestingAgentID(remoteClient));
|
||||
}
|
||||
|
||||
public void JoinGroupRequest(IClientAPI remoteClient, UUID groupID)
|
||||
{
|
||||
if (m_debugEnabled) m_log.DebugFormat("[Groups]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
|
||||
|
||||
GroupRecord groupRecord = GetGroupRecord(groupID);
|
||||
IMoneyModule money = remoteClient.Scene.RequestModuleInterface<IMoneyModule>();
|
||||
|
||||
// Should check to see if there's an outstanding invitation
|
||||
|
||||
if (money != null && groupRecord.MembershipFee > 0)
|
||||
{
|
||||
// Does the agent have the funds to cover the group join fee?
|
||||
if (!money.AmountCovered(remoteClient.AgentId, groupRecord.MembershipFee))
|
||||
{
|
||||
remoteClient.SendAlertMessage("Insufficient funds to join the group.");
|
||||
remoteClient.SendJoinGroupReply(groupID, false);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
string reason = string.Empty;
|
||||
|
||||
// Should check to see if OpenEnrollment, or if there's an outstanding invitation
|
||||
if (m_groupData.AddAgentToGroup(GetRequestingAgentIDStr(remoteClient), GetRequestingAgentIDStr(remoteClient), groupID, UUID.Zero, string.Empty, out reason))
|
||||
{
|
||||
if (money != null && groupRecord.MembershipFee > 0)
|
||||
money.ApplyCharge(remoteClient.AgentId, groupRecord.MembershipFee, MoneyTransactionType.GroupJoin, groupRecord.GroupName);
|
||||
|
||||
remoteClient.SendJoinGroupReply(groupID, true);
|
||||
|
||||
// Should this send updates to everyone in the group?
|
||||
SendAgentGroupDataUpdate(remoteClient, true);
|
||||
SendAgentGroupDataUpdate(remoteClient, GetRequestingAgentID(remoteClient));
|
||||
|
||||
if (reason != string.Empty)
|
||||
// A warning
|
||||
|
@ -1153,7 +1011,7 @@ namespace OpenSim.Groups
|
|||
|
||||
// SL sends out notifcations to the group messaging session that the person has left
|
||||
// Should this also update everyone who is in the group?
|
||||
SendAgentGroupDataUpdate(remoteClient, true);
|
||||
SendAgentGroupDataUpdate(remoteClient, GetRequestingAgentID(remoteClient));
|
||||
}
|
||||
|
||||
public void EjectGroupMemberRequest(IClientAPI remoteClient, UUID groupID, UUID ejecteeID)
|
||||
|
@ -1212,31 +1070,10 @@ namespace OpenSim.Groups
|
|||
return;
|
||||
}
|
||||
|
||||
IClientAPI ejecteeClient = GetActiveRootClient(ejecteeID);
|
||||
|
||||
// Send Message to Ejectee
|
||||
GridInstantMessage msg = new GridInstantMessage();
|
||||
|
||||
// if local send a normal message
|
||||
if(ejecteeClient != null)
|
||||
{
|
||||
msg.imSessionID = UUID.Zero.Guid;
|
||||
msg.dialog = (byte)OpenMetaverse.InstantMessageDialog.MessageFromAgent;
|
||||
// also execute and send update
|
||||
ejecteeClient.SendAgentDropGroup(groupID);
|
||||
SendAgentGroupDataUpdate(ejecteeClient,true);
|
||||
}
|
||||
else // send
|
||||
{
|
||||
// Interop, received special 210 code for ejecting a group member
|
||||
// this only works within the comms servers domain, and won't work hypergrid
|
||||
// TODO:FIXME: Use a presence server of some kind to find out where the
|
||||
// client actually is, and try contacting that region directly to notify them,
|
||||
// or provide the notification via xmlrpc update queue
|
||||
|
||||
msg.imSessionID = groupInfo.GroupID.Guid;
|
||||
msg.dialog = (byte)210; //interop
|
||||
}
|
||||
msg.fromAgentID = agentID.Guid;
|
||||
// msg.fromAgentID = info.GroupID;
|
||||
msg.toAgentID = ejecteeID.Guid;
|
||||
|
@ -1244,7 +1081,7 @@ namespace OpenSim.Groups
|
|||
msg.timestamp = 0;
|
||||
msg.fromAgentName = agentName;
|
||||
msg.message = string.Format("You have been ejected from '{1}' by {0}.", agentName, groupInfo.GroupName);
|
||||
|
||||
msg.dialog = (byte)OpenMetaverse.InstantMessageDialog.MessageFromAgent;
|
||||
msg.fromGroup = false;
|
||||
msg.offline = (byte)0;
|
||||
msg.ParentEstateID = 0;
|
||||
|
@ -1254,7 +1091,11 @@ namespace OpenSim.Groups
|
|||
OutgoingInstantMessage(msg, ejecteeID);
|
||||
|
||||
// Message to ejector
|
||||
|
||||
// Interop, received special 210 code for ejecting a group member
|
||||
// this only works within the comms servers domain, and won't work hypergrid
|
||||
// TODO:FIXME: Use a presense server of some kind to find out where the
|
||||
// client actually is, and try contacting that region directly to notify them,
|
||||
// or provide the notification via xmlrpc update queue
|
||||
|
||||
msg = new GridInstantMessage();
|
||||
msg.imSessionID = UUID.Zero.Guid;
|
||||
|
@ -1270,7 +1111,7 @@ namespace OpenSim.Groups
|
|||
{
|
||||
msg.message = string.Format("{2} has been ejected from '{1}' by {0}.", agentName, groupInfo.GroupName, "Unknown member");
|
||||
}
|
||||
msg.dialog = (byte)OpenMetaverse.InstantMessageDialog.MessageFromAgent;
|
||||
msg.dialog = (byte)210; //interop
|
||||
msg.fromGroup = false;
|
||||
msg.offline = (byte)0;
|
||||
msg.ParentEstateID = 0;
|
||||
|
@ -1278,6 +1119,11 @@ namespace OpenSim.Groups
|
|||
msg.RegionID = regionInfo.RegionID.Guid;
|
||||
msg.binaryBucket = new byte[0];
|
||||
OutgoingInstantMessage(msg, agentID);
|
||||
|
||||
|
||||
// SL sends out messages to everyone in the group
|
||||
// Who all should receive updates and what should they be updated with?
|
||||
UpdateAllClientsWithGroupInfo(ejecteeID);
|
||||
}
|
||||
|
||||
public void InviteGroupRequest(IClientAPI remoteClient, UUID groupID, UUID invitedAgentID, UUID roleID)
|
||||
|
@ -1334,24 +1180,12 @@ namespace OpenSim.Groups
|
|||
|
||||
public List<DirGroupsReplyData> FindGroups(IClientAPI remoteClient, string query)
|
||||
{
|
||||
return m_groupData.FindGroups(remoteClient.AgentId.ToString(), query);
|
||||
return m_groupData.FindGroups(GetRequestingAgentIDStr(remoteClient), query);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Client/Update Tools
|
||||
private IClientAPI GetActiveRootClient(UUID agentID)
|
||||
{
|
||||
foreach (Scene scene in m_sceneList)
|
||||
{
|
||||
ScenePresence sp = scene.GetScenePresence(agentID);
|
||||
if (sp != null && !sp.IsChildAgent && !sp.IsDeleted)
|
||||
{
|
||||
return sp.ControllingClient;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Try to find an active IClientAPI reference for agentID giving preference to root connections
|
||||
|
@ -1364,7 +1198,7 @@ namespace OpenSim.Groups
|
|||
foreach (Scene scene in m_sceneList)
|
||||
{
|
||||
ScenePresence sp = scene.GetScenePresence(agentID);
|
||||
if (sp != null&& !sp.IsDeleted)
|
||||
if (sp != null)
|
||||
{
|
||||
if (!sp.IsChildAgent)
|
||||
{
|
||||
|
@ -1381,6 +1215,71 @@ namespace OpenSim.Groups
|
|||
return child;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Send 'remoteClient' the group membership 'data' for agent 'dataForAgentID'.
|
||||
/// </summary>
|
||||
private void SendGroupMembershipInfoViaCaps(IClientAPI remoteClient, UUID dataForAgentID, GroupMembershipData[] data)
|
||||
{
|
||||
if (m_debugEnabled) m_log.InfoFormat("[Groups]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
|
||||
|
||||
// NPCs currently don't have a CAPs structure or event queues. There is a strong argument for conveying this information
|
||||
// to them anyway since it makes writing server-side bots a lot easier, but for now we don't do anything.
|
||||
if (remoteClient.SceneAgent.PresenceType == PresenceType.Npc)
|
||||
return;
|
||||
|
||||
OSDArray AgentData = new OSDArray(1);
|
||||
OSDMap AgentDataMap = new OSDMap(1);
|
||||
AgentDataMap.Add("AgentID", OSD.FromUUID(dataForAgentID));
|
||||
AgentData.Add(AgentDataMap);
|
||||
|
||||
OSDArray GroupData = new OSDArray(data.Length);
|
||||
OSDArray NewGroupData = new OSDArray(data.Length);
|
||||
|
||||
foreach (GroupMembershipData membership in data)
|
||||
{
|
||||
if (GetRequestingAgentID(remoteClient) != dataForAgentID)
|
||||
{
|
||||
if (!membership.ListInProfile)
|
||||
{
|
||||
// If we're sending group info to remoteclient about another agent,
|
||||
// filter out groups the other agent doesn't want to share.
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
OSDMap GroupDataMap = new OSDMap(6);
|
||||
OSDMap NewGroupDataMap = new OSDMap(1);
|
||||
|
||||
GroupDataMap.Add("GroupID", OSD.FromUUID(membership.GroupID));
|
||||
GroupDataMap.Add("GroupPowers", OSD.FromULong(membership.GroupPowers));
|
||||
GroupDataMap.Add("AcceptNotices", OSD.FromBoolean(membership.AcceptNotices));
|
||||
GroupDataMap.Add("GroupInsigniaID", OSD.FromUUID(membership.GroupPicture));
|
||||
GroupDataMap.Add("Contribution", OSD.FromInteger(membership.Contribution));
|
||||
GroupDataMap.Add("GroupName", OSD.FromString(membership.GroupName));
|
||||
NewGroupDataMap.Add("ListInProfile", OSD.FromBoolean(membership.ListInProfile));
|
||||
|
||||
GroupData.Add(GroupDataMap);
|
||||
NewGroupData.Add(NewGroupDataMap);
|
||||
}
|
||||
|
||||
OSDMap llDataStruct = new OSDMap(3);
|
||||
llDataStruct.Add("AgentData", AgentData);
|
||||
llDataStruct.Add("GroupData", GroupData);
|
||||
llDataStruct.Add("NewGroupData", NewGroupData);
|
||||
|
||||
if (m_debugEnabled)
|
||||
{
|
||||
m_log.InfoFormat("[Groups]: {0}", OSDParser.SerializeJsonString(llDataStruct));
|
||||
}
|
||||
|
||||
IEventQueue queue = remoteClient.Scene.RequestModuleInterface<IEventQueue>();
|
||||
|
||||
if (queue != null)
|
||||
{
|
||||
queue.Enqueue(queue.BuildEvent("AgentGroupDataUpdate", llDataStruct), GetRequestingAgentID(remoteClient));
|
||||
}
|
||||
}
|
||||
|
||||
private void SendScenePresenceUpdate(UUID AgentID, string Title)
|
||||
{
|
||||
if (m_debugEnabled) m_log.DebugFormat("[Groups]: Updating scene title for {0} with title: {1}", AgentID, Title);
|
||||
|
@ -1397,39 +1296,53 @@ namespace OpenSim.Groups
|
|||
presence.Grouptitle = Title;
|
||||
|
||||
if (! presence.IsChildAgent)
|
||||
presence.SendAvatarDataToAllAgents();
|
||||
presence.SendAvatarDataToAllClients();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void SendAgentGroupDataUpdate(IClientAPI remoteClient)
|
||||
{
|
||||
SendAgentGroupDataUpdate(remoteClient, true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tell remoteClient about its agent groups, and optionally send title to others
|
||||
/// Send updates to all clients who might be interested in groups data for dataForClientID
|
||||
/// </summary>
|
||||
private void SendAgentGroupDataUpdate(IClientAPI remoteClient, bool tellOthers)
|
||||
private void UpdateAllClientsWithGroupInfo(UUID dataForClientID)
|
||||
{
|
||||
if (m_debugEnabled) m_log.InfoFormat("[Groups]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
|
||||
|
||||
// TODO: Probably isn't nessesary to update every client in every scene.
|
||||
// Need to examine client updates and do only what's nessesary.
|
||||
lock (m_sceneList)
|
||||
{
|
||||
foreach (Scene scene in m_sceneList)
|
||||
{
|
||||
scene.ForEachClient(delegate(IClientAPI client) { SendAgentGroupDataUpdate(client, dataForClientID); });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Update remoteClient with group information about dataForAgentID
|
||||
/// </summary>
|
||||
private void SendAgentGroupDataUpdate(IClientAPI remoteClient, UUID dataForAgentID)
|
||||
{
|
||||
if (m_debugEnabled) m_log.InfoFormat("[Groups]: {0} called for {1}", System.Reflection.MethodBase.GetCurrentMethod().Name, remoteClient.Name);
|
||||
|
||||
// NPCs currently don't have a CAPs structure or event queues. There is a strong argument for conveying this information
|
||||
// to them anyway since it makes writing server-side bots a lot easier, but for now we don't do anything.
|
||||
if (remoteClient.SceneAgent.PresenceType == PresenceType.Npc)
|
||||
return;
|
||||
|
||||
// TODO: All the client update functions need to be reexamined because most do too much and send too much stuff
|
||||
|
||||
UUID agentID = GetRequestingAgentID(remoteClient);
|
||||
OnAgentDataUpdateRequest(remoteClient, dataForAgentID, UUID.Zero);
|
||||
|
||||
SendDataUpdate(remoteClient, tellOthers);
|
||||
// Need to send a group membership update to the client
|
||||
// UDP version doesn't seem to behave nicely. But we're going to send it out here
|
||||
// with an empty group membership to hopefully remove groups being displayed due
|
||||
// to the core Groups Stub
|
||||
//remoteClient.SendGroupMembership(new GroupMembershipData[0]);
|
||||
|
||||
GroupMembershipData[] membershipArray = GetProfileListedGroupMemberships(remoteClient, agentID);
|
||||
GroupMembershipData[] membershipArray = GetProfileListedGroupMemberships(remoteClient, dataForAgentID);
|
||||
SendGroupMembershipInfoViaCaps(remoteClient, dataForAgentID, membershipArray);
|
||||
|
||||
remoteClient.UpdateGroupMembership(membershipArray);
|
||||
remoteClient.SendAgentGroupDataUpdate(agentID, membershipArray);
|
||||
//remoteClient.SendAvatarGroupsReply(dataForAgentID, membershipArray);
|
||||
if (remoteClient.AgentId == dataForAgentID)
|
||||
remoteClient.RefreshGroupMembership();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -1481,49 +1394,27 @@ namespace OpenSim.Groups
|
|||
return membershipArray;
|
||||
}
|
||||
|
||||
//tell remoteClient about its agent group info, and optionally send title to others
|
||||
private void SendDataUpdate(IClientAPI remoteClient, bool tellOthers)
|
||||
{
|
||||
if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
|
||||
|
||||
UUID activeGroupID = UUID.Zero;
|
||||
string activeGroupTitle = string.Empty;
|
||||
string activeGroupName = string.Empty;
|
||||
ulong activeGroupPowers = (ulong)GroupPowers.None;
|
||||
|
||||
UUID agentID = GetRequestingAgentID(remoteClient);
|
||||
GroupMembershipData membership = m_groupData.GetAgentActiveMembership(agentID.ToString(), agentID.ToString());
|
||||
if (membership != null)
|
||||
private void SendAgentDataUpdate(IClientAPI remoteClient, UUID dataForAgentID, UUID activeGroupID, string activeGroupName, ulong activeGroupPowers, string activeGroupTitle)
|
||||
{
|
||||
activeGroupID = membership.GroupID;
|
||||
activeGroupTitle = membership.GroupTitle;
|
||||
activeGroupPowers = membership.GroupPowers;
|
||||
activeGroupName = membership.GroupName;
|
||||
if (m_debugEnabled) m_log.DebugFormat("[Groups]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
|
||||
|
||||
// TODO: All the client update functions need to be reexamined because most do too much and send too much stuff
|
||||
string firstname = "Unknown", lastname = "Unknown";
|
||||
string name = m_UserManagement.GetUserName(dataForAgentID);
|
||||
if (!string.IsNullOrEmpty(name))
|
||||
{
|
||||
string[] parts = name.Split(new char[] { ' ' });
|
||||
if (parts.Length >= 2)
|
||||
{
|
||||
firstname = parts[0];
|
||||
lastname = parts[1];
|
||||
}
|
||||
}
|
||||
|
||||
UserAccount account = m_sceneList[0].UserAccountService.GetUserAccount(remoteClient.Scene.RegionInfo.ScopeID, agentID);
|
||||
string firstname, lastname;
|
||||
if (account != null)
|
||||
{
|
||||
firstname = account.FirstName;
|
||||
lastname = account.LastName;
|
||||
}
|
||||
else
|
||||
{
|
||||
firstname = "Unknown";
|
||||
lastname = "Unknown";
|
||||
}
|
||||
|
||||
remoteClient.SendAgentDataUpdate(agentID, activeGroupID, firstname,
|
||||
remoteClient.SendAgentDataUpdate(dataForAgentID, activeGroupID, firstname,
|
||||
lastname, activeGroupPowers, activeGroupName,
|
||||
activeGroupTitle);
|
||||
|
||||
if (tellOthers)
|
||||
SendScenePresenceUpdate(agentID, activeGroupTitle);
|
||||
|
||||
ScenePresence sp = (ScenePresence)remoteClient.SceneAgent;
|
||||
if (sp != null)
|
||||
sp.Grouptitle = activeGroupTitle;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
@ -1534,7 +1425,7 @@ namespace OpenSim.Groups
|
|||
{
|
||||
if (m_debugEnabled) m_log.InfoFormat("[Groups]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
|
||||
|
||||
IClientAPI localClient = GetActiveRootClient(msgTo);
|
||||
IClientAPI localClient = GetActiveClient(msgTo);
|
||||
if (localClient != null)
|
||||
{
|
||||
if (m_debugEnabled) m_log.InfoFormat("[Groups]: MsgTo ({0}) is local, delivering directly", localClient.Name);
|
||||
|
@ -1572,4 +1463,5 @@ namespace OpenSim.Groups
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
@ -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();
|
||||
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -39,7 +39,7 @@ namespace OpenSim.Groups
|
|||
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);
|
||||
|
|
|
@ -173,9 +173,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)
|
||||
|
|
|
@ -30,7 +30,7 @@ using Mono.Addins;
|
|||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
[assembly: AssemblyVersion(OpenSim.VersionInfo.AssemblyVersionNumber)]
|
||||
[assembly: AssemblyVersion("0.8.2.*")]
|
||||
|
||||
[assembly: Addin("OpenSim.Groups", OpenSim.VersionInfo.VersionNumber)]
|
||||
[assembly: AddinDependency("OpenSim.Region.Framework", OpenSim.VersionInfo.VersionNumber)]
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -192,10 +192,10 @@ namespace OpenSim.Groups
|
|||
});
|
||||
}
|
||||
|
||||
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)
|
||||
|
|
|
@ -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";
|
||||
}
|
||||
|
|
|
@ -43,8 +43,7 @@ namespace OpenSim.Groups
|
|||
{
|
||||
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||
|
||||
public const GroupPowers DefaultEveryonePowers =
|
||||
GroupPowers.AllowSetHome |
|
||||
public const GroupPowers DefaultEveryonePowers = GroupPowers.AllowSetHome |
|
||||
GroupPowers.Accountable |
|
||||
GroupPowers.JoinChat |
|
||||
GroupPowers.AllowVoiceChat |
|
||||
|
@ -52,23 +51,31 @@ namespace OpenSim.Groups
|
|||
GroupPowers.StartProposal |
|
||||
GroupPowers.VoteOnProposal;
|
||||
|
||||
public const GroupPowers OfficersPowers = DefaultEveryonePowers |
|
||||
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.AllowEnvironment |
|
||||
GroupPowers.LandEjectAndFreeze |
|
||||
GroupPowers.LandGardening |
|
||||
GroupPowers.LandManageAllowed |
|
||||
|
@ -77,29 +84,19 @@ namespace OpenSim.Groups
|
|||
GroupPowers.LandOptions |
|
||||
GroupPowers.LandRelease |
|
||||
GroupPowers.LandSetSale |
|
||||
GroupPowers.MemberVisible |
|
||||
GroupPowers.ModerateChat |
|
||||
GroupPowers.ObjectManipulate |
|
||||
GroupPowers.ObjectSetForSale |
|
||||
GroupPowers.ReceiveNotices |
|
||||
GroupPowers.RemoveMember |
|
||||
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;
|
||||
GroupPowers.SetLandingPoint |
|
||||
GroupPowers.StartProposal |
|
||||
GroupPowers.VoteOnProposal;
|
||||
|
||||
#region Daily Cleanup
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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 &&
|
||||
|
|
|
@ -30,7 +30,7 @@ using Mono.Addins;
|
|||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
[assembly: AssemblyVersion(OpenSim.VersionInfo.AssemblyVersionNumber)]
|
||||
[assembly: AssemblyVersion("0.8.2.*")]
|
||||
|
||||
[assembly: Addin("OpenSim.OfflineIM", OpenSim.VersionInfo.VersionNumber)]
|
||||
[assembly: AddinDependency("OpenSim.Region.Framework", OpenSim.VersionInfo.VersionNumber)]
|
||||
|
|
|
@ -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,6 +32,8 @@ 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;
|
||||
|
|
|
@ -61,8 +61,9 @@ 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 : AssemblyVersion("0.8.2.*")]
|
||||
|
||||
[assembly: Addin("OpenSim.ApplicationPlugins.LoadRegions", OpenSim.VersionInfo.VersionNumber)]
|
||||
[assembly: AddinDependency("OpenSim", OpenSim.VersionInfo.VersionNumber)]
|
||||
|
|
|
@ -30,7 +30,7 @@ using Mono.Addins;
|
|||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
[assembly: AssemblyVersion(OpenSim.VersionInfo.AssemblyVersionNumber)]
|
||||
[assembly: AssemblyVersion("0.8.2.*")]
|
||||
|
||||
[assembly: Addin("OpenSim.ApplicationPlugins.RegionModulesController", OpenSim.VersionInfo.VersionNumber)]
|
||||
[assembly: AddinDependency("OpenSim", OpenSim.VersionInfo.VersionNumber)]
|
||||
|
|
|
@ -131,9 +131,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)
|
||||
|
@ -368,10 +365,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 +502,6 @@ namespace OpenSim.ApplicationPlugins.RegionModulesController
|
|||
{
|
||||
module.RegionLoaded(scene);
|
||||
}
|
||||
|
||||
scene.AllModulesLoaded();
|
||||
}
|
||||
|
||||
public void RemoveRegionFromModules (Scene scene)
|
||||
|
|
|
@ -30,7 +30,7 @@ using Mono.Addins;
|
|||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
[assembly: AssemblyVersion(OpenSim.VersionInfo.AssemblyVersionNumber)]
|
||||
[assembly: AssemblyVersion("0.8.2.*")]
|
||||
|
||||
[assembly: Addin("OpenSim.ApplicationPlugins.RemoteController", OpenSim.VersionInfo.VersionNumber)]
|
||||
[assembly: AddinDependency("OpenSim", OpenSim.VersionInfo.VersionNumber)]
|
||||
|
|
|
@ -42,6 +42,7 @@ 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;
|
||||
|
@ -74,7 +75,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 +94,6 @@ namespace OpenSim.ApplicationPlugins.RemoteController
|
|||
|
||||
public void Initialise(OpenSimBase openSim)
|
||||
{
|
||||
m_openSimVersion = openSim.GetVersionText();
|
||||
|
||||
m_configSource = openSim.ConfigSource.Source;
|
||||
try
|
||||
{
|
||||
|
@ -138,13 +136,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 +164,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 +266,32 @@ namespace OpenSim.ApplicationPlugins.RemoteController
|
|||
|
||||
try
|
||||
{
|
||||
Scene rebootedScene = null;
|
||||
bool restartAll = false;
|
||||
m_log.Info("[RADMIN]: Request to restart Region.");
|
||||
|
||||
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);
|
||||
|
||||
Scene rebootedScene = null;
|
||||
GetSceneFromRegionParams(requestData, responseData, out rebootedScene);
|
||||
}
|
||||
|
||||
IRestartModule restartModule = rebootedScene.RequestModuleInterface<IRestartModule>();
|
||||
|
||||
responseData["success"] = false;
|
||||
responseData["accepted"] = true;
|
||||
responseData["rebooting"] = true;
|
||||
|
||||
string message;
|
||||
List<int> times = new List<int>();
|
||||
|
||||
if (requestData.ContainsKey("alerts"))
|
||||
{
|
||||
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.");
|
||||
|
||||
IRestartModule restartModule = rebootedScene.RequestModuleInterface<IRestartModule>();
|
||||
if (restartModule != null)
|
||||
{
|
||||
message = "Restart has been cancelled";
|
||||
|
||||
if (requestData.ContainsKey("message"))
|
||||
message = requestData["message"].ToString();
|
||||
|
||||
restartModule.AbortRestart(message);
|
||||
List<int> times = new List<int> { 30, 15 };
|
||||
|
||||
restartModule.ScheduleRestart(UUID.Zero, "Region will restart in {0}", times.ToArray(), true);
|
||||
responseData["success"] = true;
|
||||
responseData["rebooting"] = false;
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
foreach (string a in alertTimes)
|
||||
times.Add(Convert.ToInt32(a));
|
||||
}
|
||||
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 +321,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,23 +424,6 @@ namespace OpenSim.ApplicationPlugins.RemoteController
|
|||
message = "Region is going down now.";
|
||||
}
|
||||
|
||||
if (requestData.ContainsKey("noticetype")
|
||||
&& ((string) requestData["noticetype"] == "dialog"))
|
||||
{
|
||||
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)
|
||||
{
|
||||
|
@ -598,8 +431,6 @@ namespace OpenSim.ApplicationPlugins.RemoteController
|
|||
if (dialogModule != null)
|
||||
dialogModule.SendGeneralAlert(message);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Perform shutdown
|
||||
System.Timers.Timer shutdownTimer = new System.Timers.Timer(timeout); // Wait before firing
|
||||
|
@ -1918,31 +1749,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;
|
||||
}
|
||||
|
||||
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)
|
||||
|
@ -2251,6 +2072,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,11 +2082,9 @@ 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);
|
||||
|
||||
|
@ -2280,109 +2100,23 @@ namespace OpenSim.ApplicationPlugins.RemoteController
|
|||
{
|
||||
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 +2539,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 +2576,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 +2606,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 +2660,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 +2707,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 +2723,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 +2741,7 @@ namespace OpenSim.ApplicationPlugins.RemoteController
|
|||
{
|
||||
destinationFolder = new InventoryFolderBase();
|
||||
destinationFolder.ID = UUID.Random();
|
||||
if (assetType == FolderType.Clothing)
|
||||
if (assetType == AssetType.Clothing)
|
||||
{
|
||||
destinationFolder.Name = "Clothing";
|
||||
}
|
||||
|
@ -3247,16 +2980,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 +3035,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);
|
||||
|
|
|
@ -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,27 +149,15 @@ 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}",
|
||||
// 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";
|
||||
|
@ -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)
|
||||
|
@ -295,6 +237,9 @@ namespace OpenSim.Framework.Capabilities
|
|||
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>
|
||||
|
@ -74,36 +88,17 @@ namespace OpenSim.Framework.Capabilities
|
|||
public void Remove(string capsName)
|
||||
{
|
||||
lock (m_capsHandlers)
|
||||
{
|
||||
if(m_capsHandlers.ContainsKey(capsName))
|
||||
{
|
||||
m_httpListener.RemoveStreamHandler("POST", m_capsHandlers[capsName].Path);
|
||||
m_httpListener.RemoveStreamHandler("PUT", m_capsHandlers[capsName].Path);
|
||||
m_httpListener.RemoveStreamHandler("GET", m_capsHandlers[capsName].Path);
|
||||
m_httpListener.RemoveStreamHandler("DELETE", m_capsHandlers[capsName].Path);
|
||||
m_capsHandlers.Remove(capsName);
|
||||
}
|
||||
}
|
||||
if(m_capsSimpleHandlers.TryRemove(capsName, out ISimpleStreamHandler hdr))
|
||||
{
|
||||
m_httpListener.RemoveSimpleStreamHandler(hdr.Path);
|
||||
}
|
||||
}
|
||||
|
||||
public void AddSimpleHandler(string capName, ISimpleStreamHandler handler, bool addToListener = true)
|
||||
{
|
||||
if(ContainsCap(capName))
|
||||
Remove(capName);
|
||||
if(m_capsSimpleHandlers.TryAdd(capName, handler) && addToListener)
|
||||
m_httpListener.AddSimpleStreamHandler(handler);
|
||||
}
|
||||
|
||||
public bool ContainsCap(string cap)
|
||||
{
|
||||
lock (m_capsHandlers)
|
||||
if (m_capsHandlers.ContainsKey(cap))
|
||||
return true;
|
||||
return m_capsSimpleHandlers.ContainsKey(cap);
|
||||
return m_capsHandlers.ContainsKey(cap);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -130,9 +125,6 @@ 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);
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
foreach (string capsName in m_capsHandlers.Keys)
|
||||
{
|
||||
for(int i = 0; i < requestedCaps.Count; ++i)
|
||||
{
|
||||
string capsName = requestedCaps[i];
|
||||
if (excludeSeed && "SEED" == capsName)
|
||||
continue;
|
||||
|
||||
if (m_capsSimpleHandlers.TryGetValue(capsName, out ISimpleStreamHandler shdr))
|
||||
{
|
||||
caps[capsName] = baseUrl + shdr.Path;
|
||||
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,118 @@
|
|||
/*
|
||||
* Copyright (c) Contributors, http://opensimulator.org/
|
||||
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of the OpenSimulator Project nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
using OpenMetaverse;
|
||||
using OpenMetaverse.StructuredData;
|
||||
using OpenSim.Framework;
|
||||
using OpenSim.Framework.Capabilities;
|
||||
using OpenSim.Framework.Servers.HttpServer;
|
||||
using OpenSim.Services.Interfaces;
|
||||
using OSDArray = OpenMetaverse.StructuredData.OSDArray;
|
||||
using OSDMap = OpenMetaverse.StructuredData.OSDMap;
|
||||
|
||||
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 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, m_agentID));
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,746 @@
|
|||
/*
|
||||
* 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 FetchInvDescHandler
|
||||
{
|
||||
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 FetchInvDescHandler(IInventoryService invService, ILibraryService libService)
|
||||
{
|
||||
m_InventoryService = invService;
|
||||
m_LibraryService = libService;
|
||||
}
|
||||
|
||||
|
||||
public string FetchInventoryDescendentsRequest(string request, string path, string param, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
|
||||
{
|
||||
|
||||
// nasty temporary hack here, the linden client falsely
|
||||
// identifies the uuid 00000000-0000-0000-0000-000000000000
|
||||
// as a string which breaks us
|
||||
//
|
||||
// correctly mark it as a uuid
|
||||
//
|
||||
request = request.Replace("<string>00000000-0000-0000-0000-000000000000</string>", "<uuid>00000000-0000-0000-0000-000000000000</uuid>");
|
||||
|
||||
// another hack <integer>1</integer> results in a
|
||||
// System.ArgumentException: Object type System.Int32 cannot
|
||||
// be converted to target type: System.Boolean
|
||||
//
|
||||
request = request.Replace("<key>fetch_folders</key><integer>0</integer>", "<key>fetch_folders</key><boolean>0</boolean>");
|
||||
request = request.Replace("<key>fetch_folders</key><integer>1</integer>", "<key>fetch_folders</key><boolean>1</boolean>");
|
||||
|
||||
Hashtable hash = new Hashtable();
|
||||
try
|
||||
{
|
||||
hash = (Hashtable)LLSD.LLSDDeserialize(Utils.StringToBytes(request));
|
||||
}
|
||||
catch (LLSD.LLSDParseException e)
|
||||
{
|
||||
m_log.ErrorFormat("[WEB FETCH INV DESC HANDLER]: Fetch error: {0}{1}" + e.Message, e.StackTrace);
|
||||
m_log.Error("Request: " + request);
|
||||
}
|
||||
|
||||
ArrayList foldersrequested = (ArrayList)hash["folders"];
|
||||
|
||||
string response = "";
|
||||
string bad_folders_response = "";
|
||||
|
||||
List<LLSDFetchInventoryDescendents> folders = new List<LLSDFetchInventoryDescendents>();
|
||||
for (int i = 0; i < foldersrequested.Count; i++)
|
||||
{
|
||||
Hashtable inventoryhash = (Hashtable)foldersrequested[i];
|
||||
|
||||
LLSDFetchInventoryDescendents llsdRequest = new LLSDFetchInventoryDescendents();
|
||||
|
||||
try
|
||||
{
|
||||
LLSDHelpers.DeserialiseOSDMap(inventoryhash, llsdRequest);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
m_log.Debug("[WEB FETCH INV DESC HANDLER]: caught exception doing OSD deserialize" + e);
|
||||
continue;
|
||||
}
|
||||
|
||||
folders.Add(llsdRequest);
|
||||
}
|
||||
|
||||
if (folders.Count > 0)
|
||||
{
|
||||
List<InventoryCollectionWithDescendents> invcollSet = Fetch(folders);
|
||||
//m_log.DebugFormat("[XXX]: Got {0} folders from a request of {1}", invcollSet.Count, folders.Count);
|
||||
if (invcollSet == null)
|
||||
{
|
||||
m_log.DebugFormat("[WEB FETCH INV DESC HANDLER]: Multiple folder fetch failed. Trying old protocol.");
|
||||
return FetchInventoryDescendentsRequest(foldersrequested, httpRequest, httpResponse);
|
||||
}
|
||||
|
||||
string inventoryitemstr = string.Empty;
|
||||
foreach (InventoryCollectionWithDescendents icoll in invcollSet)
|
||||
{
|
||||
LLSDInventoryDescendents reply = ToLLSD(icoll.Collection, icoll.Descendents);
|
||||
|
||||
inventoryitemstr = LLSDHelpers.SerialiseLLSDReply(reply);
|
||||
inventoryitemstr = inventoryitemstr.Replace("<llsd><map><key>folders</key><array>", "");
|
||||
inventoryitemstr = inventoryitemstr.Replace("</array></map></llsd>", "");
|
||||
|
||||
response += inventoryitemstr;
|
||||
}
|
||||
}
|
||||
|
||||
if (response.Length == 0)
|
||||
{
|
||||
/* Viewers expect a bad_folders array when not available */
|
||||
if (bad_folders_response.Length != 0)
|
||||
{
|
||||
response = "<llsd><map><key>bad_folders</key><array>" + bad_folders_response + "</array></map></llsd>";
|
||||
}
|
||||
else
|
||||
{
|
||||
response = "<llsd><map><key>folders</key><array /></map></llsd>";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (bad_folders_response.Length != 0)
|
||||
{
|
||||
response = "<llsd><map><key>folders</key><array>" + response + "</array><key>bad_folders</key><array>" + bad_folders_response + "</array></map></llsd>";
|
||||
}
|
||||
else
|
||||
{
|
||||
response = "<llsd><map><key>folders</key><array>" + response + "</array></map></llsd>";
|
||||
}
|
||||
}
|
||||
|
||||
// m_log.DebugFormat("[WEB FETCH INV DESC HANDLER]: Replying to CAPS fetch inventory request");
|
||||
// m_log.Debug("[WEB FETCH INV DESC HANDLER] "+response);
|
||||
|
||||
return response;
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 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;
|
||||
}
|
||||
|
||||
private LLSDInventoryDescendents ToLLSD(InventoryCollection inv, int descendents)
|
||||
{
|
||||
LLSDInventoryDescendents reply = new LLSDInventoryDescendents();
|
||||
LLSDInventoryFolderContents contents = new LLSDInventoryFolderContents();
|
||||
contents.agent_id = inv.OwnerID;
|
||||
contents.owner_id = inv.OwnerID;
|
||||
contents.folder_id = inv.FolderID;
|
||||
|
||||
reply.folders.Array.Add(contents);
|
||||
|
||||
if (inv.Folders != null)
|
||||
{
|
||||
foreach (InventoryFolderBase invFolder in inv.Folders)
|
||||
{
|
||||
contents.categories.Array.Add(ConvertInventoryFolder(invFolder));
|
||||
}
|
||||
|
||||
descendents += inv.Folders.Count;
|
||||
}
|
||||
|
||||
if (inv.Items != null)
|
||||
{
|
||||
foreach (InventoryItemBase invItem in inv.Items)
|
||||
{
|
||||
contents.items.Array.Add(ConvertInventoryItem(invItem));
|
||||
}
|
||||
}
|
||||
|
||||
contents.descendents = descendents;
|
||||
contents.version = inv.Version;
|
||||
|
||||
return reply;
|
||||
}
|
||||
/// <summary>
|
||||
/// Old style. Soon to be deprecated.
|
||||
/// </summary>
|
||||
/// <param name="request"></param>
|
||||
/// <param name="httpRequest"></param>
|
||||
/// <param name="httpResponse"></param>
|
||||
/// <returns></returns>
|
||||
[Obsolete]
|
||||
private string FetchInventoryDescendentsRequest(ArrayList foldersrequested, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
|
||||
{
|
||||
//m_log.DebugFormat("[WEB FETCH INV DESC HANDLER]: Received request for {0} folders", foldersrequested.Count);
|
||||
|
||||
string response = "";
|
||||
string bad_folders_response = "";
|
||||
|
||||
for (int i = 0; i < foldersrequested.Count; i++)
|
||||
{
|
||||
string inventoryitemstr = "";
|
||||
Hashtable inventoryhash = (Hashtable)foldersrequested[i];
|
||||
|
||||
LLSDFetchInventoryDescendents llsdRequest = new LLSDFetchInventoryDescendents();
|
||||
|
||||
try
|
||||
{
|
||||
LLSDHelpers.DeserialiseOSDMap(inventoryhash, llsdRequest);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
m_log.Debug("[WEB FETCH INV DESC HANDLER]: caught exception doing OSD deserialize" + e);
|
||||
}
|
||||
|
||||
LLSDInventoryDescendents reply = FetchInventoryReply(llsdRequest);
|
||||
|
||||
if (null == reply)
|
||||
{
|
||||
bad_folders_response += "<uuid>" + llsdRequest.folder_id.ToString() + "</uuid>";
|
||||
}
|
||||
else
|
||||
{
|
||||
inventoryitemstr = LLSDHelpers.SerialiseLLSDReply(reply);
|
||||
inventoryitemstr = inventoryitemstr.Replace("<llsd><map><key>folders</key><array>", "");
|
||||
inventoryitemstr = inventoryitemstr.Replace("</array></map></llsd>", "");
|
||||
}
|
||||
|
||||
response += inventoryitemstr;
|
||||
}
|
||||
|
||||
if (response.Length == 0)
|
||||
{
|
||||
/* Viewers expect a bad_folders array when not available */
|
||||
if (bad_folders_response.Length != 0)
|
||||
{
|
||||
response = "<llsd><map><key>bad_folders</key><array>" + bad_folders_response + "</array></map></llsd>";
|
||||
}
|
||||
else
|
||||
{
|
||||
response = "<llsd><map><key>folders</key><array /></map></llsd>";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (bad_folders_response.Length != 0)
|
||||
{
|
||||
response = "<llsd><map><key>folders</key><array>" + response + "</array><key>bad_folders</key><array>" + bad_folders_response + "</array></map></llsd>";
|
||||
}
|
||||
else
|
||||
{
|
||||
response = "<llsd><map><key>folders</key><array>" + response + "</array></map></llsd>";
|
||||
}
|
||||
}
|
||||
|
||||
// m_log.DebugFormat("[WEB FETCH INV DESC HANDLER]: Replying to CAPS fetch inventory request");
|
||||
//m_log.Debug("[WEB FETCH INV DESC HANDLER] "+response);
|
||||
|
||||
return response;
|
||||
|
||||
// }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handle the caps inventory descendents fetch.
|
||||
/// </summary>
|
||||
/// <param name="agentID"></param>
|
||||
/// <param name="folderID"></param>
|
||||
/// <param name="ownerID"></param>
|
||||
/// <param name="fetchFolders"></param>
|
||||
/// <param name="fetchItems"></param>
|
||||
/// <param name="sortOrder"></param>
|
||||
/// <param name="version"></param>
|
||||
/// <returns>An empty InventoryCollection if the inventory look up failed</returns>
|
||||
[Obsolete]
|
||||
private InventoryCollection Fetch(
|
||||
UUID agentID, UUID folderID, UUID ownerID,
|
||||
bool fetchFolders, bool fetchItems, int sortOrder, out int version, out int descendents)
|
||||
{
|
||||
//m_log.DebugFormat(
|
||||
// "[WEB FETCH INV DESC HANDLER]: Fetching folders ({0}), items ({1}) from {2} for agent {3}",
|
||||
// fetchFolders, fetchItems, folderID, agentID);
|
||||
|
||||
// FIXME MAYBE: We're not handling sortOrder!
|
||||
|
||||
version = 0;
|
||||
descendents = 0;
|
||||
|
||||
InventoryFolderImpl fold;
|
||||
if (m_LibraryService != null && m_LibraryService.LibraryRootFolder != null && agentID == m_LibraryService.LibraryRootFolder.Owner)
|
||||
{
|
||||
if ((fold = m_LibraryService.LibraryRootFolder.FindFolder(folderID)) != null)
|
||||
{
|
||||
InventoryCollection ret = new InventoryCollection();
|
||||
ret.Folders = new List<InventoryFolderBase>();
|
||||
ret.Items = fold.RequestListOfItems();
|
||||
descendents = ret.Folders.Count + ret.Items.Count;
|
||||
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
InventoryCollection contents = new InventoryCollection();
|
||||
|
||||
if (folderID != UUID.Zero)
|
||||
{
|
||||
InventoryCollection fetchedContents = m_InventoryService.GetFolderContent(agentID, folderID);
|
||||
|
||||
if (fetchedContents == null)
|
||||
{
|
||||
m_log.WarnFormat("[WEB FETCH INV DESC HANDLER]: Could not get contents of folder {0} for user {1}", folderID, agentID);
|
||||
return contents;
|
||||
}
|
||||
contents = fetchedContents;
|
||||
InventoryFolderBase containingFolder = new InventoryFolderBase();
|
||||
containingFolder.ID = folderID;
|
||||
containingFolder.Owner = agentID;
|
||||
containingFolder = m_InventoryService.GetFolder(containingFolder);
|
||||
|
||||
if (containingFolder != null)
|
||||
{
|
||||
//m_log.DebugFormat(
|
||||
// "[WEB FETCH INV DESC HANDLER]: Retrieved folder {0} {1} for agent id {2}",
|
||||
// containingFolder.Name, containingFolder.ID, agentID);
|
||||
|
||||
version = containingFolder.Version;
|
||||
|
||||
if (fetchItems)
|
||||
{
|
||||
List<InventoryItemBase> itemsToReturn = contents.Items;
|
||||
List<InventoryItemBase> originalItems = new List<InventoryItemBase>(itemsToReturn);
|
||||
|
||||
// descendents must only include the links, not the linked items we add
|
||||
descendents = originalItems.Count;
|
||||
|
||||
// Add target items for links in this folder before the links themselves.
|
||||
foreach (InventoryItemBase item in originalItems)
|
||||
{
|
||||
if (item.AssetType == (int)AssetType.Link)
|
||||
{
|
||||
InventoryItemBase linkedItem = m_InventoryService.GetItem(new InventoryItemBase(item.AssetID));
|
||||
|
||||
// Take care of genuinely broken links where the target doesn't exist
|
||||
// HACK: Also, don't follow up links that just point to other links. In theory this is legitimate,
|
||||
// but no viewer has been observed to set these up and this is the lazy way of avoiding cycles
|
||||
// rather than having to keep track of every folder requested in the recursion.
|
||||
if (linkedItem != null && linkedItem.AssetType != (int)AssetType.Link)
|
||||
itemsToReturn.Insert(0, linkedItem);
|
||||
}
|
||||
}
|
||||
|
||||
// Now scan for folder links and insert the items they target and those links at the head of the return data
|
||||
foreach (InventoryItemBase item in originalItems)
|
||||
{
|
||||
if (item.AssetType == (int)AssetType.LinkFolder)
|
||||
{
|
||||
InventoryCollection linkedFolderContents = m_InventoryService.GetFolderContent(ownerID, item.AssetID);
|
||||
List<InventoryItemBase> links = linkedFolderContents.Items;
|
||||
|
||||
itemsToReturn.InsertRange(0, links);
|
||||
|
||||
foreach (InventoryItemBase link in linkedFolderContents.Items)
|
||||
{
|
||||
// Take care of genuinely broken links where the target doesn't exist
|
||||
// HACK: Also, don't follow up links that just point to other links. In theory this is legitimate,
|
||||
// but no viewer has been observed to set these up and this is the lazy way of avoiding cycles
|
||||
// rather than having to keep track of every folder requested in the recursion.
|
||||
if (link != null)
|
||||
{
|
||||
// m_log.DebugFormat(
|
||||
// "[WEB FETCH INV DESC HANDLER]: Adding item {0} {1} from folder {2} linked from {3}",
|
||||
// link.Name, (AssetType)link.AssetType, item.AssetID, containingFolder.Name);
|
||||
|
||||
InventoryItemBase linkedItem
|
||||
= m_InventoryService.GetItem(new InventoryItemBase(link.AssetID));
|
||||
|
||||
if (linkedItem != null)
|
||||
itemsToReturn.Insert(0, linkedItem);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// foreach (InventoryItemBase item in contents.Items)
|
||||
// {
|
||||
// m_log.DebugFormat(
|
||||
// "[WEB FETCH INV DESC HANDLER]: Returning item {0}, type {1}, parent {2} in {3} {4}",
|
||||
// item.Name, (AssetType)item.AssetType, item.Folder, containingFolder.Name, containingFolder.ID);
|
||||
// }
|
||||
|
||||
// =====
|
||||
|
||||
//
|
||||
// foreach (InventoryItemBase linkedItem in linkedItemsToAdd)
|
||||
// {
|
||||
// m_log.DebugFormat(
|
||||
// "[WEB FETCH INV DESC HANDLER]: Inserted linked item {0} for link in folder {1} for agent {2}",
|
||||
// linkedItem.Name, folderID, agentID);
|
||||
//
|
||||
// contents.Items.Add(linkedItem);
|
||||
// }
|
||||
//
|
||||
// // If the folder requested contains links, then we need to send those folders first, otherwise the links
|
||||
// // will be broken in the viewer.
|
||||
// HashSet<UUID> linkedItemFolderIdsToSend = new HashSet<UUID>();
|
||||
// foreach (InventoryItemBase item in contents.Items)
|
||||
// {
|
||||
// if (item.AssetType == (int)AssetType.Link)
|
||||
// {
|
||||
// InventoryItemBase linkedItem = m_InventoryService.GetItem(new InventoryItemBase(item.AssetID));
|
||||
//
|
||||
// // Take care of genuinely broken links where the target doesn't exist
|
||||
// // HACK: Also, don't follow up links that just point to other links. In theory this is legitimate,
|
||||
// // but no viewer has been observed to set these up and this is the lazy way of avoiding cycles
|
||||
// // rather than having to keep track of every folder requested in the recursion.
|
||||
// if (linkedItem != null && linkedItem.AssetType != (int)AssetType.Link)
|
||||
// {
|
||||
// // We don't need to send the folder if source and destination of the link are in the same
|
||||
// // folder.
|
||||
// if (linkedItem.Folder != containingFolder.ID)
|
||||
// linkedItemFolderIdsToSend.Add(linkedItem.Folder);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// foreach (UUID linkedItemFolderId in linkedItemFolderIdsToSend)
|
||||
// {
|
||||
// m_log.DebugFormat(
|
||||
// "[WEB FETCH INV DESC HANDLER]: Recursively fetching folder {0} linked by item in folder {1} for agent {2}",
|
||||
// linkedItemFolderId, folderID, agentID);
|
||||
//
|
||||
// int dummyVersion;
|
||||
// InventoryCollection linkedCollection
|
||||
// = Fetch(
|
||||
// agentID, linkedItemFolderId, ownerID, fetchFolders, fetchItems, sortOrder, out dummyVersion);
|
||||
//
|
||||
// InventoryFolderBase linkedFolder = new InventoryFolderBase(linkedItemFolderId);
|
||||
// linkedFolder.Owner = agentID;
|
||||
// linkedFolder = m_InventoryService.GetFolder(linkedFolder);
|
||||
//
|
||||
//// contents.Folders.AddRange(linkedCollection.Folders);
|
||||
//
|
||||
// contents.Folders.Add(linkedFolder);
|
||||
// contents.Items.AddRange(linkedCollection.Items);
|
||||
// }
|
||||
// }
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Lost items don't really need a version
|
||||
version = 1;
|
||||
}
|
||||
|
||||
return contents;
|
||||
|
||||
}
|
||||
|
||||
private void AddLibraryFolders(List<LLSDFetchInventoryDescendents> fetchFolders, List<InventoryCollectionWithDescendents> result)
|
||||
{
|
||||
InventoryFolderImpl fold;
|
||||
if (m_LibraryService != null && m_LibraryService.LibraryRootFolder != null)
|
||||
{
|
||||
List<LLSDFetchInventoryDescendents> libfolders = fetchFolders.FindAll(f => f.owner_id == m_LibraryService.LibraryRootFolder.Owner);
|
||||
fetchFolders.RemoveAll(f => libfolders.Contains(f));
|
||||
|
||||
foreach (LLSDFetchInventoryDescendents f in libfolders)
|
||||
{
|
||||
if ((fold = m_LibraryService.LibraryRootFolder.FindFolder(f.folder_id)) != null)
|
||||
{
|
||||
InventoryCollectionWithDescendents ret = new InventoryCollectionWithDescendents();
|
||||
ret.Collection = new InventoryCollection();
|
||||
ret.Collection.Folders = new List<InventoryFolderBase>();
|
||||
ret.Collection.Items = fold.RequestListOfItems();
|
||||
ret.Collection.OwnerID = m_LibraryService.LibraryRootFolder.Owner;
|
||||
ret.Collection.FolderID = f.folder_id;
|
||||
ret.Collection.Version = fold.Version;
|
||||
|
||||
ret.Descendents = ret.Collection.Items.Count;
|
||||
|
||||
result.Add(ret);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private List<InventoryCollectionWithDescendents> Fetch(List<LLSDFetchInventoryDescendents> fetchFolders)
|
||||
{
|
||||
//m_log.DebugFormat(
|
||||
// "[WEB FETCH INV DESC HANDLER]: Fetching {0} folders for owner {1}", fetchFolders.Count, fetchFolders[0].owner_id);
|
||||
|
||||
// FIXME MAYBE: We're not handling sortOrder!
|
||||
|
||||
List<InventoryCollectionWithDescendents> result = new List<InventoryCollectionWithDescendents>();
|
||||
|
||||
AddLibraryFolders(fetchFolders, result);
|
||||
|
||||
if (fetchFolders.Count > 0)
|
||||
{
|
||||
UUID[] fids = new UUID[fetchFolders.Count];
|
||||
int i = 0;
|
||||
foreach (LLSDFetchInventoryDescendents f in fetchFolders)
|
||||
fids[i++] = f.folder_id;
|
||||
|
||||
InventoryCollection[] fetchedContents = m_InventoryService.GetMultipleFoldersContent(fetchFolders[0].owner_id, fids);
|
||||
|
||||
if (fetchedContents == null || (fetchedContents != null && fetchedContents.Length == 0))
|
||||
{
|
||||
//m_log.WarnFormat("[WEB FETCH INV DESC HANDLER]: Could not get contents of multiple folders for user {0}", fetchFolders[0].owner_id);
|
||||
return null;
|
||||
}
|
||||
|
||||
i = 0;
|
||||
// Do some post-processing. May need to fetch more from inv server for links
|
||||
foreach (InventoryCollection contents in fetchedContents)
|
||||
{
|
||||
InventoryCollectionWithDescendents coll = new InventoryCollectionWithDescendents();
|
||||
coll.Collection = contents;
|
||||
|
||||
// Find the original request
|
||||
LLSDFetchInventoryDescendents freq = fetchFolders[i++];
|
||||
|
||||
// The inventory server isn't sending FolderID in the collection...
|
||||
// Must fetch it individually
|
||||
if (contents.FolderID == UUID.Zero)
|
||||
{
|
||||
InventoryFolderBase containingFolder = new InventoryFolderBase();
|
||||
containingFolder.ID = freq.folder_id;
|
||||
containingFolder.Owner = freq.owner_id;
|
||||
containingFolder = m_InventoryService.GetFolder(containingFolder);
|
||||
|
||||
if (containingFolder != null)
|
||||
{
|
||||
contents.FolderID = containingFolder.ID;
|
||||
contents.OwnerID = containingFolder.Owner;
|
||||
contents.Version = containingFolder.Version;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_log.WarnFormat("[WEB FETCH INV DESC HANDLER]: Unable to fetch folder {0}", freq.folder_id);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (freq.fetch_items && contents.Items != null)
|
||||
{
|
||||
List<InventoryItemBase> itemsToReturn = contents.Items;
|
||||
List<InventoryItemBase> originalItems = new List<InventoryItemBase>(itemsToReturn);
|
||||
|
||||
// descendents must only include the links, not the linked items we add
|
||||
coll.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(coll.Collection.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, contents.FolderID);
|
||||
|
||||
InventoryItemBase linkedItem
|
||||
= m_InventoryService.GetItem(new InventoryItemBase(link.AssetID));
|
||||
|
||||
if (linkedItem != null)
|
||||
itemsToReturn.Insert(0, linkedItem);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
result.Add(coll);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/// <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;
|
||||
}
|
||||
}
|
||||
|
||||
struct InventoryCollectionWithDescendents
|
||||
{
|
||||
public InventoryCollection Collection;
|
||||
public int Descendents;
|
||||
}
|
||||
}
|
|
@ -29,12 +29,9 @@ 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
|
||||
{
|
||||
|
@ -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);
|
||||
IRequestHandler reqHandler
|
||||
= new RestStreamHandler(
|
||||
"POST",
|
||||
"/CAPS/WebFetchInvDesc/" /*+ UUID.Random()*/,
|
||||
webFetchHandler.FetchInventoryDescendentsRequest,
|
||||
"FetchInvDescendents",
|
||||
null);
|
||||
server.AddStreamHandler(reqHandler);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,120 @@
|
|||
/*
|
||||
* Copyright (c) Contributors, http://opensimulator.org/
|
||||
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of the OpenSimulator Project nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Specialized;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Imaging;
|
||||
using System.Reflection;
|
||||
using System.IO;
|
||||
using System.Web;
|
||||
using log4net;
|
||||
using Nini.Config;
|
||||
using OpenMetaverse;
|
||||
using OpenMetaverse.StructuredData;
|
||||
using OpenMetaverse.Imaging;
|
||||
using OpenSim.Framework;
|
||||
using OpenSim.Framework.Capabilities;
|
||||
using OpenSim.Framework.Servers;
|
||||
using OpenSim.Framework.Servers.HttpServer;
|
||||
using OpenSim.Region.Framework.Interfaces;
|
||||
using OpenSim.Services.Interfaces;
|
||||
using Caps = OpenSim.Framework.Capabilities.Caps;
|
||||
using OSDMap = OpenMetaverse.StructuredData.OSDMap;
|
||||
using OSDArray = OpenMetaverse.StructuredData.OSDArray;
|
||||
|
||||
namespace OpenSim.Capabilities.Handlers
|
||||
{
|
||||
public class GetDisplayNamesHandler : BaseStreamHandler
|
||||
{
|
||||
private static readonly ILog m_log =
|
||||
LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||
private IUserManagement m_UserManagement;
|
||||
|
||||
public GetDisplayNamesHandler(string path, IUserManagement umService, string name, string description)
|
||||
: base("GET", path, name, description)
|
||||
{
|
||||
m_UserManagement = umService;
|
||||
}
|
||||
|
||||
protected override byte[] ProcessRequest(string path, Stream request, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
|
||||
{
|
||||
m_log.DebugFormat("[GET_DISPLAY_NAMES]: called {0}", httpRequest.Url.Query);
|
||||
|
||||
NameValueCollection query = HttpUtility.ParseQueryString(httpRequest.Url.Query);
|
||||
string[] ids = query.GetValues("ids");
|
||||
|
||||
|
||||
if (m_UserManagement == null)
|
||||
{
|
||||
m_log.Error("[GET_DISPLAY_NAMES]: Cannot fetch display names without a user management component");
|
||||
httpResponse.StatusCode = (int)System.Net.HttpStatusCode.InternalServerError;
|
||||
return new byte[0];
|
||||
}
|
||||
|
||||
OSDMap osdReply = new OSDMap();
|
||||
OSDArray agents = new OSDArray();
|
||||
|
||||
osdReply["agents"] = agents;
|
||||
foreach (string id in ids)
|
||||
{
|
||||
UUID uuid = UUID.Zero;
|
||||
if (UUID.TryParse(id, out uuid))
|
||||
{
|
||||
string name = m_UserManagement.GetUserName(uuid);
|
||||
if (!string.IsNullOrEmpty(name))
|
||||
{
|
||||
string[] parts = name.Split(new char[] {' '});
|
||||
OSDMap osdname = new OSDMap();
|
||||
osdname["display_name_next_update"] = OSD.FromDate(DateTime.MinValue);
|
||||
osdname["display_name_expires"] = OSD.FromDate(DateTime.Now.AddMonths(1));
|
||||
osdname["display_name"] = OSD.FromString(name);
|
||||
osdname["legacy_first_name"] = parts[0];
|
||||
osdname["legacy_last_name"] = parts[1];
|
||||
osdname["username"] = OSD.FromString(name);
|
||||
osdname["id"] = OSD.FromUUID(uuid);
|
||||
osdname["is_display_name_default"] = OSD.FromBoolean(true);
|
||||
|
||||
agents.Add(osdname);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Full content request
|
||||
httpResponse.StatusCode = (int)System.Net.HttpStatusCode.OK;
|
||||
//httpResponse.ContentLength = ??;
|
||||
httpResponse.ContentType = "application/llsd+xml";
|
||||
|
||||
string reply = OSDParser.SerializeLLSDXmlString(osdReply);
|
||||
return System.Text.Encoding.UTF8.GetBytes(reply);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -35,13 +35,13 @@ using OpenMetaverse;
|
|||
|
||||
namespace OpenSim.Capabilities.Handlers
|
||||
{
|
||||
public class FetchInventory2ServerConnector : ServiceConnector
|
||||
public class GetDisplayNamesServerConnector : ServiceConnector
|
||||
{
|
||||
private IInventoryService m_InventoryService;
|
||||
private IUserManagement m_UserManagement;
|
||||
private string m_ConfigName = "CapsService";
|
||||
|
||||
public FetchInventory2ServerConnector(IConfigSource config, IHttpServer server, string configName)
|
||||
: base(config, server, configName)
|
||||
public GetDisplayNamesServerConnector(IConfigSource config, IHttpServer server, string configName) :
|
||||
base(config, server, configName)
|
||||
{
|
||||
if (configName != String.Empty)
|
||||
m_ConfigName = configName;
|
||||
|
@ -50,22 +50,22 @@ namespace OpenSim.Capabilities.Handlers
|
|||
if (serverConfig == null)
|
||||
throw new Exception(String.Format("No section '{0}' in config file", m_ConfigName));
|
||||
|
||||
string invService = serverConfig.GetString("InventoryService", String.Empty);
|
||||
string umService = serverConfig.GetString("AssetService", String.Empty);
|
||||
|
||||
if (invService == String.Empty)
|
||||
throw new Exception("No InventoryService in config file");
|
||||
if (umService == String.Empty)
|
||||
throw new Exception("No AssetService in config file");
|
||||
|
||||
Object[] args = new Object[] { config };
|
||||
m_InventoryService = ServerUtils.LoadPlugin<IInventoryService>(invService, args);
|
||||
m_UserManagement =
|
||||
ServerUtils.LoadPlugin<IUserManagement>(umService, args);
|
||||
|
||||
if (m_InventoryService == null)
|
||||
throw new Exception(String.Format("Failed to load InventoryService from {0}; config is {1}", invService, m_ConfigName));
|
||||
if (m_UserManagement == null)
|
||||
throw new Exception(String.Format("Failed to load UserManagement from {0}; config is {1}", umService, m_ConfigName));
|
||||
|
||||
FetchInventory2Handler fiHandler = new FetchInventory2Handler(m_InventoryService, UUID.Zero);
|
||||
IRequestHandler reqHandler
|
||||
= new RestStreamHandler(
|
||||
"POST", "/CAPS/FetchInventory/", fiHandler.FetchInventoryRequest, "FetchInventory", null);
|
||||
server.AddStreamHandler(reqHandler);
|
||||
string rurl = serverConfig.GetString("GetTextureRedirectURL");
|
||||
|
||||
server.AddStreamHandler(
|
||||
new GetDisplayNamesHandler("/CAPS/agents/", m_UserManagement, "GetDisplayNames", null));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -25,131 +25,229 @@
|
|||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Specialized;
|
||||
using System.Reflection;
|
||||
using System.IO;
|
||||
using System.Web;
|
||||
using log4net;
|
||||
using Nini.Config;
|
||||
using OpenMetaverse;
|
||||
using OpenMetaverse.StructuredData;
|
||||
using OpenMetaverse.Imaging;
|
||||
using OpenSim.Framework;
|
||||
using OpenSim.Framework.Servers;
|
||||
using OpenSim.Framework.Servers.HttpServer;
|
||||
using OpenSim.Services.Interfaces;
|
||||
using Caps = OpenSim.Framework.Capabilities.Caps;
|
||||
using System;
|
||||
using System.Collections.Specialized;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Imaging;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using System.Web;
|
||||
|
||||
namespace OpenSim.Capabilities.Handlers
|
||||
{
|
||||
public class GetMeshHandler
|
||||
public class GetMeshHandler : BaseStreamHandler
|
||||
{
|
||||
private static readonly ILog m_log =
|
||||
LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||
|
||||
private IAssetService m_assetService;
|
||||
|
||||
public const string DefaultFormat = "vnd.ll.mesh";
|
||||
// TODO: Change this to a config option
|
||||
private string m_RedirectURL = null;
|
||||
|
||||
public GetMeshHandler(IAssetService assService)
|
||||
public GetMeshHandler(string path, IAssetService assService, string name, string description, string redirectURL)
|
||||
: base("GET", path, name, description)
|
||||
{
|
||||
m_assetService = assService;
|
||||
}
|
||||
public Hashtable Handle(Hashtable request)
|
||||
{
|
||||
return ProcessGetMesh(request, UUID.Zero, null); ;
|
||||
m_RedirectURL = redirectURL;
|
||||
if (m_RedirectURL != null && !m_RedirectURL.EndsWith("/"))
|
||||
m_RedirectURL += "/";
|
||||
}
|
||||
|
||||
public Hashtable ProcessGetMesh(Hashtable request, UUID AgentId, Caps cap)
|
||||
protected override byte[] ProcessRequest(string path, Stream request, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
|
||||
{
|
||||
Hashtable responsedata = new Hashtable();
|
||||
// Try to parse the texture ID from the request URL
|
||||
NameValueCollection query = HttpUtility.ParseQueryString(httpRequest.Url.Query);
|
||||
string textureStr = query.GetOne("mesh_id");
|
||||
|
||||
if (m_assetService == null)
|
||||
{
|
||||
responsedata["int_response_code"] = (int)System.Net.HttpStatusCode.ServiceUnavailable;
|
||||
responsedata["str_response_string"] = "The asset service is unavailable";
|
||||
responsedata["keepalive"] = false;
|
||||
return responsedata;
|
||||
m_log.Error("[GETMESH]: Cannot fetch mesh " + textureStr + " without an asset service");
|
||||
httpResponse.StatusCode = (int)System.Net.HttpStatusCode.NotFound;
|
||||
}
|
||||
|
||||
responsedata["int_response_code"] = (int)System.Net.HttpStatusCode.BadRequest;
|
||||
responsedata["content_type"] = "text/plain";
|
||||
responsedata["int_bytes"] = 0;
|
||||
UUID meshID;
|
||||
if (!String.IsNullOrEmpty(textureStr) && UUID.TryParse(textureStr, out meshID))
|
||||
{
|
||||
// OK, we have an array with preferred formats, possibly with only one entry
|
||||
|
||||
string meshStr = string.Empty;
|
||||
if (request.ContainsKey("mesh_id"))
|
||||
meshStr = request["mesh_id"].ToString();
|
||||
httpResponse.StatusCode = (int)System.Net.HttpStatusCode.NotFound;
|
||||
AssetBase mesh;
|
||||
|
||||
if (String.IsNullOrEmpty(meshStr))
|
||||
return responsedata;
|
||||
if (!String.IsNullOrEmpty(m_RedirectURL))
|
||||
{
|
||||
// Only try to fetch locally cached meshes. Misses are redirected
|
||||
mesh = m_assetService.GetCached(meshID.ToString());
|
||||
|
||||
UUID meshID = UUID.Zero;
|
||||
if(!UUID.TryParse(meshStr, out meshID))
|
||||
return responsedata;
|
||||
if (mesh != null)
|
||||
{
|
||||
if (mesh.Type != (sbyte)AssetType.Mesh)
|
||||
{
|
||||
httpResponse.StatusCode = (int)System.Net.HttpStatusCode.NotFound;
|
||||
}
|
||||
WriteMeshData(httpRequest, httpResponse, mesh);
|
||||
}
|
||||
else
|
||||
{
|
||||
string textureUrl = m_RedirectURL + "?mesh_id="+ meshID.ToString();
|
||||
m_log.Debug("[GETMESH]: Redirecting mesh request to " + textureUrl);
|
||||
httpResponse.StatusCode = (int)OSHttpStatusCode.RedirectMovedPermanently;
|
||||
httpResponse.RedirectLocation = textureUrl;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
else // no redirect
|
||||
{
|
||||
// try the cache
|
||||
mesh = m_assetService.GetCached(meshID.ToString());
|
||||
|
||||
AssetBase mesh = m_assetService.Get(meshID.ToString());
|
||||
if (mesh == null)
|
||||
{
|
||||
responsedata["int_response_code"] = (int)System.Net.HttpStatusCode.NotFound;
|
||||
responsedata["str_response_string"] = "Mesh not found.";
|
||||
return responsedata;
|
||||
}
|
||||
// Fetch locally or remotely. Misses return a 404
|
||||
mesh = m_assetService.Get(meshID.ToString());
|
||||
|
||||
if (mesh.Type != (SByte)AssetType.Mesh)
|
||||
if (mesh != null)
|
||||
{
|
||||
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))
|
||||
if (mesh.Type != (sbyte)AssetType.Mesh)
|
||||
{
|
||||
// full mesh
|
||||
responsedata["str_response_string"] = Convert.ToBase64String(mesh.Data);
|
||||
responsedata["int_response_code"] = (int)System.Net.HttpStatusCode.OK;
|
||||
return responsedata;
|
||||
httpResponse.StatusCode = (int)System.Net.HttpStatusCode.NotFound;
|
||||
return null;
|
||||
}
|
||||
WriteMeshData(httpRequest, httpResponse, mesh);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
else // it was on the cache
|
||||
{
|
||||
if (mesh.Type != (sbyte)AssetType.Mesh)
|
||||
{
|
||||
httpResponse.StatusCode = (int)System.Net.HttpStatusCode.NotFound;
|
||||
return null;
|
||||
}
|
||||
WriteMeshData(httpRequest, httpResponse, mesh);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// range request
|
||||
// not found
|
||||
httpResponse.StatusCode = (int)System.Net.HttpStatusCode.NotFound;
|
||||
return null;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_log.Warn("[GETTEXTURE]: Failed to parse a mesh_id from GetMesh request: " + httpRequest.Url);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private void WriteMeshData(IOSHttpRequest request, IOSHttpResponse response, AssetBase texture)
|
||||
{
|
||||
string range = request.Headers.GetOne("Range");
|
||||
|
||||
if (!String.IsNullOrEmpty(range))
|
||||
{
|
||||
// Range request
|
||||
int start, end;
|
||||
if (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
|
||||
if (start >= mesh.Data.Length)
|
||||
if (start >= texture.Data.Length)
|
||||
{
|
||||
responsedata["str_response_string"] = "This range doesnt exist.";
|
||||
return responsedata;
|
||||
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, mesh.Data.Length - 1);
|
||||
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);
|
||||
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 (0 == start && len == texture.Data.Length)
|
||||
{
|
||||
response.StatusCode = (int)System.Net.HttpStatusCode.OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
response.StatusCode = (int)System.Net.HttpStatusCode.PartialContent;
|
||||
response.AddHeader("Content-Range", String.Format("bytes {0}-{1}/{2}", start, end, texture.Data.Length));
|
||||
}
|
||||
|
||||
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;
|
||||
response.ContentLength = len;
|
||||
response.ContentType = "application/vnd.ll.mesh";
|
||||
|
||||
response.Body.Write(texture.Data, start, len);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_log.Warn("[GETMESH]: Malformed Range header: " + range);
|
||||
response.StatusCode = (int)System.Net.HttpStatusCode.BadRequest;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Full content request
|
||||
response.StatusCode = (int)System.Net.HttpStatusCode.OK;
|
||||
response.ContentLength = texture.Data.Length;
|
||||
response.ContentType = "application/vnd.ll.mesh";
|
||||
response.Body.Write(texture.Data, 0, texture.Data.Length);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parse a range header.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// As per http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html,
|
||||
/// this obeys range headers with two values (e.g. 533-4165) and no second value (e.g. 533-).
|
||||
/// Where there is no value, -1 is returned.
|
||||
/// FIXME: Need to cover the case where only a second value is specified (e.g. -4165), probably by returning -1
|
||||
/// for start.</remarks>
|
||||
/// <returns></returns>
|
||||
/// <param name='header'></param>
|
||||
/// <param name='start'>Start of the range. Undefined if this was not a number.</param>
|
||||
/// <param name='end'>End of the range. Will be -1 if no end specified. Undefined if there was a raw string but this was not a number.</param>
|
||||
private bool TryParseRange(string header, out int start, out int end)
|
||||
{
|
||||
start = end = 0;
|
||||
|
||||
if (header.StartsWith("bytes="))
|
||||
{
|
||||
string[] rangeValues = header.Substring(6).Split('-');
|
||||
|
||||
if (rangeValues.Length == 2)
|
||||
{
|
||||
if (!Int32.TryParse(rangeValues[0], out start))
|
||||
return false;
|
||||
|
||||
string rawEnd = rangeValues[1];
|
||||
|
||||
if (rawEnd == "")
|
||||
{
|
||||
end = -1;
|
||||
return true;
|
||||
}
|
||||
else if (Int32.TryParse(rawEnd, out end))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
start = end = 0;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -64,15 +64,13 @@ namespace OpenSim.Capabilities.Handlers
|
|||
|
||||
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 GetTextureHandler("/CAPS/GetMesh/" /*+ UUID.Random() */, m_AssetService, "GetMesh", null, rurl));
|
||||
|
||||
rurl = serverConfig.GetString("GetMesh2RedirectURL");
|
||||
|
||||
server.AddStreamHandler(
|
||||
new GetTextureHandler("/CAPS/GetMesh2/" /*+ UUID.Random() */, m_AssetService, "GetMesh2", null, rurl));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -47,34 +47,39 @@ 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;
|
||||
|
@ -89,39 +94,30 @@ 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>
|
||||
|
@ -132,7 +128,7 @@ namespace OpenSim.Capabilities.Handlers
|
|||
/// <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,6 +137,31 @@ namespace OpenSim.Capabilities.Handlers
|
|||
if (format != DefaultFormat)
|
||||
fullID = fullID + "-" + format;
|
||||
|
||||
if (!String.IsNullOrEmpty(m_RedirectURL))
|
||||
{
|
||||
// Only try to fetch locally cached textures. Misses are redirected
|
||||
texture = m_assetService.GetCached(fullID);
|
||||
|
||||
if (texture != null)
|
||||
{
|
||||
if (texture.Type != (sbyte)AssetType.Texture)
|
||||
{
|
||||
httpResponse.StatusCode = (int)System.Net.HttpStatusCode.NotFound;
|
||||
return true;
|
||||
}
|
||||
WriteTextureData(httpRequest, httpResponse, texture, format);
|
||||
}
|
||||
else
|
||||
{
|
||||
string textureUrl = m_RedirectURL + "?texture_id="+ textureID.ToString();
|
||||
m_log.Debug("[GETTEXTURE]: Redirecting texture request to " + textureUrl);
|
||||
httpResponse.StatusCode = (int)OSHttpStatusCode.RedirectMovedPermanently;
|
||||
httpResponse.RedirectLocation = textureUrl;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else // no redirect
|
||||
{
|
||||
// try the cache
|
||||
texture = m_assetService.GetCached(fullID);
|
||||
|
||||
|
@ -154,11 +175,13 @@ namespace OpenSim.Capabilities.Handlers
|
|||
if (texture != null)
|
||||
{
|
||||
if (texture.Type != (sbyte)AssetType.Texture)
|
||||
{
|
||||
httpResponse.StatusCode = (int)System.Net.HttpStatusCode.NotFound;
|
||||
return true;
|
||||
|
||||
}
|
||||
if (format == DefaultFormat)
|
||||
{
|
||||
WriteTextureData(request, response, texture, format);
|
||||
WriteTextureData(httpRequest, httpResponse, texture, format);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
|
@ -172,7 +195,7 @@ namespace OpenSim.Capabilities.Handlers
|
|||
newTexture.Temporary = true;
|
||||
newTexture.Local = true;
|
||||
m_assetService.Store(newTexture);
|
||||
WriteTextureData(request, response, newTexture, format);
|
||||
WriteTextureData(httpRequest, httpResponse, newTexture, format);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -180,37 +203,26 @@ namespace OpenSim.Capabilities.Handlers
|
|||
else // it was on the cache
|
||||
{
|
||||
// m_log.DebugFormat("[GETTEXTURE]: texture was in the cache");
|
||||
WriteTextureData(request, response, texture, format);
|
||||
WriteTextureData(httpRequest, httpResponse, texture, format);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// not found
|
||||
// m_log.Warn("[GETTEXTURE]: Texture " + textureID + " not found");
|
||||
httpResponse.StatusCode = (int)System.Net.HttpStatusCode.NotFound;
|
||||
return true;
|
||||
}
|
||||
|
||||
//response = new Hashtable();
|
||||
|
||||
|
||||
//WriteTextureData(request,response,null,format);
|
||||
// not found
|
||||
//m_log.Warn("[GETTEXTURE]: Texture " + textureID + " not found");
|
||||
return false;
|
||||
}
|
||||
|
||||
private void WriteTextureData(Hashtable request, Hashtable response, AssetBase texture, string format)
|
||||
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,28 +309,73 @@ 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())
|
||||
{
|
||||
EncoderParameters myEncoderParameters = new EncoderParameters();
|
||||
myEncoderParameters.Param[0] = new EncoderParameter(Encoder.Quality, 95L);
|
||||
|
||||
// Save bitmap to stream
|
||||
|
@ -323,7 +388,7 @@ namespace OpenSim.Capabilities.Handlers
|
|||
}
|
||||
else
|
||||
m_log.WarnFormat("[GETTEXTURE]: No such codec {0}", format);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
|
@ -340,11 +405,12 @@ namespace OpenSim.Capabilities.Handlers
|
|||
if (image != null)
|
||||
image.Dispose();
|
||||
|
||||
if(managedImage != null)
|
||||
managedImage.Clear();
|
||||
if (imgstream != null)
|
||||
{
|
||||
imgstream.Close();
|
||||
imgstream.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
|
|
@ -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]
|
||||
|
@ -61,4 +60,3 @@ namespace OpenSim.Capabilities.Handlers.GetTexture.Tests
|
|||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
|
|
@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
|
|||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
[assembly: AssemblyVersion(OpenSim.VersionInfo.AssemblyVersionNumber)]
|
||||
[assembly: AssemblyVersion("0.8.2.*")]
|
||||
|
||||
|
|
|
@ -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));
|
||||
|
||||
// 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"));
|
||||
|
||||
server.AddStreamHandler(new AgentPreferencesServerPostHandler(m_AgentPreferencesService, auth));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -107,18 +107,18 @@ namespace OpenSim.Framework.Capabilities
|
|||
/// <returns></returns>
|
||||
public static byte[] LLSDSerialize(object obj)
|
||||
{
|
||||
using(StringWriter sw = new StringWriter())
|
||||
using(XmlTextWriter writer = new XmlTextWriter(sw))
|
||||
{
|
||||
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();
|
||||
|
||||
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
|
||||
{
|
||||
|
|
|
@ -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,33 +40,18 @@ namespace OpenSim.Framework.Capabilities
|
|||
|
||||
public static string SerialiseLLSDReply(object obj)
|
||||
{
|
||||
using(StringWriter sw = new StringWriter())
|
||||
using(XmlTextWriter writer = new XmlTextWriter(sw))
|
||||
{
|
||||
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.Flush();
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
{
|
||||
[OSDMap]
|
||||
public class LLSDItemUpdate
|
||||
{
|
||||
public UUID item_id;
|
||||
|
||||
public LLSDItemUpdate()
|
||||
{
|
||||
void Remove(string name);
|
||||
void Remove(UUID id);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 (idtype == typeof(byte[]))
|
||||
{
|
||||
if (((byte[])id).Length < 16)
|
||||
if (((byte[])id).Length == 0)
|
||||
return UUID.Zero;
|
||||
else if (((byte[])id).Length == 16)
|
||||
return new UUID((byte[])id, 0);
|
||||
}
|
||||
else if (id.GetType() == typeof(string))
|
||||
{
|
||||
if (((string)id).Length == 0)
|
||||
return UUID.Zero;
|
||||
else if (((string)id).Length == 36)
|
||||
return new UUID((string)id);
|
||||
}
|
||||
|
||||
throw new Exception("Failed to convert db value to UUID: " + id.ToString());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -71,8 +71,6 @@ namespace OpenSim.Data
|
|||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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,7 +154,17 @@ 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)
|
||||
{
|
||||
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)
|
||||
|
@ -176,16 +184,9 @@ namespace OpenSim.Data.MySQL
|
|||
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))
|
||||
{
|
||||
try
|
||||
{
|
||||
using (cmd)
|
||||
{
|
||||
// create unix epoch time
|
||||
int now = (int)Utils.DateTimeToUnixTime(DateTime.UtcNow);
|
||||
|
@ -201,15 +202,15 @@ namespace OpenSim.Data.MySQL
|
|||
cmd.Parameters.AddWithValue("?asset_flags", (int)asset.Flags);
|
||||
cmd.Parameters.AddWithValue("?data", asset.Data);
|
||||
cmd.ExecuteNonQuery();
|
||||
dbcon.Close();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -225,6 +226,8 @@ namespace OpenSim.Data.MySQL
|
|||
= new MySqlCommand("update assets set access_time=?access_time where id=?id", dbcon))
|
||||
{
|
||||
try
|
||||
{
|
||||
using (cmd)
|
||||
{
|
||||
// create unix epoch time
|
||||
int now = (int)Utils.DateTimeToUnixTime(DateTime.UtcNow);
|
||||
|
@ -232,6 +235,7 @@ namespace OpenSim.Data.MySQL
|
|||
cmd.Parameters.AddWithValue("?access_time", now);
|
||||
cmd.ExecuteNonQuery();
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
m_log.Error(
|
||||
|
@ -241,7 +245,6 @@ namespace OpenSim.Data.MySQL
|
|||
e);
|
||||
}
|
||||
}
|
||||
dbcon.Close();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -274,7 +277,6 @@ namespace OpenSim.Data.MySQL
|
|||
}
|
||||
}
|
||||
}
|
||||
dbcon.Close();
|
||||
}
|
||||
|
||||
bool[] results = new bool[uuids.Length];
|
||||
|
@ -339,7 +341,6 @@ namespace OpenSim.Data.MySQL
|
|||
e);
|
||||
}
|
||||
}
|
||||
dbcon.Close();
|
||||
}
|
||||
|
||||
return retList;
|
||||
|
@ -356,7 +357,6 @@ namespace OpenSim.Data.MySQL
|
|||
cmd.Parameters.AddWithValue("?id", id);
|
||||
cmd.ExecuteNonQuery();
|
||||
}
|
||||
dbcon.Close();
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
|
@ -59,7 +59,6 @@ namespace OpenSim.Data.MySQL
|
|||
dbcon.Open();
|
||||
Migration m = new Migration(dbcon, Assembly, "AuthStore");
|
||||
m.Update();
|
||||
dbcon.Close();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -77,8 +76,8 @@ namespace OpenSim.Data.MySQL
|
|||
{
|
||||
cmd.Parameters.AddWithValue("?principalID", principalID.ToString());
|
||||
|
||||
using(IDataReader result = cmd.ExecuteReader())
|
||||
{
|
||||
IDataReader result = cmd.ExecuteReader();
|
||||
|
||||
if (result.Read())
|
||||
{
|
||||
ret.PrincipalID = principalID;
|
||||
|
@ -93,18 +92,15 @@ namespace OpenSim.Data.MySQL
|
|||
ret.Data[s] = result[s].ToString();
|
||||
}
|
||||
|
||||
dbcon.Close();
|
||||
return ret;
|
||||
}
|
||||
else
|
||||
{
|
||||
dbcon.Close();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void CheckColumnNames(IDataReader result)
|
||||
{
|
||||
|
|
|
@ -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();
|
||||
|
@ -445,6 +471,7 @@ namespace OpenSim.Data.MySQL
|
|||
reader.Close();
|
||||
}
|
||||
}
|
||||
|
||||
dbcon.Close();
|
||||
}
|
||||
|
||||
|
@ -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,72 +44,23 @@ 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
|
||||
{
|
||||
cmd.Connection = dbcon;
|
||||
|
||||
try
|
||||
{
|
||||
int ret = cmd.ExecuteNonQuery();
|
||||
cmd.Connection = null;
|
||||
return ret;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
m_log.Error(e.Message, e);
|
||||
m_log.Error(Environment.StackTrace.ToString());
|
||||
cmd.Connection = null;
|
||||
return 0;
|
||||
}
|
||||
return cmd.ExecuteNonQuery();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
|
@ -119,3 +70,4 @@ namespace OpenSim.Data.MySQL
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -29,9 +29,11 @@ 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
|
||||
{
|
||||
|
@ -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;
|
||||
m_connectionString = connectionString;
|
||||
|
||||
CommonConstruct(storeName);
|
||||
}
|
||||
|
||||
protected void CommonConstruct(string storeName)
|
||||
{
|
||||
if (storeName != String.Empty)
|
||||
{
|
||||
// We always use a new connection for any Migrations
|
||||
using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
|
||||
{
|
||||
dbcon.Open();
|
||||
|
@ -117,69 +106,30 @@ 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);
|
||||
}
|
||||
|
@ -187,33 +137,11 @@ namespace OpenSim.Data.MySQL
|
|||
|
||||
protected T[] DoQuery(MySqlCommand cmd)
|
||||
{
|
||||
if (m_trans == null)
|
||||
{
|
||||
List<T> result = new List<T>();
|
||||
|
||||
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())
|
||||
|
@ -236,7 +164,7 @@ namespace OpenSim.Data.MySQL
|
|||
if (m_Fields[name].FieldType == typeof(bool))
|
||||
{
|
||||
int v = Convert.ToInt32(reader[name]);
|
||||
m_Fields[name].SetValue(row, v != 0);
|
||||
m_Fields[name].SetValue(row, v != 0 ? true : false);
|
||||
}
|
||||
else if (m_Fields[name].FieldType == typeof(UUID))
|
||||
{
|
||||
|
@ -247,11 +175,6 @@ namespace OpenSim.Data.MySQL
|
|||
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]);
|
||||
|
@ -276,7 +199,8 @@ namespace OpenSim.Data.MySQL
|
|||
result.Add(row);
|
||||
}
|
||||
}
|
||||
cmd.Connection = null;
|
||||
}
|
||||
|
||||
return result.ToArray();
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -428,27 +351,15 @@ namespace OpenSim.Data.MySQL
|
|||
}
|
||||
|
||||
public object DoQueryScalar(MySqlCommand cmd)
|
||||
{
|
||||
if (m_trans == null)
|
||||
{
|
||||
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;
|
||||
|
||||
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)
|
||||
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
|
@ -899,7 +886,6 @@ namespace OpenSim.Data.MySQL
|
|||
if (item != null)
|
||||
list.Add(item);
|
||||
}
|
||||
dbcon.Close();
|
||||
return list;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -60,7 +60,6 @@ namespace OpenSim.Data.MySQL
|
|||
dbcon.Open();
|
||||
Migration m = new Migration(dbcon, Assembly, "GridStore");
|
||||
m.Update();
|
||||
dbcon.Close();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -81,15 +80,16 @@ namespace OpenSim.Data.MySQL
|
|||
}
|
||||
}
|
||||
|
||||
public RegionData GetSpecific(string regionName, UUID scopeID)
|
||||
public RegionData Get(int posX, int posY, UUID scopeID)
|
||||
{
|
||||
string command = "select * from `" + m_Realm + "` where regionName = ?regionName";
|
||||
string command = "select * from `"+m_Realm+"` where locX = ?posX and locY = ?posY";
|
||||
if (scopeID != UUID.Zero)
|
||||
command += " and ScopeID = ?scopeID";
|
||||
|
||||
using (MySqlCommand cmd = new MySqlCommand(command))
|
||||
{
|
||||
cmd.Parameters.AddWithValue("?regionName", regionName);
|
||||
cmd.Parameters.AddWithValue("?posX", posX.ToString());
|
||||
cmd.Parameters.AddWithValue("?posY", posY.ToString());
|
||||
cmd.Parameters.AddWithValue("?scopeID", scopeID.ToString());
|
||||
|
||||
List<RegionData> ret = RunCommand(cmd);
|
||||
|
@ -98,48 +98,6 @@ namespace OpenSim.Data.MySQL
|
|||
|
||||
return ret[0];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public RegionData Get(int posX, int posY, UUID scopeID)
|
||||
{
|
||||
string command = "select * from `" + m_Realm + "` where locX between ?startX and ?endX and locY between ?startY and ?endY";
|
||||
if (scopeID != UUID.Zero)
|
||||
command += " and ScopeID = ?scopeID";
|
||||
|
||||
int startX = posX - (int)Constants.MaximumRegionSize;
|
||||
int startY = posY - (int)Constants.MaximumRegionSize;
|
||||
int endX = posX;
|
||||
int endY = posY;
|
||||
|
||||
List<RegionData> ret;
|
||||
using (MySqlCommand cmd = new MySqlCommand(command))
|
||||
{
|
||||
cmd.Parameters.AddWithValue("?startX", startX.ToString());
|
||||
cmd.Parameters.AddWithValue("?startY", startY.ToString());
|
||||
cmd.Parameters.AddWithValue("?endX", endX.ToString());
|
||||
cmd.Parameters.AddWithValue("?endY", endY.ToString());
|
||||
cmd.Parameters.AddWithValue("?scopeID", scopeID.ToString());
|
||||
|
||||
ret = RunCommand(cmd);
|
||||
}
|
||||
|
||||
if (ret.Count == 0)
|
||||
return null;
|
||||
|
||||
// find the first that contains pos
|
||||
RegionData rg = null;
|
||||
foreach (RegionData r in ret)
|
||||
{
|
||||
if (posX >= r.posX && posX < r.posX + r.sizeX
|
||||
&& posY >= r.posY && posY < r.posY + r.sizeY)
|
||||
{
|
||||
rg = r;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return rg;
|
||||
}
|
||||
|
||||
public RegionData Get(UUID regionID, UUID scopeID)
|
||||
|
@ -163,7 +121,6 @@ namespace OpenSim.Data.MySQL
|
|||
|
||||
public List<RegionData> Get(int startX, int startY, int endX, int endY, UUID scopeID)
|
||||
{
|
||||
/* fix size regions
|
||||
string command = "select * from `"+m_Realm+"` where locX between ?startX and ?endX and locY between ?startY and ?endY";
|
||||
if (scopeID != UUID.Zero)
|
||||
command += " and ScopeID = ?scopeID";
|
||||
|
@ -178,38 +135,6 @@ namespace OpenSim.Data.MySQL
|
|||
|
||||
return RunCommand(cmd);
|
||||
}
|
||||
*/
|
||||
string command = "select * from `" + m_Realm + "` where locX between ?startX and ?endX and locY between ?startY and ?endY";
|
||||
if (scopeID != UUID.Zero)
|
||||
command += " and ScopeID = ?scopeID";
|
||||
|
||||
int qstartX = startX - (int)Constants.MaximumRegionSize;
|
||||
int qstartY = startY - (int)Constants.MaximumRegionSize;
|
||||
|
||||
List<RegionData> dbret;
|
||||
using (MySqlCommand cmd = new MySqlCommand(command))
|
||||
{
|
||||
cmd.Parameters.AddWithValue("?startX", qstartX.ToString());
|
||||
cmd.Parameters.AddWithValue("?startY", qstartY.ToString());
|
||||
cmd.Parameters.AddWithValue("?endX", endX.ToString());
|
||||
cmd.Parameters.AddWithValue("?endY", endY.ToString());
|
||||
cmd.Parameters.AddWithValue("?scopeID", scopeID.ToString());
|
||||
|
||||
dbret = RunCommand(cmd);
|
||||
}
|
||||
|
||||
List<RegionData> ret = new List<RegionData>();
|
||||
|
||||
if (dbret.Count == 0)
|
||||
return ret;
|
||||
|
||||
foreach (RegionData r in dbret)
|
||||
{
|
||||
if (r.posX + r.sizeX > startX && r.posX <= endX
|
||||
&& r.posY + r.sizeY > startY && r.posY <= endY)
|
||||
ret.Add(r);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
public List<RegionData> RunCommand(MySqlCommand cmd)
|
||||
|
@ -262,8 +187,6 @@ namespace OpenSim.Data.MySQL
|
|||
retList.Add(ret);
|
||||
}
|
||||
}
|
||||
cmd.Connection = null;
|
||||
dbcon.Close();
|
||||
}
|
||||
|
||||
return retList;
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -46,21 +46,17 @@ namespace OpenSim.Data.MySQL
|
|||
{
|
||||
string[] words = query.Split(new char[] {' '});
|
||||
|
||||
bool valid = false;
|
||||
|
||||
for (int i = 0 ; i < words.Length ; i++)
|
||||
{
|
||||
if (words[i].Length > 2)
|
||||
valid = true;
|
||||
// if (words[i].Length < 3)
|
||||
// {
|
||||
// if (i != words.Length - 1)
|
||||
// Array.Copy(words, i + 1, words, i, words.Length - i - 1);
|
||||
// Array.Resize(ref words, words.Length - 1);
|
||||
// }
|
||||
if (words[i].Length < 3)
|
||||
{
|
||||
if (i != words.Length - 1)
|
||||
Array.Copy(words, i + 1, words, i, words.Length - i - 1);
|
||||
Array.Resize(ref words, words.Length - 1);
|
||||
}
|
||||
}
|
||||
|
||||
if ((!valid) || words.Length == 0)
|
||||
if (words.Length == 0)
|
||||
return new UserAccountData[0];
|
||||
|
||||
if (words.Length > 2)
|
||||
|
@ -70,13 +66,13 @@ namespace OpenSim.Data.MySQL
|
|||
{
|
||||
if (words.Length == 1)
|
||||
{
|
||||
cmd.CommandText = String.Format("select * from {0} where (ScopeID=?ScopeID or ScopeID='00000000-0000-0000-0000-000000000000') and (FirstName like ?search or LastName like ?search) and active=1", m_Realm);
|
||||
cmd.CommandText = String.Format("select * from {0} where (ScopeID=?ScopeID or ScopeID='00000000-0000-0000-0000-000000000000') and (FirstName like ?search or LastName like ?search)", m_Realm);
|
||||
cmd.Parameters.AddWithValue("?search", "%" + words[0] + "%");
|
||||
cmd.Parameters.AddWithValue("?ScopeID", scopeID.ToString());
|
||||
}
|
||||
else
|
||||
{
|
||||
cmd.CommandText = String.Format("select * from {0} where (ScopeID=?ScopeID or ScopeID='00000000-0000-0000-0000-000000000000') and (FirstName like ?searchFirst and LastName like ?searchLast) and active=1", m_Realm);
|
||||
cmd.CommandText = String.Format("select * from {0} where (ScopeID=?ScopeID or ScopeID='00000000-0000-0000-0000-000000000000') and (FirstName like ?searchFirst or LastName like ?searchLast)", m_Realm);
|
||||
cmd.Parameters.AddWithValue("?searchFirst", "%" + words[0] + "%");
|
||||
cmd.Parameters.AddWithValue("?searchLast", "%" + words[1] + "%");
|
||||
cmd.Parameters.AddWithValue("?ScopeID", scopeID.ToString());
|
||||
|
@ -85,21 +81,5 @@ namespace OpenSim.Data.MySQL
|
|||
return DoQuery(cmd);
|
||||
}
|
||||
}
|
||||
|
||||
public UserAccountData[] GetUsersWhere(UUID scopeID, string where)
|
||||
{
|
||||
using (MySqlCommand cmd = new MySqlCommand())
|
||||
{
|
||||
if (scopeID != UUID.Zero)
|
||||
{
|
||||
where = "(ScopeID=?ScopeID or ScopeID='00000000-0000-0000-0000-000000000000') and (" + where + ")";
|
||||
cmd.Parameters.AddWithValue("?ScopeID", scopeID.ToString());
|
||||
}
|
||||
|
||||
cmd.CommandText = String.Format("select * from {0} where " + where, m_Realm);
|
||||
|
||||
return DoQuery(cmd);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -69,7 +69,6 @@ namespace OpenSim.Data.MySQL
|
|||
|
||||
Migration m = new Migration(dbcon, Assembly, "UserProfiles");
|
||||
m.Update();
|
||||
dbcon.Close();
|
||||
}
|
||||
}
|
||||
#endregion Member Functions
|
||||
|
@ -90,7 +89,7 @@ namespace OpenSim.Data.MySQL
|
|||
|
||||
using (MySqlConnection dbcon = new MySqlConnection(ConnectionString))
|
||||
{
|
||||
const string query = "SELECT classifieduuid, name FROM classifieds WHERE creatoruuid = ?Id";
|
||||
string query = "SELECT classifieduuid, name FROM classifieds WHERE creatoruuid = ?Id";
|
||||
dbcon.Open();
|
||||
using (MySqlCommand cmd = new MySqlCommand(query, dbcon))
|
||||
{
|
||||
|
@ -112,7 +111,8 @@ namespace OpenSim.Data.MySQL
|
|||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
m_log.ErrorFormat("[PROFILES_DATA] GetClassifiedRecords exception {0}", e.Message);
|
||||
m_log.ErrorFormat("[PROFILES_DATA]" +
|
||||
": UserAccount exception {0}", e.Message);
|
||||
}
|
||||
n.Add("classifieduuid", OSD.FromUUID(Id));
|
||||
n.Add("name", OSD.FromString(Name));
|
||||
|
@ -121,58 +121,58 @@ namespace OpenSim.Data.MySQL
|
|||
}
|
||||
}
|
||||
}
|
||||
dbcon.Close();
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
public bool UpdateClassifiedRecord(UserClassifiedAdd ad, ref string result)
|
||||
{
|
||||
const string query =
|
||||
"INSERT INTO classifieds ("
|
||||
+ "`classifieduuid`,"
|
||||
+ "`creatoruuid`,"
|
||||
+ "`creationdate`,"
|
||||
+ "`expirationdate`,"
|
||||
+ "`category`,"
|
||||
+ "`name`,"
|
||||
+ "`description`,"
|
||||
+ "`parceluuid`,"
|
||||
+ "`parentestate`,"
|
||||
+ "`snapshotuuid`,"
|
||||
+ "`simname`,"
|
||||
+ "`posglobal`,"
|
||||
+ "`parcelname`,"
|
||||
+ "`classifiedflags`,"
|
||||
+ "`priceforlisting`) "
|
||||
+ "VALUES ("
|
||||
+ "?ClassifiedId,"
|
||||
+ "?CreatorId,"
|
||||
+ "?CreatedDate,"
|
||||
+ "?ExpirationDate,"
|
||||
+ "?Category,"
|
||||
+ "?Name,"
|
||||
+ "?Description,"
|
||||
+ "?ParcelId,"
|
||||
+ "?ParentEstate,"
|
||||
+ "?SnapshotId,"
|
||||
+ "?SimName,"
|
||||
+ "?GlobalPos,"
|
||||
+ "?ParcelName,"
|
||||
+ "?Flags,"
|
||||
+ "?ListingPrice ) "
|
||||
+ "ON DUPLICATE KEY UPDATE "
|
||||
+ "category=?Category, "
|
||||
+ "expirationdate=?ExpirationDate, "
|
||||
+ "name=?Name, "
|
||||
+ "description=?Description, "
|
||||
+ "parentestate=?ParentEstate, "
|
||||
+ "posglobal=?GlobalPos, "
|
||||
+ "parcelname=?ParcelName, "
|
||||
+ "classifiedflags=?Flags, "
|
||||
+ "priceforlisting=?ListingPrice, "
|
||||
+ "snapshotuuid=?SnapshotId"
|
||||
;
|
||||
string query = string.Empty;
|
||||
|
||||
|
||||
query += "INSERT INTO classifieds (";
|
||||
query += "`classifieduuid`,";
|
||||
query += "`creatoruuid`,";
|
||||
query += "`creationdate`,";
|
||||
query += "`expirationdate`,";
|
||||
query += "`category`,";
|
||||
query += "`name`,";
|
||||
query += "`description`,";
|
||||
query += "`parceluuid`,";
|
||||
query += "`parentestate`,";
|
||||
query += "`snapshotuuid`,";
|
||||
query += "`simname`,";
|
||||
query += "`posglobal`,";
|
||||
query += "`parcelname`,";
|
||||
query += "`classifiedflags`,";
|
||||
query += "`priceforlisting`) ";
|
||||
query += "VALUES (";
|
||||
query += "?ClassifiedId,";
|
||||
query += "?CreatorId,";
|
||||
query += "?CreatedDate,";
|
||||
query += "?ExpirationDate,";
|
||||
query += "?Category,";
|
||||
query += "?Name,";
|
||||
query += "?Description,";
|
||||
query += "?ParcelId,";
|
||||
query += "?ParentEstate,";
|
||||
query += "?SnapshotId,";
|
||||
query += "?SimName,";
|
||||
query += "?GlobalPos,";
|
||||
query += "?ParcelName,";
|
||||
query += "?Flags,";
|
||||
query += "?ListingPrice ) ";
|
||||
query += "ON DUPLICATE KEY UPDATE ";
|
||||
query += "category=?Category, ";
|
||||
query += "expirationdate=?ExpirationDate, ";
|
||||
query += "name=?Name, ";
|
||||
query += "description=?Description, ";
|
||||
query += "parentestate=?ParentEstate, ";
|
||||
query += "posglobal=?GlobalPos, ";
|
||||
query += "parcelname=?ParcelName, ";
|
||||
query += "classifiedflags=?Flags, ";
|
||||
query += "priceforlisting=?ListingPrice, ";
|
||||
query += "snapshotuuid=?SnapshotId";
|
||||
|
||||
if(string.IsNullOrEmpty(ad.ParcelName))
|
||||
ad.ParcelName = "Unknown";
|
||||
|
@ -228,12 +228,12 @@ namespace OpenSim.Data.MySQL
|
|||
|
||||
cmd.ExecuteNonQuery();
|
||||
}
|
||||
dbcon.Close();
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
m_log.ErrorFormat("[PROFILES_DATA]: UpdateClassifiedRecord exception {0}", e.Message);
|
||||
m_log.ErrorFormat("[PROFILES_DATA]" +
|
||||
": ClassifiedesUpdate exception {0}", e.Message);
|
||||
result = e.Message;
|
||||
return false;
|
||||
}
|
||||
|
@ -242,7 +242,10 @@ namespace OpenSim.Data.MySQL
|
|||
|
||||
public bool DeleteClassifiedRecord(UUID recordId)
|
||||
{
|
||||
const string query = "DELETE FROM classifieds WHERE classifieduuid = ?recordId";
|
||||
string query = string.Empty;
|
||||
|
||||
query += "DELETE FROM classifieds WHERE ";
|
||||
query += "classifieduuid = ?recordId";
|
||||
|
||||
try
|
||||
{
|
||||
|
@ -255,12 +258,12 @@ namespace OpenSim.Data.MySQL
|
|||
cmd.Parameters.AddWithValue("?recordId", recordId.ToString());
|
||||
cmd.ExecuteNonQuery();
|
||||
}
|
||||
dbcon.Close();
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
m_log.ErrorFormat("[PROFILES_DATA]: DeleteClassifiedRecord exception {0}", e.Message);
|
||||
m_log.ErrorFormat("[PROFILES_DATA]" +
|
||||
": DeleteClassifiedRecord exception {0}", e.Message);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
@ -268,8 +271,10 @@ namespace OpenSim.Data.MySQL
|
|||
|
||||
public bool GetClassifiedInfo(ref UserClassifiedAdd ad, ref string result)
|
||||
{
|
||||
string query = string.Empty;
|
||||
|
||||
const string query = "SELECT * FROM classifieds WHERE classifieduuid = ?AdId";
|
||||
query += "SELECT * FROM classifieds WHERE ";
|
||||
query += "classifieduuid = ?AdId";
|
||||
|
||||
try
|
||||
{
|
||||
|
@ -307,7 +312,8 @@ namespace OpenSim.Data.MySQL
|
|||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
m_log.ErrorFormat("[PROFILES_DATA]: GetClassifiedInfo exception {0}", e.Message);
|
||||
m_log.ErrorFormat("[PROFILES_DATA]" +
|
||||
": GetPickInfo exception {0}", e.Message);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -316,8 +322,10 @@ namespace OpenSim.Data.MySQL
|
|||
#region Picks Queries
|
||||
public OSDArray GetAvatarPicks(UUID avatarId)
|
||||
{
|
||||
const string query = "SELECT `pickuuid`,`name` FROM userpicks WHERE creatoruuid = ?Id";
|
||||
string query = string.Empty;
|
||||
|
||||
query += "SELECT `pickuuid`,`name` FROM userpicks WHERE ";
|
||||
query += "creatoruuid = ?Id";
|
||||
OSDArray data = new OSDArray();
|
||||
|
||||
try
|
||||
|
@ -344,20 +352,24 @@ namespace OpenSim.Data.MySQL
|
|||
}
|
||||
}
|
||||
}
|
||||
dbcon.Close();
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
m_log.ErrorFormat("[PROFILES_DATA]: GetAvatarPicks exception {0}", e.Message);
|
||||
m_log.ErrorFormat("[PROFILES_DATA]" +
|
||||
": GetAvatarPicks exception {0}", e.Message);
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
public UserProfilePick GetPickInfo(UUID avatarId, UUID pickId)
|
||||
{
|
||||
string query = string.Empty;
|
||||
UserProfilePick pick = new UserProfilePick();
|
||||
const string query = "SELECT * FROM userpicks WHERE creatoruuid = ?CreatorId AND pickuuid = ?PickId";
|
||||
|
||||
query += "SELECT * FROM userpicks WHERE ";
|
||||
query += "creatoruuid = ?CreatorId AND ";
|
||||
query += "pickuuid = ?PickId";
|
||||
|
||||
try
|
||||
{
|
||||
|
@ -402,40 +414,41 @@ namespace OpenSim.Data.MySQL
|
|||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
m_log.ErrorFormat("[PROFILES_DATA]: GetPickInfo exception {0}", e.Message);
|
||||
m_log.ErrorFormat("[PROFILES_DATA]" +
|
||||
": GetPickInfo exception {0}", e.Message);
|
||||
}
|
||||
return pick;
|
||||
}
|
||||
|
||||
public bool UpdatePicksRecord(UserProfilePick pick)
|
||||
{
|
||||
const string query =
|
||||
"INSERT INTO userpicks VALUES ("
|
||||
+ "?PickId,"
|
||||
+ "?CreatorId,"
|
||||
+ "?TopPick,"
|
||||
+ "?ParcelId,"
|
||||
+ "?Name,"
|
||||
+ "?Desc,"
|
||||
+ "?SnapshotId,"
|
||||
+ "?User,"
|
||||
+ "?Original,"
|
||||
+ "?SimName,"
|
||||
+ "?GlobalPos,"
|
||||
+ "?SortOrder,"
|
||||
+ "?Enabled,"
|
||||
+ "?Gatekeeper)"
|
||||
+ "ON DUPLICATE KEY UPDATE "
|
||||
+ "parceluuid=?ParcelId,"
|
||||
+ "name=?Name,"
|
||||
+ "description=?Desc,"
|
||||
+ "user=?User,"
|
||||
+ "simname=?SimName,"
|
||||
+ "snapshotuuid=?SnapshotId,"
|
||||
+ "pickuuid=?PickId,"
|
||||
+ "posglobal=?GlobalPos,"
|
||||
+ "gatekeeper=?Gatekeeper"
|
||||
;
|
||||
string query = string.Empty;
|
||||
|
||||
query += "INSERT INTO userpicks VALUES (";
|
||||
query += "?PickId,";
|
||||
query += "?CreatorId,";
|
||||
query += "?TopPick,";
|
||||
query += "?ParcelId,";
|
||||
query += "?Name,";
|
||||
query += "?Desc,";
|
||||
query += "?SnapshotId,";
|
||||
query += "?User,";
|
||||
query += "?Original,";
|
||||
query += "?SimName,";
|
||||
query += "?GlobalPos,";
|
||||
query += "?SortOrder,";
|
||||
query += "?Enabled,";
|
||||
query += "?Gatekeeper)";
|
||||
query += "ON DUPLICATE KEY UPDATE ";
|
||||
query += "parceluuid=?ParcelId,";
|
||||
query += "name=?Name,";
|
||||
query += "description=?Desc,";
|
||||
query += "user=?User,";
|
||||
query += "simname=?SimName,";
|
||||
query += "snapshotuuid=?SnapshotId,";
|
||||
query += "pickuuid=?PickId,";
|
||||
query += "posglobal=?GlobalPos,";
|
||||
query += "gatekeeper=?Gatekeeper";
|
||||
|
||||
try
|
||||
{
|
||||
|
@ -461,12 +474,12 @@ namespace OpenSim.Data.MySQL
|
|||
|
||||
cmd.ExecuteNonQuery();
|
||||
}
|
||||
dbcon.Close();
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
m_log.ErrorFormat("[PROFILES_DATA]: UpdatePicksRecord exception {0}", e.Message);
|
||||
m_log.ErrorFormat("[PROFILES_DATA]" +
|
||||
": UpdateAvatarNotes exception {0}", e.Message);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
@ -474,7 +487,10 @@ namespace OpenSim.Data.MySQL
|
|||
|
||||
public bool DeletePicksRecord(UUID pickId)
|
||||
{
|
||||
string query = "DELETE FROM userpicks WHERE pickuuid = ?PickId";
|
||||
string query = string.Empty;
|
||||
|
||||
query += "DELETE FROM userpicks WHERE ";
|
||||
query += "pickuuid = ?PickId";
|
||||
|
||||
try
|
||||
{
|
||||
|
@ -488,12 +504,12 @@ namespace OpenSim.Data.MySQL
|
|||
|
||||
cmd.ExecuteNonQuery();
|
||||
}
|
||||
dbcon.Close();
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
m_log.ErrorFormat("[PROFILES_DATA]: DeletePicksRecord exception {0}", e.Message);
|
||||
m_log.ErrorFormat("[PROFILES_DATA]" +
|
||||
": DeleteUserPickRecord exception {0}", e.Message);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
@ -503,7 +519,12 @@ namespace OpenSim.Data.MySQL
|
|||
#region Avatar Notes Queries
|
||||
public bool GetAvatarNotes(ref UserProfileNotes notes)
|
||||
{ // WIP
|
||||
const string query = "SELECT `notes` FROM usernotes WHERE useruuid = ?Id AND targetuuid = ?TargetId";
|
||||
string query = string.Empty;
|
||||
|
||||
query += "SELECT `notes` FROM usernotes WHERE ";
|
||||
query += "useruuid = ?Id AND ";
|
||||
query += "targetuuid = ?TargetId";
|
||||
OSDArray data = new OSDArray();
|
||||
|
||||
try
|
||||
{
|
||||
|
@ -528,37 +549,38 @@ namespace OpenSim.Data.MySQL
|
|||
}
|
||||
}
|
||||
}
|
||||
dbcon.Close();
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
m_log.ErrorFormat("[PROFILES_DATA]: GetAvatarNotes exception {0}", e.Message);
|
||||
m_log.ErrorFormat("[PROFILES_DATA]" +
|
||||
": GetAvatarNotes exception {0}", e.Message);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool UpdateAvatarNotes(ref UserProfileNotes note, ref string result)
|
||||
{
|
||||
string query;
|
||||
string query = string.Empty;
|
||||
bool remove;
|
||||
|
||||
if(string.IsNullOrEmpty(note.Notes))
|
||||
{
|
||||
remove = true;
|
||||
query = "DELETE FROM usernotes WHERE useruuid=?UserId AND targetuuid=?TargetId";
|
||||
query += "DELETE FROM usernotes WHERE ";
|
||||
query += "useruuid=?UserId AND ";
|
||||
query += "targetuuid=?TargetId";
|
||||
}
|
||||
else
|
||||
{
|
||||
remove = false;
|
||||
query = "INSERT INTO usernotes VALUES ("
|
||||
+ "?UserId,"
|
||||
+ "?TargetId,"
|
||||
+ "?Notes )"
|
||||
+ "ON DUPLICATE KEY "
|
||||
+ "UPDATE "
|
||||
+ "notes=?Notes"
|
||||
;
|
||||
query += "INSERT INTO usernotes VALUES ( ";
|
||||
query += "?UserId,";
|
||||
query += "?TargetId,";
|
||||
query += "?Notes )";
|
||||
query += "ON DUPLICATE KEY ";
|
||||
query += "UPDATE ";
|
||||
query += "notes=?Notes";
|
||||
}
|
||||
|
||||
try
|
||||
|
@ -575,12 +597,12 @@ namespace OpenSim.Data.MySQL
|
|||
|
||||
cmd.ExecuteNonQuery();
|
||||
}
|
||||
dbcon.Close();
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
m_log.ErrorFormat("[PROFILES_DATA]: UpdateAvatarNotes exception {0}", e.Message);
|
||||
m_log.ErrorFormat("[PROFILES_DATA]" +
|
||||
": UpdateAvatarNotes exception {0}", e.Message);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
@ -591,7 +613,10 @@ namespace OpenSim.Data.MySQL
|
|||
#region Avatar Properties
|
||||
public bool GetAvatarProperties(ref UserProfileProperties props, ref string result)
|
||||
{
|
||||
string query = "SELECT * FROM userprofile WHERE useruuid = ?Id";
|
||||
string query = string.Empty;
|
||||
|
||||
query += "SELECT * FROM userprofile WHERE ";
|
||||
query += "useruuid = ?Id";
|
||||
|
||||
try
|
||||
{
|
||||
|
@ -606,8 +631,6 @@ namespace OpenSim.Data.MySQL
|
|||
{
|
||||
if(reader.HasRows)
|
||||
{
|
||||
m_log.DebugFormat("[PROFILES_DATA]" +
|
||||
": Getting data for {0}.", props.UserId);
|
||||
reader.Read();
|
||||
props.WebUrl = (string)reader["profileURL"];
|
||||
UUID.TryParse((string)reader["profileImage"], out props.ImageId);
|
||||
|
@ -623,9 +646,6 @@ namespace OpenSim.Data.MySQL
|
|||
}
|
||||
else
|
||||
{
|
||||
m_log.DebugFormat("[PROFILES_DATA]" +
|
||||
": No data for {0}", props.UserId);
|
||||
|
||||
props.WebUrl = string.Empty;
|
||||
props.ImageId = UUID.Zero;
|
||||
props.AboutText = string.Empty;
|
||||
|
@ -640,36 +660,35 @@ namespace OpenSim.Data.MySQL
|
|||
props.PublishProfile = false;
|
||||
props.PublishMature = false;
|
||||
|
||||
query = "INSERT INTO userprofile ("
|
||||
+ "useruuid, "
|
||||
+ "profilePartner, "
|
||||
+ "profileAllowPublish, "
|
||||
+ "profileMaturePublish, "
|
||||
+ "profileURL, "
|
||||
+ "profileWantToMask, "
|
||||
+ "profileWantToText, "
|
||||
+ "profileSkillsMask, "
|
||||
+ "profileSkillsText, "
|
||||
+ "profileLanguages, "
|
||||
+ "profileImage, "
|
||||
+ "profileAboutText, "
|
||||
+ "profileFirstImage, "
|
||||
+ "profileFirstText) VALUES ("
|
||||
+ "?userId, "
|
||||
+ "?profilePartner, "
|
||||
+ "?profileAllowPublish, "
|
||||
+ "?profileMaturePublish, "
|
||||
+ "?profileURL, "
|
||||
+ "?profileWantToMask, "
|
||||
+ "?profileWantToText, "
|
||||
+ "?profileSkillsMask, "
|
||||
+ "?profileSkillsText, "
|
||||
+ "?profileLanguages, "
|
||||
+ "?profileImage, "
|
||||
+ "?profileAboutText, "
|
||||
+ "?profileFirstImage, "
|
||||
+ "?profileFirstText)"
|
||||
;
|
||||
query = "INSERT INTO userprofile (";
|
||||
query += "useruuid, ";
|
||||
query += "profilePartner, ";
|
||||
query += "profileAllowPublish, ";
|
||||
query += "profileMaturePublish, ";
|
||||
query += "profileURL, ";
|
||||
query += "profileWantToMask, ";
|
||||
query += "profileWantToText, ";
|
||||
query += "profileSkillsMask, ";
|
||||
query += "profileSkillsText, ";
|
||||
query += "profileLanguages, ";
|
||||
query += "profileImage, ";
|
||||
query += "profileAboutText, ";
|
||||
query += "profileFirstImage, ";
|
||||
query += "profileFirstText) VALUES (";
|
||||
query += "?userId, ";
|
||||
query += "?profilePartner, ";
|
||||
query += "?profileAllowPublish, ";
|
||||
query += "?profileMaturePublish, ";
|
||||
query += "?profileURL, ";
|
||||
query += "?profileWantToMask, ";
|
||||
query += "?profileWantToText, ";
|
||||
query += "?profileSkillsMask, ";
|
||||
query += "?profileSkillsText, ";
|
||||
query += "?profileLanguages, ";
|
||||
query += "?profileImage, ";
|
||||
query += "?profileAboutText, ";
|
||||
query += "?profileFirstImage, ";
|
||||
query += "?profileFirstText)";
|
||||
|
||||
dbcon.Close();
|
||||
dbcon.Open();
|
||||
|
@ -696,12 +715,12 @@ namespace OpenSim.Data.MySQL
|
|||
}
|
||||
}
|
||||
}
|
||||
dbcon.Close();
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
m_log.ErrorFormat("[PROFILES_DATA]: GetAvatarProperties exception {0}", e.Message);
|
||||
m_log.ErrorFormat("[PROFILES_DATA]" +
|
||||
": Requst properties exception {0}", e.Message);
|
||||
result = e.Message;
|
||||
return false;
|
||||
}
|
||||
|
@ -710,10 +729,15 @@ namespace OpenSim.Data.MySQL
|
|||
|
||||
public bool UpdateAvatarProperties(ref UserProfileProperties props, ref string result)
|
||||
{
|
||||
const string query = "UPDATE userprofile SET profileURL=?profileURL,"
|
||||
+ "profileImage=?image, profileAboutText=?abouttext,"
|
||||
+ "profileFirstImage=?firstlifeimage, profileFirstText=?firstlifetext "
|
||||
+ "WHERE useruuid=?uuid";
|
||||
string query = string.Empty;
|
||||
|
||||
query += "UPDATE userprofile SET ";
|
||||
query += "profileURL=?profileURL, ";
|
||||
query += "profileImage=?image, ";
|
||||
query += "profileAboutText=?abouttext,";
|
||||
query += "profileFirstImage=?firstlifeimage,";
|
||||
query += "profileFirstText=?firstlifetext ";
|
||||
query += "WHERE useruuid=?uuid";
|
||||
|
||||
try
|
||||
{
|
||||
|
@ -731,12 +755,12 @@ namespace OpenSim.Data.MySQL
|
|||
|
||||
cmd.ExecuteNonQuery();
|
||||
}
|
||||
dbcon.Close();
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
m_log.ErrorFormat("[PROFILES_DATA]: UpdateAvatarProperties exception {0}", e.Message);
|
||||
m_log.ErrorFormat("[PROFILES_DATA]" +
|
||||
": AgentPropertiesUpdate exception {0}", e.Message);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
@ -747,13 +771,15 @@ namespace OpenSim.Data.MySQL
|
|||
#region Avatar Interests
|
||||
public bool UpdateAvatarInterests(UserProfileProperties up, ref string result)
|
||||
{
|
||||
const string query = "UPDATE userprofile SET "
|
||||
+ "profileWantToMask=?WantMask, "
|
||||
+ "profileWantToText=?WantText,"
|
||||
+ "profileSkillsMask=?SkillsMask,"
|
||||
+ "profileSkillsText=?SkillsText, "
|
||||
+ "profileLanguages=?Languages "
|
||||
+ "WHERE useruuid=?uuid";
|
||||
string query = string.Empty;
|
||||
|
||||
query += "UPDATE userprofile SET ";
|
||||
query += "profileWantToMask=?WantMask, ";
|
||||
query += "profileWantToText=?WantText,";
|
||||
query += "profileSkillsMask=?SkillsMask,";
|
||||
query += "profileSkillsText=?SkillsText, ";
|
||||
query += "profileLanguages=?Languages ";
|
||||
query += "WHERE useruuid=?uuid";
|
||||
|
||||
try
|
||||
{
|
||||
|
@ -775,7 +801,8 @@ namespace OpenSim.Data.MySQL
|
|||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
m_log.ErrorFormat("[PROFILES_DATA]: UpdateAvatarInterests exception {0}", e.Message);
|
||||
m_log.ErrorFormat("[PROFILES_DATA]" +
|
||||
": AgentInterestsUpdate exception {0}", e.Message);
|
||||
result = e.Message;
|
||||
return false;
|
||||
}
|
||||
|
@ -786,17 +813,18 @@ namespace OpenSim.Data.MySQL
|
|||
public OSDArray GetUserImageAssets(UUID avatarId)
|
||||
{
|
||||
OSDArray data = new OSDArray();
|
||||
const string queryA = "SELECT `snapshotuuid` FROM {0} WHERE `creatoruuid` = ?Id";
|
||||
string query = "SELECT `snapshotuuid` FROM {0} WHERE `creatoruuid` = ?Id";
|
||||
|
||||
// Get classified image assets
|
||||
|
||||
|
||||
try
|
||||
{
|
||||
using (MySqlConnection dbcon = new MySqlConnection(ConnectionString))
|
||||
{
|
||||
dbcon.Open();
|
||||
|
||||
using (MySqlCommand cmd = new MySqlCommand(string.Format (queryA,"`classifieds`"), dbcon))
|
||||
using (MySqlCommand cmd = new MySqlCommand(string.Format (query,"`classifieds`"), dbcon))
|
||||
{
|
||||
cmd.Parameters.AddWithValue("?Id", avatarId.ToString());
|
||||
|
||||
|
@ -815,7 +843,7 @@ namespace OpenSim.Data.MySQL
|
|||
dbcon.Close();
|
||||
dbcon.Open();
|
||||
|
||||
using (MySqlCommand cmd = new MySqlCommand(string.Format (queryA,"`userpicks`"), dbcon))
|
||||
using (MySqlCommand cmd = new MySqlCommand(string.Format (query,"`userpicks`"), dbcon))
|
||||
{
|
||||
cmd.Parameters.AddWithValue("?Id", avatarId.ToString());
|
||||
|
||||
|
@ -834,9 +862,9 @@ namespace OpenSim.Data.MySQL
|
|||
dbcon.Close();
|
||||
dbcon.Open();
|
||||
|
||||
const string queryB = "SELECT `profileImage`, `profileFirstImage` FROM `userprofile` WHERE `useruuid` = ?Id";
|
||||
query = "SELECT `profileImage`, `profileFirstImage` FROM `userprofile` WHERE `useruuid` = ?Id";
|
||||
|
||||
using (MySqlCommand cmd = new MySqlCommand(queryB, dbcon))
|
||||
using (MySqlCommand cmd = new MySqlCommand(string.Format (query,"`userpicks`"), dbcon))
|
||||
{
|
||||
cmd.Parameters.AddWithValue("?Id", avatarId.ToString());
|
||||
|
||||
|
@ -852,12 +880,12 @@ namespace OpenSim.Data.MySQL
|
|||
}
|
||||
}
|
||||
}
|
||||
dbcon.Close();
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
m_log.ErrorFormat("[PROFILES_DATA]: GetUserImageAssets exception {0}", e.Message);
|
||||
m_log.ErrorFormat("[PROFILES_DATA]" +
|
||||
": GetAvatarNotes exception {0}", e.Message);
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
@ -865,7 +893,13 @@ namespace OpenSim.Data.MySQL
|
|||
#region User Preferences
|
||||
public bool GetUserPreferences(ref UserPreferences pref, ref string result)
|
||||
{
|
||||
const string query = "SELECT imviaemail,visible,email FROM usersettings WHERE useruuid = ?Id";
|
||||
string query = string.Empty;
|
||||
|
||||
query += "SELECT imviaemail,visible,email FROM ";
|
||||
query += "usersettings WHERE ";
|
||||
query += "useruuid = ?Id";
|
||||
|
||||
OSDArray data = new OSDArray();
|
||||
|
||||
try
|
||||
{
|
||||
|
@ -875,6 +909,7 @@ namespace OpenSim.Data.MySQL
|
|||
using (MySqlCommand cmd = new MySqlCommand(query, dbcon))
|
||||
{
|
||||
cmd.Parameters.AddWithValue("?Id", pref.UserId.ToString());
|
||||
|
||||
using (MySqlDataReader reader = cmd.ExecuteReader())
|
||||
{
|
||||
if(reader.HasRows)
|
||||
|
@ -889,9 +924,10 @@ namespace OpenSim.Data.MySQL
|
|||
dbcon.Close();
|
||||
dbcon.Open();
|
||||
|
||||
const string queryB = "INSERT INTO usersettings VALUES (?uuid,'false','false', ?Email)";
|
||||
query = "INSERT INTO usersettings VALUES ";
|
||||
query += "(?uuid,'false','false', ?Email)";
|
||||
|
||||
using (MySqlCommand put = new MySqlCommand(queryB, dbcon))
|
||||
using (MySqlCommand put = new MySqlCommand(query, dbcon))
|
||||
{
|
||||
|
||||
put.Parameters.AddWithValue("?Email", pref.EMail);
|
||||
|
@ -902,12 +938,12 @@ namespace OpenSim.Data.MySQL
|
|||
}
|
||||
}
|
||||
}
|
||||
dbcon.Close();
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
m_log.ErrorFormat("[PROFILES_DATA]: GetUserPreferences exception {0}", e.Message);
|
||||
m_log.ErrorFormat("[PROFILES_DATA]" +
|
||||
": Get preferences exception {0}", e.Message);
|
||||
result = e.Message;
|
||||
return false;
|
||||
}
|
||||
|
@ -916,9 +952,13 @@ namespace OpenSim.Data.MySQL
|
|||
|
||||
public bool UpdateUserPreferences(ref UserPreferences pref, ref string result)
|
||||
{
|
||||
const string query = "UPDATE usersettings SET imviaemail=?ImViaEmail,"
|
||||
+ "visible=?Visible, email=?EMail "
|
||||
+ "WHERE useruuid=?uuid";
|
||||
string query = string.Empty;
|
||||
|
||||
query += "UPDATE usersettings SET ";
|
||||
query += "imviaemail=?ImViaEmail, ";
|
||||
query += "visible=?Visible, ";
|
||||
query += "email=?EMail ";
|
||||
query += "WHERE useruuid=?uuid";
|
||||
|
||||
try
|
||||
{
|
||||
|
@ -934,12 +974,12 @@ namespace OpenSim.Data.MySQL
|
|||
|
||||
cmd.ExecuteNonQuery();
|
||||
}
|
||||
dbcon.Close();
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
m_log.ErrorFormat("[PROFILES_DATA]: UpdateUserPreferences exception {0} {1}", e.Message, e.InnerException);
|
||||
m_log.ErrorFormat("[PROFILES_DATA]" +
|
||||
": UserPreferencesUpdate exception {0} {1}", e.Message, e.InnerException);
|
||||
result = e.Message;
|
||||
return false;
|
||||
}
|
||||
|
@ -950,7 +990,11 @@ namespace OpenSim.Data.MySQL
|
|||
#region Integration
|
||||
public bool GetUserAppData(ref UserAppData props, ref string result)
|
||||
{
|
||||
const string query = "SELECT * FROM `userdata` WHERE UserId = ?Id AND TagId = ?TagId";
|
||||
string query = string.Empty;
|
||||
|
||||
query += "SELECT * FROM `userdata` WHERE ";
|
||||
query += "UserId = ?Id AND ";
|
||||
query += "TagId = ?TagId";
|
||||
|
||||
try
|
||||
{
|
||||
|
@ -972,8 +1016,13 @@ namespace OpenSim.Data.MySQL
|
|||
}
|
||||
else
|
||||
{
|
||||
const string queryB = "INSERT INTO userdata VALUES (?UserId, ?TagId, ?DataKey, ?DataVal)";
|
||||
using (MySqlCommand put = new MySqlCommand(queryB, dbcon))
|
||||
query += "INSERT INTO userdata VALUES ( ";
|
||||
query += "?UserId,";
|
||||
query += "?TagId,";
|
||||
query += "?DataKey,";
|
||||
query += "?DataVal) ";
|
||||
|
||||
using (MySqlCommand put = new MySqlCommand(query, dbcon))
|
||||
{
|
||||
put.Parameters.AddWithValue("?UserId", props.UserId.ToString());
|
||||
put.Parameters.AddWithValue("?TagId", props.TagId.ToString());
|
||||
|
@ -985,12 +1034,12 @@ namespace OpenSim.Data.MySQL
|
|||
}
|
||||
}
|
||||
}
|
||||
dbcon.Close();
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
m_log.ErrorFormat("[PROFILES_DATA]: GetUserAppData exception {0}", e.Message);
|
||||
m_log.ErrorFormat("[PROFILES_DATA]" +
|
||||
": Requst application data exception {0}", e.Message);
|
||||
result = e.Message;
|
||||
return false;
|
||||
}
|
||||
|
@ -999,7 +1048,14 @@ namespace OpenSim.Data.MySQL
|
|||
|
||||
public bool SetUserAppData(UserAppData props, ref string result)
|
||||
{
|
||||
const string query = "UPDATE userdata SET TagId = ?TagId, DataKey = ?DataKey, DataVal = ?DataVal WHERE UserId = ?UserId AND TagId = ?TagId";
|
||||
string query = string.Empty;
|
||||
|
||||
query += "UPDATE userdata SET ";
|
||||
query += "TagId = ?TagId, ";
|
||||
query += "DataKey = ?DataKey, ";
|
||||
query += "DataVal = ?DataVal WHERE ";
|
||||
query += "UserId = ?UserId AND ";
|
||||
query += "TagId = ?TagId";
|
||||
|
||||
try
|
||||
{
|
||||
|
@ -1015,12 +1071,12 @@ namespace OpenSim.Data.MySQL
|
|||
|
||||
cmd.ExecuteNonQuery();
|
||||
}
|
||||
dbcon.Close();
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
m_log.ErrorFormat("[PROFILES_DATA]: SetUserAppData exception {0}", e.Message);
|
||||
m_log.ErrorFormat("[PROFILES_DATA]" +
|
||||
": SetUserData exception {0}", e.Message);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
|
|
@ -58,6 +58,11 @@ namespace OpenSim.Data.MySQL
|
|||
private bool m_enableCompression = false;
|
||||
private string m_connectionString;
|
||||
|
||||
/// <summary>
|
||||
/// We can reuse this for all hashing since all methods are single-threaded through m_dbBLock
|
||||
/// </summary>
|
||||
private HashAlgorithm hasher = new SHA256CryptoServiceProvider();
|
||||
|
||||
#region IPlugin Members
|
||||
|
||||
public string Version { get { return "1.0.0.0"; } }
|
||||
|
@ -92,7 +97,6 @@ namespace OpenSim.Data.MySQL
|
|||
dbcon.Open();
|
||||
Migration m = new Migration(dbcon, Assembly, "XAssetStore");
|
||||
m.Update();
|
||||
dbcon.Close();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -126,7 +130,6 @@ namespace OpenSim.Data.MySQL
|
|||
// m_log.DebugFormat("[MYSQL XASSET DATA]: Looking for asset {0}", assetID);
|
||||
|
||||
AssetBase asset = null;
|
||||
int accessTime = 0;
|
||||
|
||||
using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
|
||||
{
|
||||
|
@ -137,6 +140,7 @@ namespace OpenSim.Data.MySQL
|
|||
dbcon))
|
||||
{
|
||||
cmd.Parameters.AddWithValue("?ID", assetID.ToString());
|
||||
|
||||
try
|
||||
{
|
||||
using (MySqlDataReader dbReader = cmd.ExecuteReader(CommandBehavior.SingleRow))
|
||||
|
@ -155,7 +159,23 @@ namespace OpenSim.Data.MySQL
|
|||
|
||||
asset.Temporary = Convert.ToBoolean(dbReader["Temporary"]);
|
||||
asset.Flags = (AssetFlags)Convert.ToInt32(dbReader["AssetFlags"]);
|
||||
accessTime = (int)dbReader["AccessTime"];
|
||||
|
||||
if (m_enableCompression)
|
||||
{
|
||||
using (GZipStream decompressionStream = new GZipStream(new MemoryStream(asset.Data), CompressionMode.Decompress))
|
||||
{
|
||||
MemoryStream outputStream = new MemoryStream();
|
||||
WebUtil.CopyStream(decompressionStream, outputStream, int.MaxValue);
|
||||
// int compressedLength = asset.Data.Length;
|
||||
asset.Data = outputStream.ToArray();
|
||||
|
||||
// m_log.DebugFormat(
|
||||
// "[XASSET DB]: Decompressed {0} {1} to {2} bytes from {3}",
|
||||
// asset.ID, asset.Name, asset.Data.Length, compressedLength);
|
||||
}
|
||||
}
|
||||
|
||||
UpdateAccessTime(asset.Metadata, (int)dbReader["AccessTime"]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -164,37 +184,8 @@ namespace OpenSim.Data.MySQL
|
|||
m_log.Error(string.Format("[MYSQL XASSET DATA]: Failure fetching asset {0}", assetID), e);
|
||||
}
|
||||
}
|
||||
dbcon.Close();
|
||||
}
|
||||
|
||||
if(asset == null)
|
||||
return asset;
|
||||
|
||||
if(accessTime > 0)
|
||||
{
|
||||
try
|
||||
{
|
||||
UpdateAccessTime(asset.Metadata, accessTime);
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
|
||||
if (m_enableCompression && asset.Data != null)
|
||||
{
|
||||
using(MemoryStream ms = new MemoryStream(asset.Data))
|
||||
using(GZipStream decompressionStream = new GZipStream(ms, CompressionMode.Decompress))
|
||||
{
|
||||
using(MemoryStream outputStream = new MemoryStream())
|
||||
{
|
||||
decompressionStream.CopyTo(outputStream, int.MaxValue);
|
||||
// int compressedLength = asset.Data.Length;
|
||||
asset.Data = outputStream.ToArray();
|
||||
}
|
||||
// m_log.DebugFormat(
|
||||
// "[XASSET DB]: Decompressed {0} {1} to {2} bytes from {3}",
|
||||
// asset.ID, asset.Name, asset.Data.Length, compressedLength);
|
||||
}
|
||||
}
|
||||
return asset;
|
||||
}
|
||||
|
||||
|
@ -245,9 +236,7 @@ namespace OpenSim.Data.MySQL
|
|||
}
|
||||
}
|
||||
|
||||
byte[] hash;
|
||||
using (HashAlgorithm hasher = new SHA256CryptoServiceProvider())
|
||||
hash = hasher.ComputeHash(asset.Data);
|
||||
byte[] hash = hasher.ComputeHash(asset.Data);
|
||||
|
||||
// m_log.DebugFormat(
|
||||
// "[XASSET DB]: Compressed data size for {0} {1}, hash {2} is {3}",
|
||||
|
@ -314,7 +303,6 @@ namespace OpenSim.Data.MySQL
|
|||
|
||||
transaction.Commit();
|
||||
}
|
||||
dbcon.Close();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -356,7 +344,6 @@ namespace OpenSim.Data.MySQL
|
|||
"[XASSET MYSQL DB]: Failure updating access_time for asset {0} with name {1}",
|
||||
assetMetadata.ID, assetMetadata.Name);
|
||||
}
|
||||
dbcon.Close();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -453,8 +440,7 @@ namespace OpenSim.Data.MySQL
|
|||
using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
|
||||
{
|
||||
dbcon.Open();
|
||||
using(MySqlCommand cmd = new MySqlCommand("SELECT Name, Description, AccessTime, AssetType, Temporary, ID, AssetFlags, CreatorID FROM XAssetsMeta LIMIT ?start, ?count",dbcon))
|
||||
{
|
||||
MySqlCommand cmd = new MySqlCommand("SELECT Name, Description, AccessTime, AssetType, Temporary, ID, AssetFlags, CreatorID FROM XAssetsMeta LIMIT ?start, ?count", dbcon);
|
||||
cmd.Parameters.AddWithValue("?start", start);
|
||||
cmd.Parameters.AddWithValue("?count", count);
|
||||
|
||||
|
@ -487,8 +473,6 @@ namespace OpenSim.Data.MySQL
|
|||
m_log.Error("[XASSETS DB]: MySql failure fetching asset set" + Environment.NewLine + e.ToString());
|
||||
}
|
||||
}
|
||||
dbcon.Close();
|
||||
}
|
||||
|
||||
return retList;
|
||||
}
|
||||
|
@ -506,9 +490,9 @@ namespace OpenSim.Data.MySQL
|
|||
cmd.Parameters.AddWithValue("?ID", id);
|
||||
cmd.ExecuteNonQuery();
|
||||
}
|
||||
|
||||
// TODO: How do we deal with data from deleted assets? Probably not easily reapable unless we
|
||||
// keep a reference count (?)
|
||||
dbcon.Close();
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
|
@ -193,9 +193,7 @@ namespace OpenSim.Data.MySQL
|
|||
{
|
||||
using (MySqlCommand cmd = new MySqlCommand())
|
||||
{
|
||||
// cmd.CommandText = String.Format("select * from inventoryitems where avatarId = ?uuid and assetType = ?type and flags & 1", m_Realm);
|
||||
|
||||
cmd.CommandText = String.Format("select * from inventoryitems where avatarId = ?uuid and assetType = ?type and flags & 1");
|
||||
cmd.CommandText = String.Format("select * from inventoryitems where avatarId = ?uuid and assetType = ?type and flags & 1", m_Realm);
|
||||
|
||||
cmd.Parameters.AddWithValue("?uuid", principalID.ToString());
|
||||
cmd.Parameters.AddWithValue("?type", (int)AssetType.Gesture);
|
||||
|
@ -214,10 +212,7 @@ namespace OpenSim.Data.MySQL
|
|||
{
|
||||
cmd.Connection = dbcon;
|
||||
|
||||
// cmd.CommandText = String.Format("select bit_or(inventoryCurrentPermissions) as inventoryCurrentPermissions from inventoryitems where avatarID = ?PrincipalID and assetID = ?AssetID group by assetID", m_Realm);
|
||||
|
||||
cmd.CommandText = String.Format("select bit_or(inventoryCurrentPermissions) as inventoryCurrentPermissions from inventoryitems where avatarID = ?PrincipalID and assetID = ?AssetID group by assetID");
|
||||
|
||||
cmd.CommandText = String.Format("select bit_or(inventoryCurrentPermissions) as inventoryCurrentPermissions from inventoryitems where avatarID = ?PrincipalID and assetID = ?AssetID group by assetID", m_Realm);
|
||||
cmd.Parameters.AddWithValue("?PrincipalID", principalID.ToString());
|
||||
cmd.Parameters.AddWithValue("?AssetID", assetID.ToString());
|
||||
|
||||
|
@ -328,6 +323,7 @@ namespace OpenSim.Data.MySQL
|
|||
{
|
||||
return false;
|
||||
}
|
||||
cmd.Dispose();
|
||||
}
|
||||
|
||||
dbcon.Close();
|
||||
|
|
|
@ -61,5 +61,5 @@ using System.Runtime.InteropServices;
|
|||
// You can specify all the values or you can default the Revision and Build Numbers
|
||||
// by using the '*' as shown below:
|
||||
|
||||
[assembly : AssemblyVersion(OpenSim.VersionInfo.AssemblyVersionNumber)]
|
||||
[assembly : AssemblyVersion("0.8.2.*")]
|
||||
|
||||
|
|
|
@ -1,18 +0,0 @@
|
|||
:VERSION 1 # -------------------------
|
||||
|
||||
BEGIN;
|
||||
|
||||
CREATE TABLE `AgentPrefs` (
|
||||
`PrincipalID` CHAR(36) NOT NULL,
|
||||
`AccessPrefs` CHAR(2) NOT NULL DEFAULT 'M',
|
||||
`HoverHeight` DOUBLE(30, 27) NOT NULL DEFAULT 0,
|
||||
`Language` CHAR(5) NOT NULL DEFAULT 'en-us',
|
||||
`LanguageIsPublic` BOOLEAN NOT NULL DEFAULT 1,
|
||||
`PermEveryone` INT(6) NOT NULL DEFAULT 0,
|
||||
`PermGroup` INT(6) NOT NULL DEFAULT 0,
|
||||
`PermNextOwner` INT(6) NOT NULL DEFAULT 532480,
|
||||
UNIQUE KEY `PrincipalID` (`PrincipalID`),
|
||||
PRIMARY KEY(`PrincipalID`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
|
||||
COMMIT;
|
|
@ -1,21 +1,81 @@
|
|||
# -----------------
|
||||
:VERSION 10
|
||||
:VERSION 1
|
||||
|
||||
BEGIN;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `assets` (
|
||||
CREATE TABLE `assets` (
|
||||
`id` binary(16) NOT NULL,
|
||||
`name` varchar(64) NOT NULL,
|
||||
`description` varchar(64) NOT NULL,
|
||||
`assetType` tinyint(4) NOT NULL,
|
||||
`invType` tinyint(4) NOT NULL,
|
||||
`local` tinyint(1) NOT NULL,
|
||||
`temporary` tinyint(1) NOT NULL,
|
||||
`data` longblob NOT NULL,
|
||||
`id` char(36) NOT NULL DEFAULT '00000000-0000-0000-0000-000000000000',
|
||||
`create_time` int(11) DEFAULT '0',
|
||||
`access_time` int(11) DEFAULT '0',
|
||||
`asset_flags` int(11) NOT NULL DEFAULT '0',
|
||||
`CreatorID` varchar(128) NOT NULL DEFAULT '',
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Rev. 1';
|
||||
|
||||
COMMIT;
|
||||
|
||||
# -----------------
|
||||
:VERSION 2
|
||||
|
||||
BEGIN;
|
||||
|
||||
ALTER TABLE assets change id oldid binary(16);
|
||||
ALTER TABLE assets add id varchar(36) not null default '';
|
||||
UPDATE assets set id = concat(substr(hex(oldid),1,8),"-",substr(hex(oldid),9,4),"-",substr(hex(oldid),13,4),"-",substr(hex(oldid),17,4),"-",substr(hex(oldid),21,12));
|
||||
ALTER TABLE assets drop oldid;
|
||||
ALTER TABLE assets add constraint primary key(id);
|
||||
|
||||
COMMIT;
|
||||
|
||||
# -----------------
|
||||
:VERSION 3
|
||||
|
||||
BEGIN;
|
||||
|
||||
ALTER TABLE assets change id oldid varchar(36);
|
||||
ALTER TABLE assets add id char(36) not null default '00000000-0000-0000-0000-000000000000';
|
||||
UPDATE assets set id = oldid;
|
||||
ALTER TABLE assets drop oldid;
|
||||
ALTER TABLE assets add constraint primary key(id);
|
||||
|
||||
COMMIT;
|
||||
|
||||
# -----------------
|
||||
:VERSION 4
|
||||
|
||||
BEGIN;
|
||||
|
||||
ALTER TABLE assets drop InvType;
|
||||
|
||||
COMMIT;
|
||||
|
||||
# -----------------
|
||||
:VERSION 5
|
||||
|
||||
BEGIN;
|
||||
|
||||
ALTER TABLE assets add create_time integer default 0;
|
||||
ALTER TABLE assets add access_time integer default 0;
|
||||
|
||||
COMMIT;
|
||||
|
||||
# -----------------
|
||||
:VERSION 6
|
||||
|
||||
DELETE FROM assets WHERE id = 'dc4b9f0b-d008-45c6-96a4-01dd947ac621'
|
||||
|
||||
:VERSION 7
|
||||
|
||||
ALTER TABLE assets ADD COLUMN asset_flags INTEGER NOT NULL DEFAULT 0;
|
||||
|
||||
:VERSION 8
|
||||
|
||||
ALTER TABLE assets ADD COLUMN CreatorID varchar(128) NOT NULL DEFAULT '';
|
||||
|
||||
:VERSION 9
|
||||
|
||||
BEGIN;
|
||||
COMMIT;
|
||||
|
|
|
@ -1,17 +1,16 @@
|
|||
:VERSION 4 # -------------------------------
|
||||
:VERSION 1 # -------------------------------
|
||||
|
||||
begin;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `auth` (
|
||||
CREATE TABLE `auth` (
|
||||
`UUID` char(36) NOT NULL,
|
||||
`passwordHash` char(32) NOT NULL DEFAULT '',
|
||||
`passwordSalt` char(32) NOT NULL DEFAULT '',
|
||||
`webLoginKey` varchar(255) NOT NULL DEFAULT '',
|
||||
`accountType` varchar(32) NOT NULL DEFAULT 'UserAccount',
|
||||
`passwordHash` char(32) NOT NULL default '',
|
||||
`passwordSalt` char(32) NOT NULL default '',
|
||||
`webLoginKey` varchar(255) NOT NULL default '',
|
||||
PRIMARY KEY (`UUID`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
) ENGINE=InnoDB;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `tokens` (
|
||||
CREATE TABLE `tokens` (
|
||||
`UUID` char(36) NOT NULL,
|
||||
`token` varchar(255) NOT NULL,
|
||||
`validity` datetime NOT NULL,
|
||||
|
@ -19,6 +18,22 @@ CREATE TABLE IF NOT EXISTS `tokens` (
|
|||
KEY `UUID` (`UUID`),
|
||||
KEY `token` (`token`),
|
||||
KEY `validity` (`validity`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
) ENGINE=InnoDB;
|
||||
|
||||
commit;
|
||||
|
||||
:VERSION 2 # -------------------------------
|
||||
|
||||
BEGIN;
|
||||
|
||||
INSERT INTO auth (UUID, passwordHash, passwordSalt, webLoginKey) SELECT `UUID` AS UUID, `passwordHash` AS passwordHash, `passwordSalt` AS passwordSalt, `webLoginKey` AS webLoginKey FROM users;
|
||||
|
||||
COMMIT;
|
||||
|
||||
:VERSION 3 # -------------------------------
|
||||
|
||||
BEGIN;
|
||||
|
||||
ALTER TABLE `auth` ADD COLUMN `accountType` VARCHAR(32) NOT NULL DEFAULT 'UserAccount';
|
||||
|
||||
COMMIT;
|
||||
|
|
|
@ -1,13 +1,20 @@
|
|||
:VERSION 3
|
||||
:VERSION 1
|
||||
|
||||
BEGIN;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `Avatars` (
|
||||
`PrincipalID` char(36) NOT NULL,
|
||||
`Name` varchar(32) NOT NULL,
|
||||
`Value` text,
|
||||
PRIMARY KEY (`PrincipalID`,`Name`),
|
||||
KEY `PrincipalID` (`PrincipalID`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
CREATE TABLE Avatars (
|
||||
PrincipalID CHAR(36) NOT NULL,
|
||||
Name VARCHAR(32) NOT NULL,
|
||||
Value VARCHAR(255) NOT NULL DEFAULT '',
|
||||
PRIMARY KEY(PrincipalID, Name),
|
||||
KEY(PrincipalID));
|
||||
|
||||
COMMIT;
|
||||
|
||||
:VERSION 2
|
||||
|
||||
BEGIN;
|
||||
|
||||
alter table Avatars change column Value Value text;
|
||||
|
||||
COMMIT;
|
||||
|
|
|
@ -1,29 +1,41 @@
|
|||
:VERSION 34
|
||||
:VERSION 13
|
||||
|
||||
# The estate migrations used to be in Region store
|
||||
# here they will do nothing (bad) if the tables are already there,
|
||||
# just update the store version.
|
||||
|
||||
BEGIN;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `estate_groups` (
|
||||
`EstateID` int(10) unsigned NOT NULL,
|
||||
`uuid` char(36) NOT NULL,
|
||||
KEY `EstateID` (`EstateID`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `estate_managers` (
|
||||
`EstateID` int(10) unsigned NOT NULL,
|
||||
`uuid` char(36) NOT NULL,
|
||||
KEY `EstateID` (`EstateID`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
) ENGINE=InnoDB;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `estate_map` (
|
||||
`RegionID` char(36) NOT NULL DEFAULT '00000000-0000-0000-0000-000000000000',
|
||||
`EstateID` int(11) NOT NULL,
|
||||
PRIMARY KEY (`RegionID`),
|
||||
CREATE TABLE IF NOT EXISTS `estate_groups` (
|
||||
`EstateID` int(10) unsigned NOT NULL,
|
||||
`uuid` char(36) NOT NULL,
|
||||
KEY `EstateID` (`EstateID`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
) ENGINE=InnoDB;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `estate_users` (
|
||||
`EstateID` int(10) unsigned NOT NULL,
|
||||
`uuid` char(36) NOT NULL,
|
||||
KEY `EstateID` (`EstateID`)
|
||||
) ENGINE=InnoDB;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `estateban` (
|
||||
`EstateID` int(10) unsigned NOT NULL,
|
||||
`bannedUUID` varchar(36) NOT NULL,
|
||||
`bannedIp` varchar(16) NOT NULL,
|
||||
`bannedIpHostMask` varchar(16) NOT NULL,
|
||||
`bannedNameMask` varchar(64) default NULL,
|
||||
KEY `estateban_EstateID` (`EstateID`)
|
||||
) ENGINE=InnoDB;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `estate_settings` (
|
||||
`EstateID` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
||||
`EstateName` varchar(64) DEFAULT NULL,
|
||||
`EstateID` int(10) unsigned NOT NULL auto_increment,
|
||||
`EstateName` varchar(64) default NULL,
|
||||
`AbuseEmailToEstateOwner` tinyint(4) NOT NULL,
|
||||
`DenyAnonymous` tinyint(4) NOT NULL,
|
||||
`ResetHomeOnTeleport` tinyint(4) NOT NULL,
|
||||
|
@ -43,41 +55,33 @@ CREATE TABLE IF NOT EXISTS `estate_settings` (
|
|||
`EstateSkipScripts` tinyint(4) NOT NULL,
|
||||
`BillableFactor` float NOT NULL,
|
||||
`PublicAccess` tinyint(4) NOT NULL,
|
||||
`AbuseEmail` varchar(255) NOT NULL,
|
||||
`EstateOwner` varchar(36) NOT NULL,
|
||||
`DenyMinors` tinyint(4) NOT NULL,
|
||||
`AllowLandmark` tinyint(4) NOT NULL DEFAULT '1',
|
||||
`AllowParcelChanges` tinyint(4) NOT NULL DEFAULT '1',
|
||||
`AllowSetHome` tinyint(4) NOT NULL DEFAULT '1',
|
||||
`AbuseEmail` varchar(255) not null,
|
||||
`EstateOwner` varchar(36) not null,
|
||||
`DenyMinors` tinyint not null,
|
||||
|
||||
PRIMARY KEY (`EstateID`)
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=101 DEFAULT CHARSET=utf8;
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=100;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `estate_users` (
|
||||
`EstateID` int(10) unsigned NOT NULL,
|
||||
`uuid` char(36) NOT NULL,
|
||||
CREATE TABLE IF NOT EXISTS `estate_map` (
|
||||
`RegionID` char(36) NOT NULL default '00000000-0000-0000-0000-000000000000',
|
||||
`EstateID` int(11) NOT NULL,
|
||||
PRIMARY KEY (`RegionID`),
|
||||
KEY `EstateID` (`EstateID`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `estateban` (
|
||||
`EstateID` int(10) unsigned NOT NULL,
|
||||
`bannedUUID` varchar(36) NOT NULL,
|
||||
`bannedIp` varchar(16) NOT NULL,
|
||||
`bannedIpHostMask` varchar(16) NOT NULL,
|
||||
`bannedNameMask` varchar(64) DEFAULT NULL,
|
||||
KEY `estateban_EstateID` (`EstateID`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
) ENGINE=InnoDB;
|
||||
|
||||
COMMIT;
|
||||
|
||||
:VERSION 35
|
||||
:VERSION 32 #--------------------- (moved from RegionStore migr, just in case)
|
||||
|
||||
BEGIN;
|
||||
ALTER TABLE `estateban`
|
||||
ADD COLUMN `banningUUID` varchar(36) NOT NULL DEFAULT '00000000-0000-0000-0000-000000000000',
|
||||
ADD COLUMN `banTime` int(11) NOT NULL DEFAULT 0;
|
||||
ALTER TABLE estate_settings AUTO_INCREMENT = 100;
|
||||
COMMIT;
|
||||
|
||||
:VERSION 36
|
||||
:VERSION 33 #---------------------
|
||||
|
||||
BEGIN;
|
||||
ALTER TABLE `estate_settings`
|
||||
ADD COLUMN `AllowEnviromentOverride` tinyint(4) NOT NULL DEFAULT '0';
|
||||
ALTER TABLE estate_settings ADD COLUMN `AllowLandmark` tinyint(4) NOT NULL default '1';
|
||||
ALTER TABLE estate_settings ADD COLUMN `AllowParcelChanges` tinyint(4) NOT NULL default '1';
|
||||
ALTER TABLE estate_settings ADD COLUMN `AllowSetHome` tinyint(4) NOT NULL default '1';
|
||||
COMMIT;
|
||||
|
||||
|
|
|
@ -1,18 +0,0 @@
|
|||
# -----------------
|
||||
:VERSION 1
|
||||
|
||||
BEGIN;
|
||||
|
||||
CREATE TABLE `fsassets` (
|
||||
`id` char(36) NOT NULL,
|
||||
`name` varchar(64) NOT NULL DEFAULT '',
|
||||
`description` varchar(64) NOT NULL DEFAULT '',
|
||||
`type` int(11) NOT NULL,
|
||||
`hash` char(80) NOT NULL,
|
||||
`create_time` int(11) NOT NULL DEFAULT '0',
|
||||
`access_time` int(11) NOT NULL DEFAULT '0',
|
||||
`asset_flags` int(11) NOT NULL DEFAULT '0',
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
|
||||
COMMIT;
|
|
@ -1,14 +1,32 @@
|
|||
:VERSION 4 # -------------------------
|
||||
:VERSION 1 # -------------------------
|
||||
|
||||
BEGIN;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `Friends` (
|
||||
`PrincipalID` varchar(255) NOT NULL DEFAULT '00000000-0000-0000-0000-000000000000',
|
||||
`Friend` varchar(255) NOT NULL,
|
||||
`Flags` varchar(16) NOT NULL DEFAULT '0',
|
||||
`Offered` varchar(32) NOT NULL DEFAULT '0',
|
||||
PRIMARY KEY (`PrincipalID`(36),`Friend`(36)),
|
||||
KEY `PrincipalID` (`PrincipalID`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
CREATE TABLE `Friends` (
|
||||
`PrincipalID` CHAR(36) NOT NULL,
|
||||
`Friend` VARCHAR(255) NOT NULL,
|
||||
`Flags` VARCHAR(16) NOT NULL DEFAULT 0,
|
||||
`Offered` VARCHAR(32) NOT NULL DEFAULT 0,
|
||||
PRIMARY KEY(`PrincipalID`, `Friend`),
|
||||
KEY(`PrincipalID`)
|
||||
) ENGINE=InnoDB;
|
||||
|
||||
COMMIT;
|
||||
|
||||
:VERSION 2 # -------------------------
|
||||
|
||||
BEGIN;
|
||||
|
||||
INSERT INTO `Friends` SELECT `ownerID`, `friendID`, `friendPerms`, 0 FROM `userfriends`;
|
||||
|
||||
COMMIT;
|
||||
|
||||
:VERSION 3 # -------------------------
|
||||
|
||||
BEGIN;
|
||||
|
||||
ALTER TABLE `Friends` MODIFY COLUMN PrincipalID varchar(255) NOT NULL DEFAULT '00000000-0000-0000-0000-000000000000';
|
||||
ALTER TABLE `Friends` DROP PRIMARY KEY;
|
||||
ALTER TABLE `Friends` ADD PRIMARY KEY(PrincipalID(36), Friend(36));
|
||||
|
||||
COMMIT;
|
||||
|
|
|
@ -1,52 +1,105 @@
|
|||
:VERSION 10
|
||||
:VERSION 1
|
||||
|
||||
BEGIN;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `regions` (
|
||||
CREATE TABLE `regions` (
|
||||
`uuid` varchar(36) NOT NULL,
|
||||
`regionHandle` bigint(20) unsigned NOT NULL,
|
||||
`regionName` varchar(128) DEFAULT NULL,
|
||||
`regionRecvKey` varchar(128) DEFAULT NULL,
|
||||
`regionSendKey` varchar(128) DEFAULT NULL,
|
||||
`regionSecret` varchar(128) DEFAULT NULL,
|
||||
`regionDataURI` varchar(255) DEFAULT NULL,
|
||||
`serverIP` varchar(64) DEFAULT NULL,
|
||||
`serverPort` int(10) unsigned DEFAULT NULL,
|
||||
`serverURI` varchar(255) DEFAULT NULL,
|
||||
`locX` int(10) unsigned DEFAULT NULL,
|
||||
`locY` int(10) unsigned DEFAULT NULL,
|
||||
`locZ` int(10) unsigned DEFAULT NULL,
|
||||
`eastOverrideHandle` bigint(20) unsigned DEFAULT NULL,
|
||||
`westOverrideHandle` bigint(20) unsigned DEFAULT NULL,
|
||||
`southOverrideHandle` bigint(20) unsigned DEFAULT NULL,
|
||||
`northOverrideHandle` bigint(20) unsigned DEFAULT NULL,
|
||||
`regionAssetURI` varchar(255) DEFAULT NULL,
|
||||
`regionAssetRecvKey` varchar(128) DEFAULT NULL,
|
||||
`regionAssetSendKey` varchar(128) DEFAULT NULL,
|
||||
`regionUserURI` varchar(255) DEFAULT NULL,
|
||||
`regionUserRecvKey` varchar(128) DEFAULT NULL,
|
||||
`regionUserSendKey` varchar(128) DEFAULT NULL,
|
||||
`regionMapTexture` varchar(36) DEFAULT NULL,
|
||||
`serverHttpPort` int(10) DEFAULT NULL,
|
||||
`serverRemotingPort` int(10) DEFAULT NULL,
|
||||
`owner_uuid` varchar(36) NOT NULL DEFAULT '00000000-0000-0000-0000-000000000000',
|
||||
`originUUID` varchar(36) DEFAULT NULL,
|
||||
`access` int(10) unsigned DEFAULT '1',
|
||||
`ScopeID` char(36) NOT NULL DEFAULT '00000000-0000-0000-0000-000000000000',
|
||||
`sizeX` int(11) NOT NULL DEFAULT '0',
|
||||
`sizeY` int(11) NOT NULL DEFAULT '0',
|
||||
`flags` int(11) NOT NULL DEFAULT '0',
|
||||
`last_seen` int(11) NOT NULL DEFAULT '0',
|
||||
`PrincipalID` char(36) NOT NULL DEFAULT '00000000-0000-0000-0000-000000000000',
|
||||
`Token` varchar(255) NOT NULL,
|
||||
`parcelMapTexture` varchar(36) DEFAULT NULL,
|
||||
`regionName` varchar(32) default NULL,
|
||||
`regionRecvKey` varchar(128) default NULL,
|
||||
`regionSendKey` varchar(128) default NULL,
|
||||
`regionSecret` varchar(128) default NULL,
|
||||
`regionDataURI` varchar(255) default NULL,
|
||||
`serverIP` varchar(64) default NULL,
|
||||
`serverPort` int(10) unsigned default NULL,
|
||||
`serverURI` varchar(255) default NULL,
|
||||
`locX` int(10) unsigned default NULL,
|
||||
`locY` int(10) unsigned default NULL,
|
||||
`locZ` int(10) unsigned default NULL,
|
||||
`eastOverrideHandle` bigint(20) unsigned default NULL,
|
||||
`westOverrideHandle` bigint(20) unsigned default NULL,
|
||||
`southOverrideHandle` bigint(20) unsigned default NULL,
|
||||
`northOverrideHandle` bigint(20) unsigned default NULL,
|
||||
`regionAssetURI` varchar(255) default NULL,
|
||||
`regionAssetRecvKey` varchar(128) default NULL,
|
||||
`regionAssetSendKey` varchar(128) default NULL,
|
||||
`regionUserURI` varchar(255) default NULL,
|
||||
`regionUserRecvKey` varchar(128) default NULL,
|
||||
`regionUserSendKey` varchar(128) default NULL, `regionMapTexture` varchar(36) default NULL,
|
||||
`serverHttpPort` int(10) default NULL, `serverRemotingPort` int(10) default NULL,
|
||||
`owner_uuid` varchar(36) default '00000000-0000-0000-0000-000000000000' not null,
|
||||
`originUUID` varchar(36),
|
||||
PRIMARY KEY (`uuid`),
|
||||
KEY `regionName` (`regionName`),
|
||||
KEY `regionHandle` (`regionHandle`),
|
||||
KEY `overrideHandles` (`eastOverrideHandle`,`westOverrideHandle`,`southOverrideHandle`,`northOverrideHandle`),
|
||||
KEY `ScopeID` (`ScopeID`),
|
||||
KEY `flags` (`flags`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
KEY `overrideHandles` (`eastOverrideHandle`,`westOverrideHandle`,`southOverrideHandle`,`northOverrideHandle`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Rev. 3';
|
||||
|
||||
:VERSION 2
|
||||
|
||||
BEGIN;
|
||||
|
||||
ALTER TABLE regions add column access integer unsigned default 1;
|
||||
|
||||
COMMIT;
|
||||
|
||||
:VERSION 3
|
||||
|
||||
BEGIN;
|
||||
|
||||
ALTER TABLE regions add column ScopeID char(36) not null default '00000000-0000-0000-0000-000000000000';
|
||||
|
||||
create index ScopeID on regions(ScopeID);
|
||||
|
||||
COMMIT;
|
||||
|
||||
:VERSION 4
|
||||
|
||||
BEGIN;
|
||||
|
||||
ALTER TABLE regions add column sizeX integer not null default 0;
|
||||
ALTER TABLE regions add column sizeY integer not null default 0;
|
||||
|
||||
COMMIT;
|
||||
|
||||
:VERSION 5
|
||||
|
||||
BEGIN;
|
||||
|
||||
ALTER TABLE `regions` ADD COLUMN `flags` integer NOT NULL DEFAULT 0;
|
||||
CREATE INDEX flags ON regions(flags);
|
||||
|
||||
COMMIT;
|
||||
|
||||
:VERSION 6
|
||||
|
||||
BEGIN;
|
||||
|
||||
ALTER TABLE `regions` ADD COLUMN `last_seen` integer NOT NULL DEFAULT 0;
|
||||
|
||||
COMMIT;
|
||||
|
||||
:VERSION 7
|
||||
|
||||
BEGIN;
|
||||
|
||||
ALTER TABLE `regions` ADD COLUMN `PrincipalID` char(36) NOT NULL DEFAULT '00000000-0000-0000-0000-000000000000';
|
||||
ALTER TABLE `regions` ADD COLUMN `Token` varchar(255) NOT NULL;
|
||||
|
||||
COMMIT;
|
||||
|
||||
|
||||
:VERSION 8 # ------------
|
||||
|
||||
BEGIN;
|
||||
|
||||
alter table regions modify column regionName varchar(128) default NULL;
|
||||
|
||||
COMMIT;
|
||||
|
||||
:VERSION 9 # ------------
|
||||
|
||||
BEGIN;
|
||||
|
||||
alter table regions add column `parcelMapTexture` varchar(36) default NULL;
|
||||
|
||||
COMMIT;
|
||||
|
||||
|
|
|
@ -16,9 +16,3 @@ CREATE TABLE `hg_traveling_data` (
|
|||
|
||||
COMMIT;
|
||||
|
||||
:VERSION 2 # --------------------------
|
||||
|
||||
ALTER TABLE `hg_traveling_data` MODIFY `TMStamp` timestamp NOT NULL default CURRENT_TIMESTAMP;
|
||||
|
||||
COMMIT;
|
||||
|
||||
|
|
|
@ -1,16 +1,42 @@
|
|||
:VERSION 5 # --------------------------
|
||||
:VERSION 1 # --------------------------
|
||||
|
||||
BEGIN;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `im_offline` (
|
||||
`ID` mediumint(9) NOT NULL AUTO_INCREMENT,
|
||||
`PrincipalID` char(36) NOT NULL DEFAULT '',
|
||||
`FromID` char(36) NOT NULL DEFAULT '',
|
||||
CREATE TABLE `im_offline` (
|
||||
`ID` MEDIUMINT NOT NULL AUTO_INCREMENT,
|
||||
`PrincipalID` char(36) NOT NULL default '',
|
||||
`Message` text NOT NULL,
|
||||
`TMStamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
`TMStamp` timestamp NOT NULL,
|
||||
PRIMARY KEY (`ID`),
|
||||
KEY `PrincipalID` (`PrincipalID`),
|
||||
KEY `FromID` (`FromID`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
KEY `PrincipalID` (`PrincipalID`)
|
||||
) ENGINE=MyISAM;
|
||||
|
||||
COMMIT;
|
||||
|
||||
:VERSION 2 # --------------------------
|
||||
|
||||
BEGIN;
|
||||
|
||||
INSERT INTO `im_offline` SELECT * from `diva_im_offline`;
|
||||
DROP TABLE `diva_im_offline`;
|
||||
DELETE FROM `migrations` WHERE name='diva_im_Store';
|
||||
|
||||
COMMIT;
|
||||
|
||||
:VERSION 3 # --------------------------
|
||||
|
||||
BEGIN;
|
||||
|
||||
ALTER TABLE `im_offline`
|
||||
ADD `FromID` char(36) NOT NULL default '' AFTER `PrincipalID`,
|
||||
ADD KEY `FromID` (`FromID`);
|
||||
|
||||
COMMIT;
|
||||
|
||||
:VERSION 4 # --------------------------
|
||||
|
||||
BEGIN;
|
||||
|
||||
ALTER TABLE im_offline CONVERT TO CHARACTER SET utf8;
|
||||
|
||||
COMMIT;
|
||||
|
|
|
@ -1,42 +1,109 @@
|
|||
:VERSION 7 # ------------
|
||||
:VERSION 1 # ------------
|
||||
BEGIN;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `inventoryitems` (
|
||||
`assetID` varchar(36) DEFAULT NULL,
|
||||
`assetType` int(11) DEFAULT NULL,
|
||||
`inventoryName` varchar(64) DEFAULT NULL,
|
||||
`inventoryDescription` varchar(128) DEFAULT NULL,
|
||||
`inventoryNextPermissions` int(10) unsigned DEFAULT NULL,
|
||||
`inventoryCurrentPermissions` int(10) unsigned DEFAULT NULL,
|
||||
`invType` int(11) DEFAULT NULL,
|
||||
`creatorID` varchar(255) NOT NULL DEFAULT '00000000-0000-0000-0000-000000000000',
|
||||
`inventoryBasePermissions` int(10) unsigned NOT NULL DEFAULT '0',
|
||||
`inventoryEveryOnePermissions` int(10) unsigned NOT NULL DEFAULT '0',
|
||||
`salePrice` int(11) NOT NULL DEFAULT '0',
|
||||
`saleType` tinyint(4) NOT NULL DEFAULT '0',
|
||||
`creationDate` int(11) NOT NULL DEFAULT '0',
|
||||
`groupID` varchar(36) NOT NULL DEFAULT '00000000-0000-0000-0000-000000000000',
|
||||
`groupOwned` tinyint(4) NOT NULL DEFAULT '0',
|
||||
`flags` int(11) unsigned NOT NULL DEFAULT '0',
|
||||
`inventoryID` char(36) NOT NULL DEFAULT '00000000-0000-0000-0000-000000000000',
|
||||
`avatarID` char(36) DEFAULT NULL,
|
||||
`parentFolderID` char(36) DEFAULT NULL,
|
||||
`inventoryGroupPermissions` int(10) unsigned NOT NULL DEFAULT '0',
|
||||
PRIMARY KEY (`inventoryID`),
|
||||
KEY `inventoryitems_avatarid` (`avatarID`),
|
||||
KEY `inventoryitems_parentFolderid` (`parentFolderID`)
|
||||
CREATE TABLE `inventoryfolders` (
|
||||
`folderID` varchar(36) NOT NULL default '',
|
||||
`agentID` varchar(36) default NULL,
|
||||
`parentFolderID` varchar(36) default NULL,
|
||||
`folderName` varchar(64) default NULL,
|
||||
`type` smallint NOT NULL default 0,
|
||||
`version` int NOT NULL default 0,
|
||||
PRIMARY KEY (`folderID`),
|
||||
KEY `owner` (`agentID`),
|
||||
KEY `parent` (`parentFolderID`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `inventoryfolders` (
|
||||
`folderName` varchar(64) DEFAULT NULL,
|
||||
`type` smallint(6) NOT NULL DEFAULT '0',
|
||||
`version` int(11) NOT NULL DEFAULT '0',
|
||||
`folderID` char(36) NOT NULL DEFAULT '00000000-0000-0000-0000-000000000000',
|
||||
`agentID` char(36) DEFAULT NULL,
|
||||
`parentFolderID` char(36) DEFAULT NULL,
|
||||
PRIMARY KEY (`folderID`),
|
||||
KEY `inventoryfolders_agentid` (`agentID`),
|
||||
KEY `inventoryfolders_parentFolderid` (`parentFolderID`)
|
||||
CREATE TABLE `inventoryitems` (
|
||||
`inventoryID` varchar(36) NOT NULL default '',
|
||||
`assetID` varchar(36) default NULL,
|
||||
`assetType` int(11) default NULL,
|
||||
`parentFolderID` varchar(36) default NULL,
|
||||
`avatarID` varchar(36) default NULL,
|
||||
`inventoryName` varchar(64) default NULL,
|
||||
`inventoryDescription` varchar(128) default NULL,
|
||||
`inventoryNextPermissions` int(10) unsigned default NULL,
|
||||
`inventoryCurrentPermissions` int(10) unsigned default NULL,
|
||||
`invType` int(11) default NULL,
|
||||
`creatorID` varchar(36) default NULL,
|
||||
`inventoryBasePermissions` int(10) unsigned NOT NULL default 0,
|
||||
`inventoryEveryOnePermissions` int(10) unsigned NOT NULL default 0,
|
||||
`salePrice` int(11) NOT NULL default 0,
|
||||
`saleType` tinyint(4) NOT NULL default 0,
|
||||
`creationDate` int(11) NOT NULL default 0,
|
||||
`groupID` varchar(36) NOT NULL default '00000000-0000-0000-0000-000000000000',
|
||||
`groupOwned` tinyint(4) NOT NULL default 0,
|
||||
`flags` int(11) unsigned NOT NULL default 0,
|
||||
PRIMARY KEY (`inventoryID`),
|
||||
KEY `owner` (`avatarID`),
|
||||
KEY `folder` (`parentFolderID`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
|
||||
COMMIT;
|
||||
|
||||
:VERSION 2 # ------------
|
||||
|
||||
BEGIN;
|
||||
|
||||
ALTER TABLE inventoryfolders change folderID folderIDold varchar(36);
|
||||
ALTER TABLE inventoryfolders change agentID agentIDold varchar(36);
|
||||
ALTER TABLE inventoryfolders change parentFolderID parentFolderIDold varchar(36);
|
||||
ALTER TABLE inventoryfolders add folderID char(36) not null default '00000000-0000-0000-0000-000000000000';
|
||||
ALTER TABLE inventoryfolders add agentID char(36) default NULL;
|
||||
ALTER TABLE inventoryfolders add parentFolderID char(36) default NULL;
|
||||
UPDATE inventoryfolders set folderID = folderIDold, agentID = agentIDold, parentFolderID = parentFolderIDold;
|
||||
ALTER TABLE inventoryfolders drop folderIDold;
|
||||
ALTER TABLE inventoryfolders drop agentIDold;
|
||||
ALTER TABLE inventoryfolders drop parentFolderIDold;
|
||||
ALTER TABLE inventoryfolders add constraint primary key(folderID);
|
||||
ALTER TABLE inventoryfolders add index inventoryfolders_agentid(agentID);
|
||||
ALTER TABLE inventoryfolders add index inventoryfolders_parentFolderid(parentFolderID);
|
||||
|
||||
ALTER TABLE inventoryitems change inventoryID inventoryIDold varchar(36);
|
||||
ALTER TABLE inventoryitems change avatarID avatarIDold varchar(36);
|
||||
ALTER TABLE inventoryitems change parentFolderID parentFolderIDold varchar(36);
|
||||
ALTER TABLE inventoryitems add inventoryID char(36) not null default '00000000-0000-0000-0000-000000000000';
|
||||
ALTER TABLE inventoryitems add avatarID char(36) default NULL;
|
||||
ALTER TABLE inventoryitems add parentFolderID char(36) default NULL;
|
||||
UPDATE inventoryitems set inventoryID = inventoryIDold, avatarID = avatarIDold, parentFolderID = parentFolderIDold;
|
||||
ALTER TABLE inventoryitems drop inventoryIDold;
|
||||
ALTER TABLE inventoryitems drop avatarIDold;
|
||||
ALTER TABLE inventoryitems drop parentFolderIDold;
|
||||
ALTER TABLE inventoryitems add constraint primary key(inventoryID);
|
||||
ALTER TABLE inventoryitems add index inventoryitems_avatarid(avatarID);
|
||||
ALTER TABLE inventoryitems add index inventoryitems_parentFolderid(parentFolderID);
|
||||
|
||||
COMMIT;
|
||||
|
||||
:VERSION 3 # ------------
|
||||
|
||||
BEGIN;
|
||||
|
||||
alter table inventoryitems add column inventoryGroupPermissions integer unsigned not null default 0;
|
||||
|
||||
COMMIT;
|
||||
|
||||
:VERSION 4 # ------------
|
||||
|
||||
BEGIN;
|
||||
|
||||
update inventoryitems set creatorID = '00000000-0000-0000-0000-000000000000' where creatorID is NULL;
|
||||
update inventoryitems set creatorID = '00000000-0000-0000-0000-000000000000' where creatorID = '';
|
||||
alter table inventoryitems modify column creatorID varchar(36) not NULL default '00000000-0000-0000-0000-000000000000';
|
||||
|
||||
COMMIT;
|
||||
|
||||
:VERSION 5 # ------------
|
||||
|
||||
BEGIN;
|
||||
|
||||
alter table inventoryitems modify column creatorID varchar(128) not NULL default '00000000-0000-0000-0000-000000000000';
|
||||
|
||||
COMMIT;
|
||||
|
||||
:VERSION 6 # ------------
|
||||
|
||||
BEGIN;
|
||||
|
||||
alter table inventoryitems modify column creatorID varchar(255) not NULL default '00000000-0000-0000-0000-000000000000';
|
||||
|
||||
COMMIT;
|
||||
|
|
|
@ -1,16 +0,0 @@
|
|||
:VERSION 1
|
||||
|
||||
BEGIN;
|
||||
|
||||
CREATE TABLE `MuteList` (
|
||||
`AgentID` char(36) NOT NULL,
|
||||
`MuteID` char(36) NOT NULL DEFAULT '00000000-0000-0000-0000-000000000000',
|
||||
`MuteName` varchar(64) NOT NULL DEFAULT '',
|
||||
`MuteType` int(11) NOT NULL DEFAULT '1',
|
||||
`MuteFlags` int(11) NOT NULL DEFAULT '0',
|
||||
`Stamp` int(11) NOT NULL,
|
||||
UNIQUE KEY `AgentID_2` (`AgentID`,`MuteID`,`MuteName`),
|
||||
KEY `AgentID` (`AgentID`)
|
||||
);
|
||||
|
||||
COMMIT;
|
|
@ -1,16 +1,31 @@
|
|||
:VERSION 4 # --------------------------
|
||||
:VERSION 1 # --------------------------
|
||||
|
||||
BEGIN;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `Presence` (
|
||||
`UserID` varchar(255) NOT NULL,
|
||||
`RegionID` char(36) NOT NULL DEFAULT '00000000-0000-0000-0000-000000000000',
|
||||
`SessionID` char(36) NOT NULL DEFAULT '00000000-0000-0000-0000-000000000000',
|
||||
`SecureSessionID` char(36) NOT NULL DEFAULT '00000000-0000-0000-0000-000000000000',
|
||||
`LastSeen` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
UNIQUE KEY `SessionID` (`SessionID`),
|
||||
KEY `UserID` (`UserID`),
|
||||
KEY `RegionID` (`RegionID`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
CREATE TABLE `Presence` (
|
||||
`UserID` VARCHAR(255) NOT NULL,
|
||||
`RegionID` CHAR(36) NOT NULL DEFAULT '00000000-0000-0000-0000-000000000000',
|
||||
`SessionID` CHAR(36) NOT NULL DEFAULT '00000000-0000-0000-0000-000000000000',
|
||||
`SecureSessionID` CHAR(36) NOT NULL DEFAULT '00000000-0000-0000-0000-000000000000'
|
||||
) ENGINE=InnoDB;
|
||||
|
||||
CREATE UNIQUE INDEX SessionID ON Presence(SessionID);
|
||||
CREATE INDEX UserID ON Presence(UserID);
|
||||
|
||||
COMMIT;
|
||||
|
||||
:VERSION 2 # --------------------------
|
||||
|
||||
BEGIN;
|
||||
|
||||
ALTER TABLE `Presence` ADD COLUMN LastSeen timestamp;
|
||||
|
||||
COMMIT;
|
||||
|
||||
:VERSION 3 # --------------------------
|
||||
|
||||
BEGIN;
|
||||
|
||||
CREATE INDEX RegionID ON Presence(RegionID);
|
||||
|
||||
COMMIT;
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,31 +1,47 @@
|
|||
:VERSION 5 # -------------------------
|
||||
:VERSION 1 # -------------------------
|
||||
|
||||
BEGIN;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `UserAccounts` (
|
||||
`PrincipalID` char(36) NOT NULL,
|
||||
`ScopeID` char(36) NOT NULL,
|
||||
`FirstName` varchar(64) NOT NULL,
|
||||
`LastName` varchar(64) NOT NULL,
|
||||
`Email` varchar(64) DEFAULT NULL,
|
||||
`ServiceURLs` text,
|
||||
`Created` int(11) DEFAULT NULL,
|
||||
`UserLevel` int(11) NOT NULL DEFAULT '0',
|
||||
`UserFlags` int(11) NOT NULL DEFAULT '0',
|
||||
`UserTitle` varchar(64) NOT NULL DEFAULT '',
|
||||
UNIQUE KEY `PrincipalID` (`PrincipalID`),
|
||||
KEY `Email` (`Email`),
|
||||
KEY `FirstName` (`FirstName`),
|
||||
KEY `LastName` (`LastName`),
|
||||
KEY `Name` (`FirstName`,`LastName`)
|
||||
CREATE TABLE `UserAccounts` (
|
||||
`PrincipalID` CHAR(36) NOT NULL,
|
||||
`ScopeID` CHAR(36) NOT NULL,
|
||||
`FirstName` VARCHAR(64) NOT NULL,
|
||||
`LastName` VARCHAR(64) NOT NULL,
|
||||
`Email` VARCHAR(64),
|
||||
`ServiceURLs` TEXT,
|
||||
`Created` INT(11)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
|
||||
COMMIT;
|
||||
|
||||
:VERSION 6 # -------------------------
|
||||
:VERSION 2 # -------------------------
|
||||
|
||||
BEGIN;
|
||||
|
||||
ALTER TABLE `UserAccounts` ADD `active` INT NOT NULL DEFAULT '1';
|
||||
INSERT INTO UserAccounts (PrincipalID, ScopeID, FirstName, LastName, Email, ServiceURLs, Created) SELECT `UUID` AS PrincipalID, '00000000-0000-0000-0000-000000000000' AS ScopeID, username AS FirstName, lastname AS LastName, email as Email, CONCAT('AssetServerURI=', userAssetURI, ' InventoryServerURI=', userInventoryURI, ' GatewayURI= HomeURI=') AS ServiceURLs, created as Created FROM users;
|
||||
|
||||
COMMIT;
|
||||
|
||||
:VERSION 3 # -------------------------
|
||||
|
||||
BEGIN;
|
||||
|
||||
CREATE UNIQUE INDEX PrincipalID ON UserAccounts(PrincipalID);
|
||||
CREATE INDEX Email ON UserAccounts(Email);
|
||||
CREATE INDEX FirstName ON UserAccounts(FirstName);
|
||||
CREATE INDEX LastName ON UserAccounts(LastName);
|
||||
CREATE INDEX Name ON UserAccounts(FirstName,LastName);
|
||||
|
||||
COMMIT;
|
||||
|
||||
:VERSION 4 # -------------------------
|
||||
|
||||
BEGIN;
|
||||
|
||||
ALTER TABLE UserAccounts ADD COLUMN UserLevel integer NOT NULL DEFAULT 0;
|
||||
ALTER TABLE UserAccounts ADD COLUMN UserFlags integer NOT NULL DEFAULT 0;
|
||||
ALTER TABLE UserAccounts ADD COLUMN UserTitle varchar(64) NOT NULL DEFAULT '';
|
||||
|
||||
COMMIT;
|
||||
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
:VERSION 5 # -------------------------------
|
||||
:VERSION 1 # -------------------------------
|
||||
|
||||
begin;
|
||||
|
||||
|
@ -27,7 +27,7 @@ CREATE TABLE IF NOT EXISTS `usernotes` (
|
|||
`targetuuid` varchar(36) NOT NULL,
|
||||
`notes` text NOT NULL,
|
||||
UNIQUE KEY `useruuid` (`useruuid`,`targetuuid`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
|
||||
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `userpicks` (
|
||||
|
@ -44,9 +44,8 @@ CREATE TABLE IF NOT EXISTS `userpicks` (
|
|||
`posglobal` varchar(255) NOT NULL,
|
||||
`sortorder` int(2) NOT NULL,
|
||||
`enabled` enum('true','false') NOT NULL,
|
||||
`gatekeeper` varchar(255),
|
||||
PRIMARY KEY (`pickuuid`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
|
||||
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `userprofile` (
|
||||
|
@ -65,22 +64,35 @@ CREATE TABLE IF NOT EXISTS `userprofile` (
|
|||
`profileFirstImage` varchar(36) NOT NULL,
|
||||
`profileFirstText` text NOT NULL,
|
||||
PRIMARY KEY (`useruuid`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
|
||||
|
||||
commit;
|
||||
|
||||
:VERSION 2 # -------------------------------
|
||||
|
||||
begin;
|
||||
CREATE TABLE IF NOT EXISTS `userdata` (
|
||||
`UserId` char(36) NOT NULL,
|
||||
`TagId` varchar(64) NOT NULL,
|
||||
`DataKey` varchar(255),
|
||||
`DataVal` varchar(255),
|
||||
PRIMARY KEY (`UserId`,`TagId`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
|
||||
|
||||
commit;
|
||||
|
||||
:VERSION 3 # -------------------------------
|
||||
begin;
|
||||
CREATE TABLE IF NOT EXISTS `usersettings` (
|
||||
`useruuid` varchar(36) NOT NULL,
|
||||
`imviaemail` enum('true','false') NOT NULL,
|
||||
`visible` enum('true','false') NOT NULL,
|
||||
`email` varchar(254) NOT NULL,
|
||||
PRIMARY KEY (`useruuid`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
|
||||
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
|
||||
commit;
|
||||
|
||||
:VERSION 4 # -------------------------------
|
||||
begin;
|
||||
ALTER TABLE userpicks ADD COLUMN gatekeeper varchar(255);
|
||||
commit;
|
||||
|
|
|
@ -0,0 +1,168 @@
|
|||
:VERSION 1 # -----------------------------
|
||||
|
||||
BEGIN;
|
||||
|
||||
SET FOREIGN_KEY_CHECKS=0;
|
||||
-- ----------------------------
|
||||
-- Table structure for agents
|
||||
-- ----------------------------
|
||||
CREATE TABLE `agents` (
|
||||
`UUID` varchar(36) NOT NULL,
|
||||
`sessionID` varchar(36) NOT NULL,
|
||||
`secureSessionID` varchar(36) NOT NULL,
|
||||
`agentIP` varchar(16) NOT NULL,
|
||||
`agentPort` int(11) NOT NULL,
|
||||
`agentOnline` tinyint(4) NOT NULL,
|
||||
`loginTime` int(11) NOT NULL,
|
||||
`logoutTime` int(11) NOT NULL,
|
||||
`currentRegion` varchar(36) NOT NULL,
|
||||
`currentHandle` bigint(20) unsigned NOT NULL,
|
||||
`currentPos` varchar(64) NOT NULL,
|
||||
PRIMARY KEY (`UUID`),
|
||||
UNIQUE KEY `session` (`sessionID`),
|
||||
UNIQUE KEY `ssession` (`secureSessionID`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
|
||||
-- Create schema avatar_appearance
|
||||
--
|
||||
|
||||
CREATE TABLE `avatarappearance` (
|
||||
Owner char(36) NOT NULL,
|
||||
Serial int(10) unsigned NOT NULL,
|
||||
Visual_Params blob NOT NULL,
|
||||
Texture blob NOT NULL,
|
||||
Avatar_Height float NOT NULL,
|
||||
Body_Item char(36) NOT NULL,
|
||||
Body_Asset char(36) NOT NULL,
|
||||
Skin_Item char(36) NOT NULL,
|
||||
Skin_Asset char(36) NOT NULL,
|
||||
Hair_Item char(36) NOT NULL,
|
||||
Hair_Asset char(36) NOT NULL,
|
||||
Eyes_Item char(36) NOT NULL,
|
||||
Eyes_Asset char(36) NOT NULL,
|
||||
Shirt_Item char(36) NOT NULL,
|
||||
Shirt_Asset char(36) NOT NULL,
|
||||
Pants_Item char(36) NOT NULL,
|
||||
Pants_Asset char(36) NOT NULL,
|
||||
Shoes_Item char(36) NOT NULL,
|
||||
Shoes_Asset char(36) NOT NULL,
|
||||
Socks_Item char(36) NOT NULL,
|
||||
Socks_Asset char(36) NOT NULL,
|
||||
Jacket_Item char(36) NOT NULL,
|
||||
Jacket_Asset char(36) NOT NULL,
|
||||
Gloves_Item char(36) NOT NULL,
|
||||
Gloves_Asset char(36) NOT NULL,
|
||||
Undershirt_Item char(36) NOT NULL,
|
||||
Undershirt_Asset char(36) NOT NULL,
|
||||
Underpants_Item char(36) NOT NULL,
|
||||
Underpants_Asset char(36) NOT NULL,
|
||||
Skirt_Item char(36) NOT NULL,
|
||||
Skirt_Asset char(36) NOT NULL,
|
||||
PRIMARY KEY (`Owner`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
|
||||
SET FOREIGN_KEY_CHECKS=0;
|
||||
-- ----------------------------
|
||||
-- Table structure for users
|
||||
-- ----------------------------
|
||||
CREATE TABLE `userfriends` (
|
||||
`ownerID` VARCHAR(37) NOT NULL,
|
||||
`friendID` VARCHAR(37) NOT NULL,
|
||||
`friendPerms` INT NOT NULL,
|
||||
`datetimestamp` INT NOT NULL,
|
||||
UNIQUE KEY (`ownerID`, `friendID`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
-- ----------------------------
|
||||
-- Table structure for users
|
||||
-- ----------------------------
|
||||
CREATE TABLE `users` (
|
||||
`UUID` varchar(36) NOT NULL default '',
|
||||
`username` varchar(32) NOT NULL,
|
||||
`lastname` varchar(32) NOT NULL,
|
||||
`passwordHash` varchar(32) NOT NULL,
|
||||
`passwordSalt` varchar(32) NOT NULL,
|
||||
`homeRegion` bigint(20) unsigned default NULL,
|
||||
`homeLocationX` float default NULL,
|
||||
`homeLocationY` float default NULL,
|
||||
`homeLocationZ` float default NULL,
|
||||
`homeLookAtX` float default NULL,
|
||||
`homeLookAtY` float default NULL,
|
||||
`homeLookAtZ` float default NULL,
|
||||
`created` int(11) NOT NULL,
|
||||
`lastLogin` int(11) NOT NULL,
|
||||
`userInventoryURI` varchar(255) default NULL,
|
||||
`userAssetURI` varchar(255) default NULL,
|
||||
`profileCanDoMask` int(10) unsigned default NULL,
|
||||
`profileWantDoMask` int(10) unsigned default NULL,
|
||||
`profileAboutText` text,
|
||||
`profileFirstText` text,
|
||||
`profileImage` varchar(36) default NULL,
|
||||
`profileFirstImage` varchar(36) default NULL,
|
||||
`webLoginKey` varchar(36) default NULL,
|
||||
PRIMARY KEY (`UUID`),
|
||||
UNIQUE KEY `usernames` (`username`,`lastname`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
|
||||
-- ----------------------------
|
||||
-- Records
|
||||
-- ----------------------------
|
||||
COMMIT;
|
||||
|
||||
:VERSION 2 # -----------------------------
|
||||
|
||||
BEGIN;
|
||||
|
||||
ALTER TABLE users add homeRegionID char(36) NOT NULL default '00000000-0000-0000-0000-000000000000';
|
||||
|
||||
COMMIT;
|
||||
|
||||
:VERSION 3 # -----------------------------
|
||||
|
||||
BEGIN;
|
||||
|
||||
ALTER TABLE users add userFlags integer NOT NULL default 0;
|
||||
ALTER TABLE users add godLevel integer NOT NULL default 0;
|
||||
|
||||
COMMIT;
|
||||
|
||||
:VERSION 4 # -----------------------------
|
||||
|
||||
BEGIN;
|
||||
|
||||
ALTER TABLE users add customType varchar(32) not null default '';
|
||||
ALTER TABLE users add partner char(36) not null default '00000000-0000-0000-0000-000000000000';
|
||||
|
||||
COMMIT;
|
||||
|
||||
:VERSION 5 # -----------------------------
|
||||
|
||||
BEGIN;
|
||||
|
||||
CREATE TABLE `avatarattachments` (`UUID` char(36) NOT NULL, `attachpoint` int(11) NOT NULL, `item` char(36) NOT NULL, `asset` char(36) NOT NULL) ENGINE=InnoDB;
|
||||
|
||||
COMMIT;
|
||||
|
||||
:VERSION 6 # -----------------------------
|
||||
|
||||
BEGIN;
|
||||
|
||||
ALTER TABLE agents add currentLookAt varchar(36) not null default '';
|
||||
|
||||
COMMIT;
|
||||
|
||||
:VERSION 7 # -----------------------------
|
||||
|
||||
BEGIN;
|
||||
|
||||
ALTER TABLE users add email varchar(250);
|
||||
|
||||
COMMIT;
|
||||
|
||||
:VERSION 8 # -----------------------------
|
||||
|
||||
BEGIN;
|
||||
|
||||
ALTER TABLE users add scopeID char(36) not null default '00000000-0000-0000-0000-000000000000';
|
||||
|
||||
COMMIT;
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue