Part #2 of previous commit.
parent
0ab3e9a399
commit
778092e075
|
@ -0,0 +1,41 @@
|
||||||
|
<property name="projectdir" value="opensim-0.4" />
|
||||||
|
|
||||||
|
<target name="distdir">
|
||||||
|
<delete dir="${projectdir}" />
|
||||||
|
<copy todir="${projectdir}">
|
||||||
|
<fileset basedir=".">
|
||||||
|
<include name="ThirdPartyLicenses/**" />
|
||||||
|
<include name="CONTRIBUTORS.txt" />
|
||||||
|
<include name="README" />
|
||||||
|
<include name="OpenSim/**/*.cs" />
|
||||||
|
<include name="**/*.build" />
|
||||||
|
<include name="**/*.csproj" />
|
||||||
|
<include name="**/*.csproj.user" />
|
||||||
|
<include name="**/*.sln" />
|
||||||
|
<include name="bin/*.dll" />
|
||||||
|
<include name="bin/*.so" />
|
||||||
|
<include name="bin/*.config" />
|
||||||
|
<include name="bin/assets/**" />
|
||||||
|
<include name="bin/data/**" />
|
||||||
|
<include name="bin/OpenSim*xml" />
|
||||||
|
<!-- the next is to exclude built libs -->
|
||||||
|
<exclude name="bin/OpenSim.*dll" />
|
||||||
|
<include name="bin/OpenSim.ini" />
|
||||||
|
<include name="bin/defaultstripe.png" />
|
||||||
|
</fileset>
|
||||||
|
</copy>
|
||||||
|
<touch file="${projectdir}/bin/startup_commands.txt" />
|
||||||
|
</target>
|
||||||
|
|
||||||
|
<target name="dist" depends="distdir">
|
||||||
|
<zip zipfile="${projectdir}.zip">
|
||||||
|
<fileset basedir=".">
|
||||||
|
<include name="${projectdir}/**" />
|
||||||
|
</fileset>
|
||||||
|
</zip>
|
||||||
|
<tar destfile="${projectdir}.tar.gz" compression="GZip">
|
||||||
|
<fileset basedir=".">
|
||||||
|
<include name="${projectdir}/**" />
|
||||||
|
</fileset>
|
||||||
|
</tar>
|
||||||
|
</target>
|
|
@ -0,0 +1,106 @@
|
||||||
|
/*
|
||||||
|
* 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 OpenSim 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 Mono.Addins;
|
||||||
|
using OpenSim.Framework;
|
||||||
|
using OpenSim.Framework.Console;
|
||||||
|
using OpenSim.Framework.RegionLoader.Filesystem;
|
||||||
|
using OpenSim.Framework.RegionLoader.Web;
|
||||||
|
|
||||||
|
[assembly : Addin]
|
||||||
|
[assembly : AddinDependency("OpenSim", "0.4")]
|
||||||
|
|
||||||
|
namespace OpenSim.ApplicationPlugins.LoadRegions
|
||||||
|
{
|
||||||
|
[Extension("/OpenSim/Startup")]
|
||||||
|
public class LoadRegionsPlugin : IApplicationPlugin
|
||||||
|
{
|
||||||
|
public void Initialise(OpenSimMain openSim)
|
||||||
|
{
|
||||||
|
MainLog.Instance.Notice("LOADREGIONS", "Load Regions addin being initialised");
|
||||||
|
|
||||||
|
IRegionLoader regionLoader;
|
||||||
|
if (openSim.ConfigSource.Configs["Startup"].GetString("region_info_source", "filesystem") == "filesystem")
|
||||||
|
{
|
||||||
|
MainLog.Instance.Notice("LOADREGIONS", "Loading Region Info from filesystem");
|
||||||
|
regionLoader = new RegionLoaderFileSystem();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
MainLog.Instance.Notice("LOADREGIONSPLUGIN", "Loading Region Info from web");
|
||||||
|
regionLoader = new RegionLoaderWebServer();
|
||||||
|
}
|
||||||
|
|
||||||
|
regionLoader.SetIniConfigSource(openSim.ConfigSource);
|
||||||
|
RegionInfo[] regionsToLoad = regionLoader.LoadRegions();
|
||||||
|
|
||||||
|
openSim.ModuleLoader.LoadDefaultSharedModules();
|
||||||
|
|
||||||
|
for (int i = 0; i < regionsToLoad.Length; i++)
|
||||||
|
{
|
||||||
|
MainLog.Instance.Debug("LOADREGIONS", "Creating Region: " + regionsToLoad[i].RegionName + " (ThreadID: " + System.Threading.Thread.CurrentThread.ManagedThreadId.ToString() + ")");
|
||||||
|
openSim.CreateRegion(regionsToLoad[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
openSim.ModuleLoader.PostInitialise();
|
||||||
|
openSim.ModuleLoader.ClearCache();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void LoadRegionFromConfig(OpenSimMain openSim, ulong regionhandle)
|
||||||
|
{
|
||||||
|
MainLog.Instance.Notice("LOADREGIONS", "Load Regions addin being initialised");
|
||||||
|
|
||||||
|
IRegionLoader regionLoader;
|
||||||
|
if (openSim.ConfigSource.Configs["Startup"].GetString("region_info_source", "filesystem") == "filesystem")
|
||||||
|
{
|
||||||
|
MainLog.Instance.Notice("LOADREGIONS", "Loading Region Info from filesystem");
|
||||||
|
regionLoader = new RegionLoaderFileSystem();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
MainLog.Instance.Notice("LOADREGIONS", "Loading Region Info from web");
|
||||||
|
regionLoader = new RegionLoaderWebServer();
|
||||||
|
}
|
||||||
|
|
||||||
|
regionLoader.SetIniConfigSource(openSim.ConfigSource);
|
||||||
|
RegionInfo[] regionsToLoad = regionLoader.LoadRegions();
|
||||||
|
for (int i = 0; i < regionsToLoad.Length; i++)
|
||||||
|
{
|
||||||
|
if (regionhandle == regionsToLoad[i].RegionHandle)
|
||||||
|
{
|
||||||
|
MainLog.Instance.Debug("LOADREGIONS", "Creating Region: " + regionsToLoad[i].RegionName + " (ThreadID: " + System.Threading.Thread.CurrentThread.ManagedThreadId.ToString() + ")");
|
||||||
|
openSim.CreateRegion(regionsToLoad[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Close()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,39 @@
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
// General Information about an assembly is controlled through the following
|
||||||
|
// set of attributes. Change these attribute values to modify the information
|
||||||
|
// associated with an assembly.
|
||||||
|
|
||||||
|
[assembly : AssemblyTitle("OpenSim.Addin")]
|
||||||
|
[assembly : AssemblyDescription("")]
|
||||||
|
[assembly : AssemblyConfiguration("")]
|
||||||
|
[assembly : AssemblyCompany("")]
|
||||||
|
[assembly : AssemblyProduct("OpenSim.Addin")]
|
||||||
|
[assembly : AssemblyCopyright("Copyright © 2007")]
|
||||||
|
[assembly : AssemblyTrademark("")]
|
||||||
|
[assembly : AssemblyCulture("")]
|
||||||
|
|
||||||
|
// Setting ComVisible to false makes the types in this assembly not visible
|
||||||
|
// to COM components. If you need to access a type in this assembly from
|
||||||
|
// COM, set the ComVisible attribute to true on that type.
|
||||||
|
|
||||||
|
[assembly : ComVisible(false)]
|
||||||
|
|
||||||
|
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||||
|
|
||||||
|
[assembly : Guid("45b979d9-d8d4-42fd-9780-fe9ac7e86cb4")]
|
||||||
|
|
||||||
|
// Version information for an assembly consists of the following four values:
|
||||||
|
//
|
||||||
|
// Major Version
|
||||||
|
// Minor Version
|
||||||
|
// Build Number
|
||||||
|
// Revision
|
||||||
|
//
|
||||||
|
// You can specify all the values or you can default the Build and Revision Numbers
|
||||||
|
// by using the '*' as shown below:
|
||||||
|
// [assembly: AssemblyVersion("1.0.*")]
|
||||||
|
|
||||||
|
[assembly : AssemblyVersion("1.0.0.0")]
|
||||||
|
[assembly : AssemblyFileVersion("1.0.0.0")]
|
|
@ -0,0 +1,250 @@
|
||||||
|
/*
|
||||||
|
* 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 OpenSim 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.Net;
|
||||||
|
using System.Timers;
|
||||||
|
using libsecondlife;
|
||||||
|
using Mono.Addins;
|
||||||
|
using Nwc.XmlRpc;
|
||||||
|
using OpenSim.Framework;
|
||||||
|
using OpenSim.Framework.Console;
|
||||||
|
using OpenSim.Framework.Servers;
|
||||||
|
using OpenSim.Region.Environment.Scenes;
|
||||||
|
|
||||||
|
[assembly : Addin]
|
||||||
|
[assembly : AddinDependency("OpenSim", "0.4")]
|
||||||
|
|
||||||
|
namespace OpenSim.ApplicationPlugins.LoadRegions
|
||||||
|
{
|
||||||
|
[Extension("/OpenSim/Startup")]
|
||||||
|
public class RemoteAdminPlugin : IApplicationPlugin
|
||||||
|
{
|
||||||
|
private OpenSimMain m_app;
|
||||||
|
private BaseHttpServer m_httpd;
|
||||||
|
private string requiredPassword = "";
|
||||||
|
|
||||||
|
public void Initialise(OpenSimMain openSim)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (openSim.ConfigSource.Configs["RemoteAdmin"].GetBoolean("enabled", false))
|
||||||
|
{
|
||||||
|
MainLog.Instance.Verbose("RADMIN", "Remote Admin Plugin Enabled");
|
||||||
|
requiredPassword = openSim.ConfigSource.Configs["RemoteAdmin"].GetString("access_password", "");
|
||||||
|
|
||||||
|
m_app = openSim;
|
||||||
|
m_httpd = openSim.HttpServer;
|
||||||
|
|
||||||
|
m_httpd.AddXmlRPCHandler("admin_create_region", XmlRpcCreateRegionMethod);
|
||||||
|
m_httpd.AddXmlRPCHandler("admin_shutdown", XmlRpcShutdownMethod);
|
||||||
|
m_httpd.AddXmlRPCHandler("admin_broadcast", XmlRpcAlertMethod);
|
||||||
|
m_httpd.AddXmlRPCHandler("admin_restart", XmlRpcRestartMethod);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (NullReferenceException)
|
||||||
|
{
|
||||||
|
// Ignore.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public XmlRpcResponse XmlRpcRestartMethod(XmlRpcRequest request)
|
||||||
|
{
|
||||||
|
XmlRpcResponse response = new XmlRpcResponse();
|
||||||
|
Hashtable requestData = (Hashtable) request.Params[0];
|
||||||
|
|
||||||
|
LLUUID regionID = new LLUUID((string) requestData["regionID"]);
|
||||||
|
|
||||||
|
Hashtable responseData = new Hashtable();
|
||||||
|
if (requiredPassword != "" &&
|
||||||
|
(!requestData.Contains("password") || (string) requestData["password"] != requiredPassword))
|
||||||
|
{
|
||||||
|
responseData["accepted"] = "false";
|
||||||
|
response.Value = responseData;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
responseData["accepted"] = "true";
|
||||||
|
response.Value = responseData;
|
||||||
|
|
||||||
|
Scene RebootedScene;
|
||||||
|
|
||||||
|
if (m_app.SceneManager.TryGetScene(regionID, out RebootedScene))
|
||||||
|
{
|
||||||
|
responseData["rebooting"] = "true";
|
||||||
|
RebootedScene.Restart(30);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
responseData["rebooting"] = "false";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
|
public XmlRpcResponse XmlRpcAlertMethod(XmlRpcRequest request)
|
||||||
|
{
|
||||||
|
XmlRpcResponse response = new XmlRpcResponse();
|
||||||
|
Hashtable requestData = (Hashtable) request.Params[0];
|
||||||
|
|
||||||
|
Hashtable responseData = new Hashtable();
|
||||||
|
if (requiredPassword != "" &&
|
||||||
|
(!requestData.Contains("password") || (string) requestData["password"] != requiredPassword))
|
||||||
|
{
|
||||||
|
responseData["accepted"] = "false";
|
||||||
|
response.Value = responseData;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
string message = (string) requestData["message"];
|
||||||
|
MainLog.Instance.Verbose("RADMIN", "Broadcasting: " + message);
|
||||||
|
|
||||||
|
responseData["accepted"] = "true";
|
||||||
|
response.Value = responseData;
|
||||||
|
|
||||||
|
m_app.SceneManager.SendGeneralMessage(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
|
public XmlRpcResponse XmlRpcShutdownMethod(XmlRpcRequest request)
|
||||||
|
{
|
||||||
|
MainLog.Instance.Verbose("RADMIN", "Received Shutdown Administrator Request");
|
||||||
|
XmlRpcResponse response = new XmlRpcResponse();
|
||||||
|
Hashtable requestData = (Hashtable) request.Params[0];
|
||||||
|
Hashtable responseData = new Hashtable();
|
||||||
|
if (requiredPassword != "" &&
|
||||||
|
(!requestData.Contains("password") || (string) requestData["password"] != requiredPassword))
|
||||||
|
{
|
||||||
|
responseData["accepted"] = "false";
|
||||||
|
response.Value = responseData;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if ((string) requestData["shutdown"] == "delayed")
|
||||||
|
{
|
||||||
|
int timeout = (Int32) requestData["milliseconds"];
|
||||||
|
|
||||||
|
responseData["accepted"] = "true";
|
||||||
|
response.Value = responseData;
|
||||||
|
|
||||||
|
m_app.SceneManager.SendGeneralMessage("Region is going down in " + ((int) (timeout/1000)).ToString() +
|
||||||
|
" second(s). Please save what you are doing and log out.");
|
||||||
|
|
||||||
|
// Perform shutdown
|
||||||
|
Timer shutdownTimer = new Timer(timeout); // Wait before firing
|
||||||
|
shutdownTimer.AutoReset = false;
|
||||||
|
shutdownTimer.Elapsed += new ElapsedEventHandler(shutdownTimer_Elapsed);
|
||||||
|
shutdownTimer.Start();
|
||||||
|
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
responseData["accepted"] = "true";
|
||||||
|
response.Value = responseData;
|
||||||
|
|
||||||
|
m_app.SceneManager.SendGeneralMessage("Region is going down now.");
|
||||||
|
|
||||||
|
// Perform shutdown
|
||||||
|
Timer shutdownTimer = new Timer(2000); // Wait 2 seconds before firing
|
||||||
|
shutdownTimer.AutoReset = false;
|
||||||
|
shutdownTimer.Elapsed += new ElapsedEventHandler(shutdownTimer_Elapsed);
|
||||||
|
shutdownTimer.Start();
|
||||||
|
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void shutdownTimer_Elapsed(object sender, ElapsedEventArgs e)
|
||||||
|
{
|
||||||
|
m_app.Shutdown();
|
||||||
|
}
|
||||||
|
|
||||||
|
public XmlRpcResponse XmlRpcCreateRegionMethod(XmlRpcRequest request)
|
||||||
|
{
|
||||||
|
MainLog.Instance.Verbose("RADMIN", "Received Create Region Administrator Request");
|
||||||
|
XmlRpcResponse response = new XmlRpcResponse();
|
||||||
|
Hashtable requestData = (Hashtable) request.Params[0];
|
||||||
|
Hashtable responseData = new Hashtable();
|
||||||
|
if (requiredPassword != "" &&
|
||||||
|
(!requestData.Contains("password") || (string) requestData["password"] != requiredPassword))
|
||||||
|
{
|
||||||
|
responseData["created"] = "false";
|
||||||
|
response.Value = responseData;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
RegionInfo newRegionData = new RegionInfo();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
newRegionData.RegionID = (string) requestData["region_id"];
|
||||||
|
newRegionData.RegionName = (string) requestData["region_name"];
|
||||||
|
newRegionData.RegionLocX = Convert.ToUInt32((Int32) requestData["region_x"]);
|
||||||
|
newRegionData.RegionLocY = Convert.ToUInt32((Int32) requestData["region_y"]);
|
||||||
|
|
||||||
|
// Security risk
|
||||||
|
newRegionData.DataStore = (string) requestData["datastore"];
|
||||||
|
|
||||||
|
newRegionData.InternalEndPoint = new IPEndPoint(
|
||||||
|
IPAddress.Parse((string) requestData["listen_ip"]), 0);
|
||||||
|
|
||||||
|
newRegionData.InternalEndPoint.Port = (Int32) requestData["listen_port"];
|
||||||
|
newRegionData.ExternalHostName = (string) requestData["external_address"];
|
||||||
|
|
||||||
|
newRegionData.MasterAvatarFirstName = (string) requestData["region_master_first"];
|
||||||
|
newRegionData.MasterAvatarLastName = (string) requestData["region_master_last"];
|
||||||
|
|
||||||
|
m_app.CreateRegion(newRegionData);
|
||||||
|
|
||||||
|
responseData["created"] = "true";
|
||||||
|
response.Value = responseData;
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
responseData["created"] = "false";
|
||||||
|
responseData["error"] = e.ToString();
|
||||||
|
response.Value = responseData;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Close()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,263 @@
|
||||||
|
/*
|
||||||
|
* 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 OpenSim 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;
|
||||||
|
|
||||||
|
namespace OpenSim.Framework
|
||||||
|
{
|
||||||
|
// ACL Class
|
||||||
|
// Modelled after the structure of the Zend ACL Framework Library
|
||||||
|
// with one key difference - the tree will search for all matching
|
||||||
|
// permissions rather than just the first. Deny permissions will
|
||||||
|
// override all others.
|
||||||
|
|
||||||
|
#region ACL Core Class
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Access Control List Engine
|
||||||
|
/// </summary>
|
||||||
|
public class ACL
|
||||||
|
{
|
||||||
|
private Dictionary<string, Role> Roles = new Dictionary<string, Role>();
|
||||||
|
private Dictionary<string, Resource> Resources = new Dictionary<string, Resource>();
|
||||||
|
|
||||||
|
public ACL AddRole(Role role)
|
||||||
|
{
|
||||||
|
if (Roles.ContainsKey(role.Name))
|
||||||
|
throw new AlreadyContainsRoleException(role);
|
||||||
|
|
||||||
|
Roles.Add(role.Name, role);
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ACL AddResource(Resource resource)
|
||||||
|
{
|
||||||
|
Resources.Add(resource.Name, resource);
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Permission HasPermission(string role, string resource)
|
||||||
|
{
|
||||||
|
if (!Roles.ContainsKey(role))
|
||||||
|
throw new KeyNotFoundException();
|
||||||
|
|
||||||
|
if (!Resources.ContainsKey(resource))
|
||||||
|
throw new KeyNotFoundException();
|
||||||
|
|
||||||
|
return Roles[role].RequestPermission(resource);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ACL GrantPermission(string role, string resource)
|
||||||
|
{
|
||||||
|
if (!Roles.ContainsKey(role))
|
||||||
|
throw new KeyNotFoundException();
|
||||||
|
|
||||||
|
if (!Resources.ContainsKey(resource))
|
||||||
|
throw new KeyNotFoundException();
|
||||||
|
|
||||||
|
Roles[role].GivePermission(resource, Permission.Allow);
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ACL DenyPermission(string role, string resource)
|
||||||
|
{
|
||||||
|
if (!Roles.ContainsKey(role))
|
||||||
|
throw new KeyNotFoundException();
|
||||||
|
|
||||||
|
if (!Resources.ContainsKey(resource))
|
||||||
|
throw new KeyNotFoundException();
|
||||||
|
|
||||||
|
Roles[role].GivePermission(resource, Permission.Deny);
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ACL ResetPermission(string role, string resource)
|
||||||
|
{
|
||||||
|
if (!Roles.ContainsKey(role))
|
||||||
|
throw new KeyNotFoundException();
|
||||||
|
|
||||||
|
if (!Resources.ContainsKey(resource))
|
||||||
|
throw new KeyNotFoundException();
|
||||||
|
|
||||||
|
Roles[role].GivePermission(resource, Permission.None);
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Exceptions
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Thrown when an ACL attempts to add a duplicate role.
|
||||||
|
/// </summary>
|
||||||
|
public class AlreadyContainsRoleException : Exception
|
||||||
|
{
|
||||||
|
protected Role m_role;
|
||||||
|
|
||||||
|
public Role ErrorRole
|
||||||
|
{
|
||||||
|
get { return m_role; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public AlreadyContainsRoleException(Role role)
|
||||||
|
{
|
||||||
|
m_role = role;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
return "This ACL already contains a role called '" + m_role.Name + "'.";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Roles and Resources
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Does this Role have permission to access a specified Resource?
|
||||||
|
/// </summary>
|
||||||
|
public enum Permission
|
||||||
|
{
|
||||||
|
Deny,
|
||||||
|
None,
|
||||||
|
Allow
|
||||||
|
} ;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A role class, for use with Users or Groups
|
||||||
|
/// </summary>
|
||||||
|
public class Role
|
||||||
|
{
|
||||||
|
private string m_name;
|
||||||
|
private Role[] m_parents;
|
||||||
|
private Dictionary<string, Permission> m_resources = new Dictionary<string, Permission>();
|
||||||
|
|
||||||
|
public string Name
|
||||||
|
{
|
||||||
|
get { return m_name; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public Permission RequestPermission(string resource)
|
||||||
|
{
|
||||||
|
return RequestPermission(resource, Permission.None);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Permission RequestPermission(string resource, Permission current)
|
||||||
|
{
|
||||||
|
// Deny permissions always override any others
|
||||||
|
if (current == Permission.Deny)
|
||||||
|
return current;
|
||||||
|
|
||||||
|
Permission temp = Permission.None;
|
||||||
|
|
||||||
|
// Pickup non-None permissions
|
||||||
|
if (m_resources.ContainsKey(resource) && m_resources[resource] != Permission.None)
|
||||||
|
temp = m_resources[resource];
|
||||||
|
|
||||||
|
if (m_parents != null)
|
||||||
|
{
|
||||||
|
foreach (Role parent in m_parents)
|
||||||
|
{
|
||||||
|
temp = parent.RequestPermission(resource, temp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void GivePermission(string resource, Permission perm)
|
||||||
|
{
|
||||||
|
m_resources[resource] = perm;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Role(string name)
|
||||||
|
{
|
||||||
|
m_name = name;
|
||||||
|
m_parents = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Role(string name, Role[] parents)
|
||||||
|
{
|
||||||
|
m_name = name;
|
||||||
|
m_parents = parents;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Resource
|
||||||
|
{
|
||||||
|
private string m_name;
|
||||||
|
|
||||||
|
public string Name
|
||||||
|
{
|
||||||
|
get { return m_name; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public Resource(string name)
|
||||||
|
{
|
||||||
|
m_name = name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Tests
|
||||||
|
|
||||||
|
internal class ACLTester
|
||||||
|
{
|
||||||
|
public ACLTester()
|
||||||
|
{
|
||||||
|
ACL acl = new ACL();
|
||||||
|
|
||||||
|
Role Guests = new Role("Guests");
|
||||||
|
acl.AddRole(Guests);
|
||||||
|
|
||||||
|
Role[] parents = new Role[0];
|
||||||
|
parents[0] = Guests;
|
||||||
|
|
||||||
|
Role JoeGuest = new Role("JoeGuest", parents);
|
||||||
|
acl.AddRole(JoeGuest);
|
||||||
|
|
||||||
|
Resource CanBuild = new Resource("CanBuild");
|
||||||
|
acl.AddResource(CanBuild);
|
||||||
|
|
||||||
|
|
||||||
|
acl.GrantPermission("Guests", "CanBuild");
|
||||||
|
|
||||||
|
acl.HasPermission("JoeGuest", "CanBuild");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
|
@ -0,0 +1,111 @@
|
||||||
|
/*
|
||||||
|
* 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 OpenSim 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 libsecondlife;
|
||||||
|
|
||||||
|
namespace OpenSim.Framework
|
||||||
|
{
|
||||||
|
public class AgentCircuitData
|
||||||
|
{
|
||||||
|
public AgentCircuitData()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public AgentCircuitData(sAgentCircuitData cAgent)
|
||||||
|
{
|
||||||
|
AgentID = new LLUUID(cAgent.AgentID);
|
||||||
|
SessionID = new LLUUID(cAgent.SessionID);
|
||||||
|
SecureSessionID = new LLUUID(cAgent.SecureSessionID);
|
||||||
|
startpos = new LLVector3(cAgent.startposx, cAgent.startposy, cAgent.startposz);
|
||||||
|
firstname = cAgent.firstname;
|
||||||
|
lastname = cAgent.lastname;
|
||||||
|
circuitcode = cAgent.circuitcode;
|
||||||
|
child = cAgent.child;
|
||||||
|
InventoryFolder = new LLUUID(cAgent.InventoryFolder);
|
||||||
|
BaseFolder = new LLUUID(cAgent.BaseFolder);
|
||||||
|
CapsPath = cAgent.CapsPath;
|
||||||
|
ClientVersion = cAgent.ClientVersion; //rex
|
||||||
|
}
|
||||||
|
|
||||||
|
public LLUUID AgentID;
|
||||||
|
public LLUUID SessionID;
|
||||||
|
public LLUUID SecureSessionID;
|
||||||
|
public LLVector3 startpos;
|
||||||
|
public string firstname;
|
||||||
|
public string lastname;
|
||||||
|
public uint circuitcode;
|
||||||
|
public bool child;
|
||||||
|
public LLUUID InventoryFolder;
|
||||||
|
public LLUUID BaseFolder;
|
||||||
|
public string CapsPath = "";
|
||||||
|
public string ClientVersion = "not set"; //rex
|
||||||
|
public string authenticationAddr;
|
||||||
|
public string asAddress = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
[Serializable]
|
||||||
|
public class sAgentCircuitData
|
||||||
|
{
|
||||||
|
public sAgentCircuitData()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public sAgentCircuitData(AgentCircuitData cAgent)
|
||||||
|
{
|
||||||
|
AgentID = cAgent.AgentID.UUID;
|
||||||
|
SessionID = cAgent.SessionID.UUID;
|
||||||
|
SecureSessionID = cAgent.SecureSessionID.UUID;
|
||||||
|
startposx = cAgent.startpos.X;
|
||||||
|
startposy = cAgent.startpos.Y;
|
||||||
|
startposz = cAgent.startpos.Z;
|
||||||
|
firstname = cAgent.firstname;
|
||||||
|
lastname = cAgent.lastname;
|
||||||
|
circuitcode = cAgent.circuitcode;
|
||||||
|
child = cAgent.child;
|
||||||
|
InventoryFolder = cAgent.InventoryFolder.UUID;
|
||||||
|
BaseFolder = cAgent.BaseFolder.UUID;
|
||||||
|
CapsPath = cAgent.CapsPath;
|
||||||
|
ClientVersion = cAgent.ClientVersion; //rex
|
||||||
|
}
|
||||||
|
|
||||||
|
public Guid AgentID;
|
||||||
|
public Guid SessionID;
|
||||||
|
public Guid SecureSessionID;
|
||||||
|
public float startposx;
|
||||||
|
public float startposy;
|
||||||
|
public float startposz;
|
||||||
|
public string firstname;
|
||||||
|
public string lastname;
|
||||||
|
public uint circuitcode;
|
||||||
|
public bool child;
|
||||||
|
public Guid InventoryFolder;
|
||||||
|
public Guid BaseFolder;
|
||||||
|
public string CapsPath = "";
|
||||||
|
public string ClientVersion = "not set"; //rex
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,128 @@
|
||||||
|
/*
|
||||||
|
* 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 OpenSim 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 libsecondlife;
|
||||||
|
|
||||||
|
namespace OpenSim.Framework
|
||||||
|
{
|
||||||
|
public class AgentCircuitManager
|
||||||
|
{
|
||||||
|
public Dictionary<uint, AgentCircuitData> AgentCircuits = new Dictionary<uint, AgentCircuitData>();
|
||||||
|
|
||||||
|
public AgentCircuitManager()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual AuthenticateResponse AuthenticateSession(LLUUID sessionID, LLUUID agentID, uint circuitcode)
|
||||||
|
{
|
||||||
|
AgentCircuitData validcircuit = null;
|
||||||
|
if (AgentCircuits.ContainsKey(circuitcode))
|
||||||
|
{
|
||||||
|
validcircuit = AgentCircuits[circuitcode];
|
||||||
|
}
|
||||||
|
AuthenticateResponse user = new AuthenticateResponse();
|
||||||
|
if (validcircuit == null)
|
||||||
|
{
|
||||||
|
//don't have this circuit code in our list
|
||||||
|
user.Authorised = false;
|
||||||
|
return (user);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((sessionID == validcircuit.SessionID) && (agentID == validcircuit.AgentID))
|
||||||
|
{
|
||||||
|
user.Authorised = true;
|
||||||
|
user.LoginInfo = new Login();
|
||||||
|
user.LoginInfo.Agent = agentID;
|
||||||
|
user.LoginInfo.Session = sessionID;
|
||||||
|
user.LoginInfo.SecureSession = validcircuit.SecureSessionID;
|
||||||
|
user.LoginInfo.First = validcircuit.firstname;
|
||||||
|
user.LoginInfo.Last = validcircuit.lastname;
|
||||||
|
user.LoginInfo.InventoryFolder = validcircuit.InventoryFolder;
|
||||||
|
user.LoginInfo.BaseFolder = validcircuit.BaseFolder;
|
||||||
|
user.LoginInfo.ClientVersion = validcircuit.ClientVersion;//rex
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Invalid
|
||||||
|
user.Authorised = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (user);
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void AddNewCircuit(uint circuitCode, AgentCircuitData agentData)
|
||||||
|
{
|
||||||
|
if (AgentCircuits.ContainsKey(circuitCode))
|
||||||
|
{
|
||||||
|
AgentCircuits[circuitCode] = agentData;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
AgentCircuits.Add(circuitCode, agentData);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public LLVector3 GetPosition(uint circuitCode)
|
||||||
|
{
|
||||||
|
LLVector3 vec = new LLVector3();
|
||||||
|
if (AgentCircuits.ContainsKey(circuitCode))
|
||||||
|
{
|
||||||
|
vec = AgentCircuits[circuitCode].startpos;
|
||||||
|
}
|
||||||
|
return vec;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void UpdateAgentData(AgentCircuitData agentData)
|
||||||
|
{
|
||||||
|
if (AgentCircuits.ContainsKey((uint) agentData.circuitcode))
|
||||||
|
{
|
||||||
|
AgentCircuits[(uint) agentData.circuitcode].firstname = agentData.firstname;
|
||||||
|
AgentCircuits[(uint) agentData.circuitcode].lastname = agentData.lastname;
|
||||||
|
AgentCircuits[(uint) agentData.circuitcode].startpos = agentData.startpos;
|
||||||
|
// Console.WriteLine("update user start pos is " + agentData.startpos.X + " , " + agentData.startpos.Y + " , " + agentData.startpos.Z);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void UpdateAgentChildStatus(uint circuitcode, bool childstatus)
|
||||||
|
{
|
||||||
|
if (AgentCircuits.ContainsKey(circuitcode))
|
||||||
|
{
|
||||||
|
AgentCircuits[circuitcode].child = childstatus;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool GetAgentChildStatus(uint circuitcode)
|
||||||
|
{
|
||||||
|
if (AgentCircuits.ContainsKey(circuitcode))
|
||||||
|
{
|
||||||
|
return AgentCircuits[circuitcode].child;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,258 @@
|
||||||
|
/*
|
||||||
|
* 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 OpenSim 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 libsecondlife;
|
||||||
|
using libsecondlife.Packets;
|
||||||
|
|
||||||
|
namespace OpenSim.Framework
|
||||||
|
{
|
||||||
|
public class AgentInventory
|
||||||
|
{
|
||||||
|
//Holds the local copy of Inventory info for a agent
|
||||||
|
public Dictionary<LLUUID, InventoryFolder> InventoryFolders;
|
||||||
|
public Dictionary<LLUUID, InventoryItem> InventoryItems;
|
||||||
|
public InventoryFolder InventoryRoot;
|
||||||
|
public int LastCached; //maybe used by opensim app, time this was last stored/compared to user server
|
||||||
|
public LLUUID AgentID;
|
||||||
|
public AvatarWearable[] Wearables;
|
||||||
|
|
||||||
|
public AgentInventory()
|
||||||
|
{
|
||||||
|
InventoryFolders = new Dictionary<LLUUID, InventoryFolder>();
|
||||||
|
InventoryItems = new Dictionary<LLUUID, InventoryItem>();
|
||||||
|
Initialise();
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void Initialise()
|
||||||
|
{
|
||||||
|
Wearables = new AvatarWearable[13];
|
||||||
|
for (int i = 0; i < 13; i++)
|
||||||
|
{
|
||||||
|
Wearables[i] = new AvatarWearable();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool CreateNewFolder(LLUUID folderID, ushort type)
|
||||||
|
{
|
||||||
|
InventoryFolder Folder = new InventoryFolder();
|
||||||
|
Folder.FolderID = folderID;
|
||||||
|
Folder.OwnerID = AgentID;
|
||||||
|
Folder.DefaultType = type;
|
||||||
|
InventoryFolders.Add(Folder.FolderID, Folder);
|
||||||
|
return (true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void CreateRootFolder(LLUUID newAgentID, bool createTextures)
|
||||||
|
{
|
||||||
|
AgentID = newAgentID;
|
||||||
|
InventoryRoot = new InventoryFolder();
|
||||||
|
InventoryRoot.FolderID = LLUUID.Random();
|
||||||
|
InventoryRoot.ParentID = LLUUID.Zero;
|
||||||
|
InventoryRoot.Version = 1;
|
||||||
|
InventoryRoot.DefaultType = 8;
|
||||||
|
InventoryRoot.OwnerID = AgentID;
|
||||||
|
InventoryRoot.FolderName = "My Inventory";
|
||||||
|
InventoryFolders.Add(InventoryRoot.FolderID, InventoryRoot);
|
||||||
|
InventoryRoot.OwnerID = AgentID;
|
||||||
|
if (createTextures)
|
||||||
|
{
|
||||||
|
CreateNewFolder(LLUUID.Random(), 0, "Textures", InventoryRoot.FolderID);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool CreateNewFolder(LLUUID folderID, ushort type, string folderName)
|
||||||
|
{
|
||||||
|
InventoryFolder Folder = new InventoryFolder();
|
||||||
|
Folder.FolderID = folderID;
|
||||||
|
Folder.OwnerID = AgentID;
|
||||||
|
Folder.DefaultType = type;
|
||||||
|
Folder.FolderName = folderName;
|
||||||
|
InventoryFolders.Add(Folder.FolderID, Folder);
|
||||||
|
return (true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool CreateNewFolder(LLUUID folderID, ushort type, string folderName, LLUUID parentID)
|
||||||
|
{
|
||||||
|
if (!InventoryFolders.ContainsKey(folderID))
|
||||||
|
{
|
||||||
|
System.Console.WriteLine("creating new folder called " + folderName + " in agents inventory");
|
||||||
|
InventoryFolder Folder = new InventoryFolder();
|
||||||
|
Folder.FolderID = folderID;
|
||||||
|
Folder.OwnerID = AgentID;
|
||||||
|
Folder.DefaultType = type;
|
||||||
|
Folder.FolderName = folderName;
|
||||||
|
Folder.ParentID = parentID;
|
||||||
|
InventoryFolders.Add(Folder.FolderID, Folder);
|
||||||
|
}
|
||||||
|
return (true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool HasFolder(LLUUID folderID)
|
||||||
|
{
|
||||||
|
if (InventoryFolders.ContainsKey(folderID))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public LLUUID GetFolderID(string folderName)
|
||||||
|
{
|
||||||
|
foreach (InventoryFolder inv in InventoryFolders.Values)
|
||||||
|
{
|
||||||
|
if (inv.FolderName == folderName)
|
||||||
|
{
|
||||||
|
return inv.FolderID;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return LLUUID.Zero;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool UpdateItemAsset(LLUUID itemID, AssetBase asset)
|
||||||
|
{
|
||||||
|
if (InventoryItems.ContainsKey(itemID))
|
||||||
|
{
|
||||||
|
InventoryItem Item = InventoryItems[itemID];
|
||||||
|
Item.AssetID = asset.FullID;
|
||||||
|
System.Console.WriteLine("updated inventory item " + itemID.ToString() +
|
||||||
|
" so it now is set to asset " + asset.FullID.ToString());
|
||||||
|
//TODO need to update the rest of the info
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool UpdateItemDetails(LLUUID itemID, UpdateInventoryItemPacket.InventoryDataBlock packet)
|
||||||
|
{
|
||||||
|
System.Console.WriteLine("updating inventory item details");
|
||||||
|
if (InventoryItems.ContainsKey(itemID))
|
||||||
|
{
|
||||||
|
System.Console.WriteLine("changing name to " + Util.FieldToString(packet.Name));
|
||||||
|
InventoryItem Item = InventoryItems[itemID];
|
||||||
|
Item.Name = Util.FieldToString(packet.Name);
|
||||||
|
System.Console.WriteLine("updated inventory item " + itemID.ToString());
|
||||||
|
//TODO need to update the rest of the info
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public LLUUID AddToInventory(LLUUID folderID, AssetBase asset)
|
||||||
|
{
|
||||||
|
if (InventoryFolders.ContainsKey(folderID))
|
||||||
|
{
|
||||||
|
LLUUID NewItemID = LLUUID.Random();
|
||||||
|
|
||||||
|
InventoryItem Item = new InventoryItem();
|
||||||
|
Item.FolderID = folderID;
|
||||||
|
Item.OwnerID = AgentID;
|
||||||
|
Item.AssetID = asset.FullID;
|
||||||
|
Item.ItemID = NewItemID;
|
||||||
|
Item.Type = asset.Type;
|
||||||
|
Item.Name = asset.Name;
|
||||||
|
Item.Description = asset.Description;
|
||||||
|
Item.InvType = asset.InvType;
|
||||||
|
InventoryItems.Add(Item.ItemID, Item);
|
||||||
|
InventoryFolder Folder = InventoryFolders[Item.FolderID];
|
||||||
|
Folder.Items.Add(Item);
|
||||||
|
return (Item.ItemID);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return (null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool DeleteFromInventory(LLUUID itemID)
|
||||||
|
{
|
||||||
|
bool res = false;
|
||||||
|
if (InventoryItems.ContainsKey(itemID))
|
||||||
|
{
|
||||||
|
InventoryItem item = InventoryItems[itemID];
|
||||||
|
InventoryItems.Remove(itemID);
|
||||||
|
foreach (InventoryFolder fold in InventoryFolders.Values)
|
||||||
|
{
|
||||||
|
if (fold.Items.Contains(item))
|
||||||
|
{
|
||||||
|
fold.Items.Remove(item);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
res = true;
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class InventoryFolder
|
||||||
|
{
|
||||||
|
public List<InventoryItem> Items;
|
||||||
|
//public List<InventoryFolder> Subfolders;
|
||||||
|
public LLUUID FolderID;
|
||||||
|
public LLUUID OwnerID;
|
||||||
|
public LLUUID ParentID = LLUUID.Zero;
|
||||||
|
public string FolderName;
|
||||||
|
public ushort DefaultType;
|
||||||
|
public ushort Version;
|
||||||
|
|
||||||
|
public InventoryFolder()
|
||||||
|
{
|
||||||
|
Items = new List<InventoryItem>();
|
||||||
|
//Subfolders = new List<InventoryFolder>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class InventoryItem
|
||||||
|
{
|
||||||
|
public LLUUID FolderID;
|
||||||
|
public LLUUID OwnerID;
|
||||||
|
public LLUUID ItemID;
|
||||||
|
public LLUUID AssetID;
|
||||||
|
public LLUUID CreatorID;
|
||||||
|
public sbyte InvType;
|
||||||
|
public sbyte Type;
|
||||||
|
public string Name = "";
|
||||||
|
public string Description;
|
||||||
|
|
||||||
|
public InventoryItem()
|
||||||
|
{
|
||||||
|
CreatorID = LLUUID.Zero;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string ExportString()
|
||||||
|
{
|
||||||
|
string typ = "notecard";
|
||||||
|
string result = "";
|
||||||
|
result += "\tinv_object\t0\n\t{\n";
|
||||||
|
result += "\t\tobj_id\t%s\n";
|
||||||
|
result += "\t\tparent_id\t" + ItemID.ToString() + "\n";
|
||||||
|
result += "\t\ttype\t" + typ + "\n";
|
||||||
|
result += "\t\tname\t" + Name + "|\n";
|
||||||
|
result += "\t}\n";
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,36 @@
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
// General Information about an assembly is controlled through the following
|
||||||
|
// set of attributes. Change these attribute values to modify the information
|
||||||
|
// associated with an assembly.
|
||||||
|
|
||||||
|
[assembly : AssemblyTitle("OpenSim.FrameWork")]
|
||||||
|
[assembly : AssemblyDescription("")]
|
||||||
|
[assembly : AssemblyConfiguration("")]
|
||||||
|
[assembly : AssemblyCompany("")]
|
||||||
|
[assembly : AssemblyProduct("OpenSim.FrameWork")]
|
||||||
|
[assembly : AssemblyCopyright("Copyright © 2007")]
|
||||||
|
[assembly : AssemblyTrademark("")]
|
||||||
|
[assembly : AssemblyCulture("")]
|
||||||
|
|
||||||
|
// Setting ComVisible to false makes the types in this assembly not visible
|
||||||
|
// to COM components. If you need to access a type in this assembly from
|
||||||
|
// COM, set the ComVisible attribute to true on that type.
|
||||||
|
|
||||||
|
[assembly : ComVisible(false)]
|
||||||
|
|
||||||
|
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||||
|
|
||||||
|
[assembly : Guid("a08e20c7-f191-4137-b1f0-9291408fa521")]
|
||||||
|
|
||||||
|
// Version information for an assembly consists of the following four values:
|
||||||
|
//
|
||||||
|
// Major Version
|
||||||
|
// Minor Version
|
||||||
|
// Build Number
|
||||||
|
// Revision
|
||||||
|
//
|
||||||
|
|
||||||
|
[assembly : AssemblyVersion("1.0.0.0")]
|
||||||
|
[assembly : AssemblyFileVersion("1.0.0.0")]
|
|
@ -0,0 +1,56 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) Contributors, http://opensimulator.org/
|
||||||
|
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of the OpenSim 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 libsecondlife;
|
||||||
|
|
||||||
|
namespace OpenSim.Framework
|
||||||
|
{
|
||||||
|
[Serializable]
|
||||||
|
public class AssetBase
|
||||||
|
{
|
||||||
|
public byte[] Data;
|
||||||
|
public LLUUID FullID;
|
||||||
|
public sbyte Type;
|
||||||
|
public sbyte InvType;
|
||||||
|
public string Name = "";
|
||||||
|
public string Description = "";
|
||||||
|
public string MediaURL = "";//rex
|
||||||
|
public bool Local = false;
|
||||||
|
public bool Temporary = false;
|
||||||
|
|
||||||
|
public AssetBase()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public AssetBase(LLUUID assetId, string name)
|
||||||
|
{
|
||||||
|
FullID = assetId;
|
||||||
|
Name = name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,83 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) Contributors, http://opensimulator.org/
|
||||||
|
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of the OpenSim 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
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// UserConfig -- For User Server Configuration
|
||||||
|
/// </summary>
|
||||||
|
public class AssetConfig
|
||||||
|
{
|
||||||
|
public string DefaultStartupMsg = "";
|
||||||
|
|
||||||
|
public string DatabaseProvider = "";
|
||||||
|
|
||||||
|
public static uint DefaultHttpPort = 8003;
|
||||||
|
public uint HttpPort = DefaultHttpPort;
|
||||||
|
|
||||||
|
private ConfigurationMember configMember;
|
||||||
|
|
||||||
|
public AssetConfig(string description, string filename)
|
||||||
|
{
|
||||||
|
configMember =
|
||||||
|
new ConfigurationMember(filename, description, loadConfigurationOptions, handleIncomingConfiguration, true);
|
||||||
|
configMember.performConfigurationRetrieve();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void loadConfigurationOptions()
|
||||||
|
{
|
||||||
|
configMember.addConfigurationOption("default_startup_message",
|
||||||
|
ConfigurationOption.ConfigurationTypes.TYPE_STRING_NOT_EMPTY,
|
||||||
|
"Default Startup Message", "Welcome to OGS", false);
|
||||||
|
|
||||||
|
configMember.addConfigurationOption("database_provider", ConfigurationOption.ConfigurationTypes.TYPE_STRING,
|
||||||
|
"DLL for database provider", "OpenSim.Framework.Data.MySQL.dll", false);
|
||||||
|
|
||||||
|
configMember.addConfigurationOption("http_port", ConfigurationOption.ConfigurationTypes.TYPE_UINT32,
|
||||||
|
"Http Listener port", DefaultHttpPort.ToString(), false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool handleIncomingConfiguration(string configuration_key, object configuration_result)
|
||||||
|
{
|
||||||
|
switch (configuration_key)
|
||||||
|
{
|
||||||
|
case "default_startup_message":
|
||||||
|
DefaultStartupMsg = (string) configuration_result;
|
||||||
|
break;
|
||||||
|
case "database_provider":
|
||||||
|
DatabaseProvider = (string) configuration_result;
|
||||||
|
break;
|
||||||
|
case "http_port":
|
||||||
|
HttpPort = (uint) configuration_result;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,60 @@
|
||||||
|
/*
|
||||||
|
* 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 OpenSim 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.Text;
|
||||||
|
using libsecondlife;
|
||||||
|
|
||||||
|
namespace OpenSim.Framework
|
||||||
|
{
|
||||||
|
public class AssetLandmark : AssetBase
|
||||||
|
{
|
||||||
|
public int Version;
|
||||||
|
public LLVector3 Position;
|
||||||
|
public LLUUID RegionID;
|
||||||
|
|
||||||
|
public AssetLandmark(AssetBase a)
|
||||||
|
{
|
||||||
|
Data = a.Data;
|
||||||
|
FullID = a.FullID;
|
||||||
|
Type = a.Type;
|
||||||
|
InvType = a.InvType;
|
||||||
|
Name = a.Name;
|
||||||
|
Description = a.Description;
|
||||||
|
MediaURL = a.MediaURL; //rex
|
||||||
|
InternData();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void InternData()
|
||||||
|
{
|
||||||
|
string temp = Encoding.UTF8.GetString(Data).Trim();
|
||||||
|
string[] parts = temp.Split('\n');
|
||||||
|
int.TryParse(parts[0].Substring(17, 1), out Version);
|
||||||
|
LLUUID.TryParse(parts[1].Substring(10, 36), out RegionID);
|
||||||
|
LLVector3.TryParse(parts[2].Substring(11, parts[2].Length - 11), out Position);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,164 @@
|
||||||
|
/*
|
||||||
|
* 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 OpenSim Project nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
||||||
|
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Xml;
|
||||||
|
|
||||||
|
using libsecondlife;
|
||||||
|
using Nini.Config;
|
||||||
|
|
||||||
|
using OpenSim.Framework;
|
||||||
|
using OpenSim.Framework.Console;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Loads assets from the filesystem location. Not yet a plugin, though it should be.
|
||||||
|
/// </summary>
|
||||||
|
namespace OpenSim.Framework.AssetLoader.Filesystem
|
||||||
|
{
|
||||||
|
public class AssetLoaderFileSystem : IAssetLoader
|
||||||
|
{
|
||||||
|
protected AssetBase CreateAsset(string assetIdStr, string name, string path, bool isImage)
|
||||||
|
{
|
||||||
|
AssetBase asset = new AssetBase(
|
||||||
|
new LLUUID(assetIdStr),
|
||||||
|
name
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!String.IsNullOrEmpty(path))
|
||||||
|
{
|
||||||
|
MainLog.Instance.Verbose("ASSETS", "Loading: [{0}][{1}]", name, path);
|
||||||
|
|
||||||
|
LoadAsset(asset, isImage, path);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
MainLog.Instance.Verbose("ASSETS", "Instantiated: [{0}]", name);
|
||||||
|
}
|
||||||
|
|
||||||
|
return asset;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void LoadAsset(AssetBase info, bool image, string path)
|
||||||
|
{
|
||||||
|
FileInfo fInfo = new FileInfo(path);
|
||||||
|
long numBytes = fInfo.Length;
|
||||||
|
FileStream fStream = new FileStream(path, FileMode.Open, FileAccess.Read);
|
||||||
|
byte[] idata = new byte[numBytes];
|
||||||
|
BinaryReader br = new BinaryReader(fStream);
|
||||||
|
idata = br.ReadBytes((int) numBytes);
|
||||||
|
br.Close();
|
||||||
|
fStream.Close();
|
||||||
|
info.Data = idata;
|
||||||
|
//info.loaded=true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ForEachDefaultXmlAsset(Action<AssetBase> action)
|
||||||
|
{
|
||||||
|
string assetSetFilename = Path.Combine(Util.assetsDir(), "AssetSets.xml");
|
||||||
|
|
||||||
|
ForEachDefaultXmlAsset(assetSetFilename, action);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ForEachDefaultXmlAsset(string assetSetFilename, Action<AssetBase> action)
|
||||||
|
{
|
||||||
|
List<AssetBase> assets = new List<AssetBase>();
|
||||||
|
if (File.Exists(assetSetFilename))
|
||||||
|
{
|
||||||
|
string assetSetPath = "ERROR";
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
XmlConfigSource source = new XmlConfigSource(assetSetFilename);
|
||||||
|
|
||||||
|
for (int i = 0; i < source.Configs.Count; i++)
|
||||||
|
{
|
||||||
|
assetSetPath = source.Configs[i].GetString("file", "");
|
||||||
|
|
||||||
|
LoadXmlAssetSet(Path.Combine(Util.assetsDir(), assetSetPath), assets);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (XmlException e)
|
||||||
|
{
|
||||||
|
MainLog.Instance.Error("ASSETS", "Error loading {0} : {1}", assetSetPath, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
MainLog.Instance.Error(
|
||||||
|
"ASSETS",
|
||||||
|
"Asset set control file assets/AssetSets.xml does not exist! No assets loaded.");
|
||||||
|
}
|
||||||
|
|
||||||
|
assets.ForEach(action);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Use the asset set information at path to load assets
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="path"></param>
|
||||||
|
/// <param name="assets"></param>
|
||||||
|
protected void LoadXmlAssetSet(string assetSetPath, List<AssetBase> assets)
|
||||||
|
{
|
||||||
|
MainLog.Instance.Verbose("ASSETS", "Loading asset set {0}", assetSetPath);
|
||||||
|
|
||||||
|
if (File.Exists(assetSetPath))
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
XmlConfigSource source = new XmlConfigSource(assetSetPath);
|
||||||
|
String dir = Path.GetDirectoryName(assetSetPath);
|
||||||
|
|
||||||
|
for (int i = 0; i < source.Configs.Count; i++)
|
||||||
|
{
|
||||||
|
string assetIdStr = source.Configs[i].GetString("assetID", LLUUID.Random().ToString());
|
||||||
|
string name = source.Configs[i].GetString("name", "");
|
||||||
|
sbyte type = (sbyte) source.Configs[i].GetInt("assetType", 0);
|
||||||
|
sbyte invType = (sbyte) source.Configs[i].GetInt("inventoryType", 0);
|
||||||
|
string assetPath = Path.Combine(dir, source.Configs[i].GetString("fileName", ""));
|
||||||
|
|
||||||
|
AssetBase newAsset = CreateAsset(assetIdStr, name, assetPath, false);
|
||||||
|
|
||||||
|
newAsset.Type = type;
|
||||||
|
newAsset.InvType = invType;
|
||||||
|
assets.Add(newAsset);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (XmlException e)
|
||||||
|
{
|
||||||
|
MainLog.Instance.Error("ASSETS", "Error loading {0} : {1}", assetSetPath, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
MainLog.Instance.Error("ASSETS", "Asset set file {0} does not exist!", assetSetPath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
using libsecondlife;
|
||||||
|
|
||||||
|
namespace OpenSim.Framework
|
||||||
|
{
|
||||||
|
public struct AssetRequest
|
||||||
|
{
|
||||||
|
public LLUUID AssetID;
|
||||||
|
public bool IsTexture;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,48 @@
|
||||||
|
/*
|
||||||
|
* 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 OpenSim 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 libsecondlife;
|
||||||
|
|
||||||
|
namespace OpenSim.Framework
|
||||||
|
{
|
||||||
|
public class AssetStorage
|
||||||
|
{
|
||||||
|
public AssetStorage()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public AssetStorage(LLUUID assetUUID)
|
||||||
|
{
|
||||||
|
UUID = assetUUID;
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] Data;
|
||||||
|
public sbyte Type;
|
||||||
|
public string Name;
|
||||||
|
public LLUUID UUID;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,39 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) Contributors, http://opensimulator.org/
|
||||||
|
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of the OpenSim 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
|
||||||
|
{
|
||||||
|
public class AuthenticateResponse
|
||||||
|
{
|
||||||
|
public bool Authorised;
|
||||||
|
public Login LoginInfo;
|
||||||
|
|
||||||
|
public AuthenticateResponse()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,71 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) Contributors, http://opensimulator.org/
|
||||||
|
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of the OpenSim 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 libsecondlife;
|
||||||
|
|
||||||
|
namespace OpenSim.Framework
|
||||||
|
{
|
||||||
|
public class AvatarWearable
|
||||||
|
{
|
||||||
|
public LLUUID AssetID = new LLUUID("00000000-0000-0000-0000-000000000000");
|
||||||
|
public LLUUID ItemID = new LLUUID("00000000-0000-0000-0000-000000000000");
|
||||||
|
|
||||||
|
public AvatarWearable()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public AvatarWearable(LLUUID itemId, LLUUID assetId)
|
||||||
|
{
|
||||||
|
AssetID = assetId;
|
||||||
|
ItemID = itemId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static AvatarWearable[] DefaultWearables
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
AvatarWearable[] defaultWearables = new AvatarWearable[13]; //should be 13 of these
|
||||||
|
for (int i = 0; i < 13; i++)
|
||||||
|
{
|
||||||
|
defaultWearables[i] = new AvatarWearable();
|
||||||
|
}
|
||||||
|
defaultWearables[0].AssetID = new LLUUID("66c41e39-38f9-f75a-024e-585989bfab73");
|
||||||
|
defaultWearables[0].ItemID = new LLUUID("66c41e39-38f9-f75a-024e-585989bfaba9");
|
||||||
|
|
||||||
|
defaultWearables[1].ItemID = new LLUUID("77c41e39-38f9-f75a-024e-585989bfabc9");
|
||||||
|
defaultWearables[1].AssetID = new LLUUID("77c41e39-38f9-f75a-024e-585989bbabbb");
|
||||||
|
|
||||||
|
defaultWearables[4].ItemID = new LLUUID("77c41e39-38f9-f75a-0000-585989bf0000");
|
||||||
|
defaultWearables[4].AssetID = new LLUUID("00000000-38f9-1111-024e-222222111110");
|
||||||
|
|
||||||
|
defaultWearables[5].ItemID = new LLUUID("77c41e39-38f9-f75a-0000-5859892f1111");
|
||||||
|
defaultWearables[5].AssetID = new LLUUID("00000000-38f9-1111-024e-222222111120");
|
||||||
|
return defaultWearables;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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 OpenSim 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 System.Threading;
|
||||||
|
|
||||||
|
namespace OpenSim.Framework
|
||||||
|
{
|
||||||
|
public class BlockingQueue<T>
|
||||||
|
{
|
||||||
|
private readonly Queue<T> m_queue = new Queue<T>();
|
||||||
|
private readonly object m_queueSync = new object();
|
||||||
|
|
||||||
|
public void Enqueue(T value)
|
||||||
|
{
|
||||||
|
lock (m_queueSync)
|
||||||
|
{
|
||||||
|
m_queue.Enqueue(value);
|
||||||
|
Monitor.Pulse(m_queueSync);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public T Dequeue()
|
||||||
|
{
|
||||||
|
lock (m_queueSync)
|
||||||
|
{
|
||||||
|
if (m_queue.Count < 1)
|
||||||
|
{
|
||||||
|
Monitor.Wait(m_queueSync);
|
||||||
|
}
|
||||||
|
|
||||||
|
return m_queue.Dequeue();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Contains(T item)
|
||||||
|
{
|
||||||
|
lock (m_queueSync)
|
||||||
|
{
|
||||||
|
return m_queue.Contains(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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 OpenSim Project nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
||||||
|
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace OpenSim.Framework
|
||||||
|
{
|
||||||
|
[Serializable]
|
||||||
|
public class ChildAgentDataUpdate
|
||||||
|
{
|
||||||
|
public ChildAgentDataUpdate()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public sLLVector3 Position;
|
||||||
|
public ulong regionHandle;
|
||||||
|
public float drawdistance;
|
||||||
|
public sLLVector3 cameraPosition;
|
||||||
|
public sLLVector3 Velocity;
|
||||||
|
public float AVHeight;
|
||||||
|
public Guid AgentID;
|
||||||
|
public float godlevel;
|
||||||
|
public byte[] throttles;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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 OpenSim 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 libsecondlife;
|
||||||
|
using libsecondlife.Packets;
|
||||||
|
|
||||||
|
namespace OpenSim.Framework
|
||||||
|
{
|
||||||
|
public delegate void ForEachClientDelegate(IClientAPI client);
|
||||||
|
|
||||||
|
public class ClientManager
|
||||||
|
{
|
||||||
|
private Dictionary<uint, IClientAPI> m_clients;
|
||||||
|
|
||||||
|
public void ForEachClient(ForEachClientDelegate whatToDo)
|
||||||
|
{
|
||||||
|
|
||||||
|
// Wasteful, I know
|
||||||
|
IClientAPI[] LocalClients = new IClientAPI[0];
|
||||||
|
lock (m_clients)
|
||||||
|
{
|
||||||
|
LocalClients = new IClientAPI[m_clients.Count];
|
||||||
|
m_clients.Values.CopyTo(LocalClients, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < LocalClients.Length; i++)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
whatToDo(LocalClients[i]);
|
||||||
|
}
|
||||||
|
catch (System.Exception e)
|
||||||
|
{
|
||||||
|
OpenSim.Framework.Console.MainLog.Instance.Warn("CLIENT", "Unable to do ForEachClient for one of the clients" + "\n Reason: " + e.ToString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public ClientManager()
|
||||||
|
{
|
||||||
|
m_clients = new Dictionary<uint, IClientAPI>();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Remove(uint id)
|
||||||
|
{
|
||||||
|
m_clients.Remove(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Add(uint id, IClientAPI client)
|
||||||
|
{
|
||||||
|
m_clients.Add(id, client);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void InPacket(uint circuitCode, Packet packet)
|
||||||
|
{
|
||||||
|
IClientAPI client;
|
||||||
|
|
||||||
|
if (m_clients.TryGetValue(circuitCode, out client))
|
||||||
|
{
|
||||||
|
client.InPacket(packet);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void CloseAllAgents(uint circuitCode)
|
||||||
|
{
|
||||||
|
IClientAPI client;
|
||||||
|
|
||||||
|
if (m_clients.TryGetValue(circuitCode, out client))
|
||||||
|
{
|
||||||
|
CloseAllCircuits(client.AgentId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void CloseAllCircuits(LLUUID agentId)
|
||||||
|
{
|
||||||
|
uint[] circuits = GetAllCircuits(agentId);
|
||||||
|
// We're using a for loop here so changes to the circuits don't cause it to completely fail.
|
||||||
|
|
||||||
|
for (int i = 0; i < circuits.Length; i++)
|
||||||
|
{
|
||||||
|
IClientAPI client;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
|
||||||
|
if (m_clients.TryGetValue(circuits[i], out client))
|
||||||
|
{
|
||||||
|
Remove(client.CircuitCode);
|
||||||
|
client.Close(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (System.Exception e)
|
||||||
|
{
|
||||||
|
OpenSim.Framework.Console.MainLog.Instance.Error("CLIENT", string.Format("Unable to shutdown circuit for: {0}\n Reason: {1}", agentId, e));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private uint[] GetAllCircuits(LLUUID agentId)
|
||||||
|
{
|
||||||
|
List<uint> circuits = new List<uint>();
|
||||||
|
// Wasteful, I know
|
||||||
|
IClientAPI[] LocalClients = new IClientAPI[0];
|
||||||
|
lock (m_clients)
|
||||||
|
{
|
||||||
|
LocalClients = new IClientAPI[m_clients.Count];
|
||||||
|
m_clients.Values.CopyTo(LocalClients, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
for (int i = 0; i < LocalClients.Length; i++ )
|
||||||
|
{
|
||||||
|
if (LocalClients[i].AgentId == agentId)
|
||||||
|
{
|
||||||
|
circuits.Add(LocalClients[i].CircuitCode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return circuits.ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void ViewerEffectHandler(IClientAPI sender, ViewerEffectPacket.EffectBlock[] effectBlock)
|
||||||
|
{
|
||||||
|
ViewerEffectPacket packet = (ViewerEffectPacket) PacketPool.Instance.GetPacket(PacketType.ViewerEffect);
|
||||||
|
// TODO: don't create new blocks if recycling an old packet
|
||||||
|
packet.Effect = effectBlock;
|
||||||
|
|
||||||
|
// Wasteful, I know
|
||||||
|
IClientAPI[] LocalClients = new IClientAPI[0];
|
||||||
|
lock (m_clients)
|
||||||
|
{
|
||||||
|
LocalClients = new IClientAPI[m_clients.Count];
|
||||||
|
m_clients.Values.CopyTo(LocalClients, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
for (int i = 0; i < LocalClients.Length; i++)
|
||||||
|
{
|
||||||
|
if (LocalClients[i].AgentId != sender.AgentId)
|
||||||
|
{
|
||||||
|
packet.AgentData.AgentID = LocalClients[i].AgentId;
|
||||||
|
packet.AgentData.SessionID = LocalClients[i].SessionId;
|
||||||
|
LocalClients[i].OutPacket(packet, ThrottleOutPacketType.Task);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool TryGetClient(uint circuitId, out IClientAPI user)
|
||||||
|
{
|
||||||
|
return m_clients.TryGetValue(circuitId, out user);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,54 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) Contributors, http://opensimulator.org/
|
||||||
|
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of the OpenSim 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 OpenSim.Framework.Servers;
|
||||||
|
|
||||||
|
namespace OpenSim.Framework.Communications
|
||||||
|
{
|
||||||
|
public class CAPSService
|
||||||
|
{
|
||||||
|
private BaseHttpServer m_server;
|
||||||
|
|
||||||
|
public CAPSService(BaseHttpServer httpServer)
|
||||||
|
{
|
||||||
|
m_server = httpServer;
|
||||||
|
AddCapsSeedHandler("/CapsSeed/", CapsRequest);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void AddCapsSeedHandler(string path, RestMethod restMethod)
|
||||||
|
{
|
||||||
|
m_server.AddStreamHandler(new RestStreamHandler("POST", path, restMethod));
|
||||||
|
}
|
||||||
|
|
||||||
|
public string CapsRequest(string request, string path, string param)
|
||||||
|
{
|
||||||
|
System.Console.WriteLine("new caps request " + request + " from path " + path);
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,725 @@
|
||||||
|
/*
|
||||||
|
* 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 OpenSim 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.Threading;
|
||||||
|
using libsecondlife;
|
||||||
|
using libsecondlife.Packets;
|
||||||
|
using OpenSim.Framework.Console;
|
||||||
|
|
||||||
|
namespace OpenSim.Framework.Communications.Cache
|
||||||
|
{
|
||||||
|
public delegate void AssetRequestCallback(LLUUID assetID, AssetBase asset);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Manages local cache of assets and their sending to viewers.
|
||||||
|
/// </summary>
|
||||||
|
public class AssetCache : IAssetReceiver
|
||||||
|
{
|
||||||
|
public Dictionary<LLUUID, AssetInfo> Assets;
|
||||||
|
public Dictionary<LLUUID, TextureImage> Textures;
|
||||||
|
|
||||||
|
public List<AssetRequest> AssetRequests = new List<AssetRequest>(); //assets ready to be sent to viewers
|
||||||
|
public List<AssetRequest> TextureRequests = new List<AssetRequest>(); //textures ready to be sent
|
||||||
|
|
||||||
|
public Dictionary<LLUUID, AssetRequest> RequestedAssets = new Dictionary<LLUUID, AssetRequest>();
|
||||||
|
//Assets requested from the asset server
|
||||||
|
|
||||||
|
public Dictionary<LLUUID, AssetRequest> RequestedTextures = new Dictionary<LLUUID, AssetRequest>();
|
||||||
|
//Textures requested from the asset server
|
||||||
|
|
||||||
|
public Dictionary<LLUUID, AssetRequestsList> RequestLists = new Dictionary<LLUUID, AssetRequestsList>();
|
||||||
|
|
||||||
|
private readonly IAssetServer m_assetServer;
|
||||||
|
|
||||||
|
private readonly Thread m_assetCacheThread;
|
||||||
|
private readonly LogBase m_log;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
public AssetCache(IAssetServer assetServer, LogBase log)
|
||||||
|
{
|
||||||
|
log.Verbose("ASSETSTORAGE", "Creating Asset cache");
|
||||||
|
m_assetServer = assetServer;
|
||||||
|
m_assetServer.SetReceiver(this);
|
||||||
|
Assets = new Dictionary<LLUUID, AssetInfo>();
|
||||||
|
Textures = new Dictionary<LLUUID, TextureImage>();
|
||||||
|
m_assetCacheThread = new Thread(new ThreadStart(RunAssetManager));
|
||||||
|
m_assetCacheThread.IsBackground = true;
|
||||||
|
m_assetCacheThread.Start();
|
||||||
|
|
||||||
|
m_log = log;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
public void RunAssetManager()
|
||||||
|
{
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
ProcessAssetQueue();
|
||||||
|
Thread.Sleep(500);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
m_log.Error("ASSETCACHE", e.ToString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Only get an asset if we already have it in the cache.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="assetID"></param></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
private AssetBase GetCachedAsset(LLUUID assetID)
|
||||||
|
{
|
||||||
|
AssetBase asset = null;
|
||||||
|
if (Textures.ContainsKey(assetID))
|
||||||
|
{
|
||||||
|
asset = Textures[assetID];
|
||||||
|
}
|
||||||
|
else if (Assets.ContainsKey(assetID))
|
||||||
|
{
|
||||||
|
asset = Assets[assetID];
|
||||||
|
}
|
||||||
|
return asset;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void GetAsset(LLUUID assetID, AssetRequestCallback callback)
|
||||||
|
{
|
||||||
|
AssetBase asset = null;
|
||||||
|
if (Textures.ContainsKey(assetID))
|
||||||
|
{
|
||||||
|
asset = Textures[assetID];
|
||||||
|
}
|
||||||
|
else if (Assets.ContainsKey(assetID))
|
||||||
|
{
|
||||||
|
asset = Assets[assetID];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (asset != null)
|
||||||
|
{
|
||||||
|
callback(assetID, asset);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
NewAssetRequest req = new NewAssetRequest(assetID, callback);
|
||||||
|
if (RequestLists.ContainsKey(assetID))
|
||||||
|
{
|
||||||
|
lock (RequestLists)
|
||||||
|
{
|
||||||
|
RequestLists[assetID].Requests.Add(req);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
AssetRequestsList reqList = new AssetRequestsList(assetID);
|
||||||
|
reqList.Requests.Add(req);
|
||||||
|
lock (RequestLists)
|
||||||
|
{
|
||||||
|
RequestLists.Add(assetID, reqList);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
m_assetServer.RequestAsset(assetID, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get an asset. If the asset isn't in the cache, a request will be made to the persistent store to
|
||||||
|
/// load it into the cache.
|
||||||
|
///
|
||||||
|
/// XXX We'll keep polling the cache until we get the asset or we exceed
|
||||||
|
/// the allowed number of polls. This isn't a very good way of doing things since a single thread
|
||||||
|
/// is processing inbound packets, so if the asset server is slow, we could block this for up to
|
||||||
|
/// the timeout period. What we might want to do is register asynchronous callbacks on asset
|
||||||
|
/// receipt in the same manner as the nascent (but not yet active) TextureDownloadModule. Of course,
|
||||||
|
/// a timeout before asset receipt usually isn't fatal, the operation will work on the retry when the
|
||||||
|
/// asset is much more likely to have made it into the cache.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="assetID"></param>
|
||||||
|
/// <param name="isTexture"></param>
|
||||||
|
/// <returns>null if the asset could not be retrieved</returns>
|
||||||
|
public AssetBase GetAsset(LLUUID assetID, bool isTexture)
|
||||||
|
{
|
||||||
|
// I'm not going over 3 seconds since this will be blocking processing of all the other inbound
|
||||||
|
// packets from the client.
|
||||||
|
int pollPeriod = 200;
|
||||||
|
int maxPolls = 15;
|
||||||
|
|
||||||
|
AssetBase asset = GetCachedAsset(assetID);
|
||||||
|
if (asset != null)
|
||||||
|
{
|
||||||
|
return asset;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_assetServer.RequestAsset(assetID, isTexture);
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
Thread.Sleep(pollPeriod);
|
||||||
|
|
||||||
|
asset = GetCachedAsset(assetID);
|
||||||
|
if (asset != null)
|
||||||
|
{
|
||||||
|
return asset;
|
||||||
|
}
|
||||||
|
} while (--maxPolls > 0);
|
||||||
|
|
||||||
|
MainLog.Instance.Warn(
|
||||||
|
"ASSETCACHE", "Asset {0} was not received before the retrieval timeout was reached");
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// rex, new function
|
||||||
|
public List<AssetBase> GetAssetList(int vAssetType)
|
||||||
|
{
|
||||||
|
return m_assetServer.GetAssetList(vAssetType);
|
||||||
|
}
|
||||||
|
|
||||||
|
// rex, new function
|
||||||
|
public AssetBase FetchAsset(LLUUID assetID)
|
||||||
|
{
|
||||||
|
return m_assetServer.FetchAsset(assetID);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Add an asset to both the persistent store and the cache.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="asset"></param>
|
||||||
|
public void AddAsset(AssetBase asset)
|
||||||
|
{
|
||||||
|
string temporary = asset.Temporary ? "temporary" : "";
|
||||||
|
string type = asset.Type == 0 ? "texture" : "asset";
|
||||||
|
|
||||||
|
string result = "Ignored";
|
||||||
|
|
||||||
|
if (asset.Type == 0)
|
||||||
|
{
|
||||||
|
if (Textures.ContainsKey(asset.FullID))
|
||||||
|
{
|
||||||
|
result = "Duplicate ignored.";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
TextureImage textur = new TextureImage(asset);
|
||||||
|
Textures.Add(textur.FullID, textur);
|
||||||
|
if (asset.Temporary)
|
||||||
|
{
|
||||||
|
result = "Added to cache";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_assetServer.StoreAndCommitAsset(asset);
|
||||||
|
result = "Added to server";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (Assets.ContainsKey(asset.FullID))
|
||||||
|
{
|
||||||
|
result = "Duplicate ignored.";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
AssetInfo assetInf = new AssetInfo(asset);
|
||||||
|
Assets.Add(assetInf.FullID, assetInf);
|
||||||
|
if (asset.Temporary)
|
||||||
|
{
|
||||||
|
result = "Added to cache";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_assetServer.StoreAndCommitAsset(asset);
|
||||||
|
result = "Added to server";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_log.Verbose("ASSETCACHE", "Adding {0} {1} [{2}]: {3}.", temporary, type, asset.FullID, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
// rex, new function for "replace asset" functionality
|
||||||
|
public void ReplaceAsset(AssetBase asset)
|
||||||
|
{
|
||||||
|
string temporary = asset.Temporary ? "temporary" : "";
|
||||||
|
string type = asset.Type == 0 ? "texture" : "asset";
|
||||||
|
|
||||||
|
string result = "Ignored";
|
||||||
|
|
||||||
|
if (asset.Type == 0)
|
||||||
|
{
|
||||||
|
if (Textures.ContainsKey(asset.FullID))
|
||||||
|
{
|
||||||
|
Textures.Remove(asset.FullID);
|
||||||
|
}
|
||||||
|
|
||||||
|
TextureImage textur = new TextureImage(asset);
|
||||||
|
Textures.Add(textur.FullID, textur);
|
||||||
|
|
||||||
|
if (asset.Temporary)
|
||||||
|
{
|
||||||
|
result = "Replaced old asset in cache";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_assetServer.UpdateAsset(asset);
|
||||||
|
result = "Replaced old asset on server";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (Assets.ContainsKey(asset.FullID))
|
||||||
|
{
|
||||||
|
Assets.Remove(asset.FullID);
|
||||||
|
}
|
||||||
|
|
||||||
|
AssetInfo assetInf = new AssetInfo(asset);
|
||||||
|
Assets.Add(assetInf.FullID, assetInf);
|
||||||
|
|
||||||
|
if (asset.Temporary)
|
||||||
|
{
|
||||||
|
result = "Replaced old asset in cache";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_assetServer.UpdateAsset(asset);
|
||||||
|
result = "Replaced old asset on server";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_log.Verbose("ASSETCACHE", "Adding {0} {1} [{2}]: {3}.", temporary, type, asset.FullID, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
// rex new function
|
||||||
|
public bool ExistsAsset(LLUUID assetID)
|
||||||
|
{
|
||||||
|
if (Textures.ContainsKey(assetID))
|
||||||
|
return true;
|
||||||
|
if (Assets.ContainsKey(assetID))
|
||||||
|
return true;
|
||||||
|
return m_assetServer.ExistsAsset(assetID);
|
||||||
|
}
|
||||||
|
|
||||||
|
// rex new function for "replace asset" functionality
|
||||||
|
public LLUUID ExistsAsset(sbyte type, string name)
|
||||||
|
{
|
||||||
|
// First check locally cached assets
|
||||||
|
// Texture or other asset?
|
||||||
|
if (type == 0)
|
||||||
|
{
|
||||||
|
foreach (KeyValuePair<LLUUID, TextureImage> kvp in Textures)
|
||||||
|
{
|
||||||
|
TextureImage t = kvp.Value;
|
||||||
|
if (t != null)
|
||||||
|
{
|
||||||
|
if ((t.Name == name) && (t.Type == type))
|
||||||
|
{
|
||||||
|
return t.FullID;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
foreach (KeyValuePair<LLUUID, AssetInfo> kvp in Assets)
|
||||||
|
{
|
||||||
|
AssetInfo a = kvp.Value;
|
||||||
|
if (a != null)
|
||||||
|
{
|
||||||
|
if ((a.Name == name) && (a.Type == type))
|
||||||
|
{
|
||||||
|
return a.FullID;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Then have to check asset server
|
||||||
|
return m_assetServer.ExistsAsset(type, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void DeleteAsset(LLUUID assetID)
|
||||||
|
{
|
||||||
|
// this.m_assetServer.DeleteAsset(assetID);
|
||||||
|
|
||||||
|
//Todo should delete it from memory too
|
||||||
|
}
|
||||||
|
|
||||||
|
public AssetBase CopyAsset(LLUUID assetID)
|
||||||
|
{
|
||||||
|
AssetBase asset = GetCachedAsset(assetID);
|
||||||
|
if (asset == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
asset.FullID = LLUUID.Random(); // TODO: check for conflicts
|
||||||
|
AddAsset(asset);
|
||||||
|
return asset;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AssetReceived(AssetBase asset, bool IsTexture)
|
||||||
|
{
|
||||||
|
if (asset.FullID != LLUUID.Zero) // if it is set to zero then the asset wasn't found by the server
|
||||||
|
{
|
||||||
|
//check if it is a texture or not
|
||||||
|
//then add to the correct cache list
|
||||||
|
//then check for waiting requests for this asset/texture (in the Requested lists)
|
||||||
|
//and move those requests into the Requests list.
|
||||||
|
|
||||||
|
if (IsTexture)
|
||||||
|
{
|
||||||
|
//Console.WriteLine("asset received from asset server");
|
||||||
|
|
||||||
|
TextureImage image = new TextureImage(asset);
|
||||||
|
if (!Textures.ContainsKey(image.FullID))
|
||||||
|
{
|
||||||
|
Textures.Add(image.FullID, image);
|
||||||
|
if (RequestedTextures.ContainsKey(image.FullID))
|
||||||
|
{
|
||||||
|
AssetRequest req = RequestedTextures[image.FullID];
|
||||||
|
req.ImageInfo = image;
|
||||||
|
|
||||||
|
req.NumPackets = CalculateNumPackets(image.Data);
|
||||||
|
|
||||||
|
RequestedTextures.Remove(image.FullID);
|
||||||
|
TextureRequests.Add(req);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
AssetInfo assetInf = new AssetInfo(asset);
|
||||||
|
if (!Assets.ContainsKey(assetInf.FullID))
|
||||||
|
{
|
||||||
|
Assets.Add(assetInf.FullID, assetInf);
|
||||||
|
if (RequestedAssets.ContainsKey(assetInf.FullID))
|
||||||
|
{
|
||||||
|
AssetRequest req = RequestedAssets[assetInf.FullID];
|
||||||
|
req.AssetInf = assetInf;
|
||||||
|
req.NumPackets = CalculateNumPackets(assetInf.Data);
|
||||||
|
RequestedAssets.Remove(assetInf.FullID);
|
||||||
|
AssetRequests.Add(req);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (RequestLists.ContainsKey(asset.FullID))
|
||||||
|
{
|
||||||
|
AssetRequestsList reqList = RequestLists[asset.FullID];
|
||||||
|
foreach (NewAssetRequest req in reqList.Requests)
|
||||||
|
{
|
||||||
|
req.Callback(asset.FullID, asset);
|
||||||
|
}
|
||||||
|
|
||||||
|
lock (RequestLists)
|
||||||
|
{
|
||||||
|
RequestLists.Remove(asset.FullID);
|
||||||
|
reqList.Requests.Clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AssetNotFound(LLUUID assetID)
|
||||||
|
{
|
||||||
|
//if (this.RequestedTextures.ContainsKey(assetID))
|
||||||
|
//{
|
||||||
|
// MainLog.Instance.Warn("ASSET CACHE", "sending image not found for {0}", assetID);
|
||||||
|
// AssetRequest req = this.RequestedTextures[assetID];
|
||||||
|
// ImageNotInDatabasePacket notFound = new ImageNotInDatabasePacket();
|
||||||
|
// notFound.ImageID.ID = assetID;
|
||||||
|
// req.RequestUser.OutPacket(notFound);
|
||||||
|
// this.RequestedTextures.Remove(assetID);
|
||||||
|
//}
|
||||||
|
//else
|
||||||
|
//{
|
||||||
|
// MainLog.Instance.Error("ASSET CACHE", "Cound not send image not found for {0}", assetID);
|
||||||
|
//}
|
||||||
|
}
|
||||||
|
|
||||||
|
private int CalculateNumPackets(byte[] data)
|
||||||
|
{
|
||||||
|
const uint m_maxPacketSize = 600;
|
||||||
|
int numPackets = 1;
|
||||||
|
|
||||||
|
if (data.LongLength > m_maxPacketSize)
|
||||||
|
{
|
||||||
|
// over max number of bytes so split up file
|
||||||
|
long restData = data.LongLength - m_maxPacketSize;
|
||||||
|
int restPackets = (int) ((restData + m_maxPacketSize - 1)/m_maxPacketSize);
|
||||||
|
numPackets += restPackets;
|
||||||
|
}
|
||||||
|
|
||||||
|
return numPackets;
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Assets
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="userInfo"></param>
|
||||||
|
/// <param name="transferRequest"></param>
|
||||||
|
public void AddAssetRequest(IClientAPI userInfo, TransferRequestPacket transferRequest)
|
||||||
|
{
|
||||||
|
LLUUID requestID = null;
|
||||||
|
byte source = 2;
|
||||||
|
if (transferRequest.TransferInfo.SourceType == 2)
|
||||||
|
{
|
||||||
|
//direct asset request
|
||||||
|
requestID = new LLUUID(transferRequest.TransferInfo.Params, 0);
|
||||||
|
}
|
||||||
|
else if (transferRequest.TransferInfo.SourceType == 3)
|
||||||
|
{
|
||||||
|
//inventory asset request
|
||||||
|
requestID = new LLUUID(transferRequest.TransferInfo.Params, 80);
|
||||||
|
source = 3;
|
||||||
|
//Console.WriteLine("asset request " + requestID);
|
||||||
|
}
|
||||||
|
//check to see if asset is in local cache, if not we need to request it from asset server.
|
||||||
|
//Console.WriteLine("asset request " + requestID);
|
||||||
|
if (!Assets.ContainsKey(requestID))
|
||||||
|
{
|
||||||
|
//not found asset
|
||||||
|
// so request from asset server
|
||||||
|
if (!RequestedAssets.ContainsKey(requestID))
|
||||||
|
{
|
||||||
|
AssetRequest request = new AssetRequest();
|
||||||
|
request.RequestUser = userInfo;
|
||||||
|
request.RequestAssetID = requestID;
|
||||||
|
request.TransferRequestID = transferRequest.TransferInfo.TransferID;
|
||||||
|
request.AssetRequestSource = source;
|
||||||
|
request.Params = transferRequest.TransferInfo.Params;
|
||||||
|
RequestedAssets.Add(requestID, request);
|
||||||
|
m_assetServer.RequestAsset(requestID, false);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
//it is in our cache
|
||||||
|
AssetInfo asset = Assets[requestID];
|
||||||
|
|
||||||
|
// add to the AssetRequests list
|
||||||
|
AssetRequest req = new AssetRequest();
|
||||||
|
req.RequestUser = userInfo;
|
||||||
|
req.RequestAssetID = requestID;
|
||||||
|
req.TransferRequestID = transferRequest.TransferInfo.TransferID;
|
||||||
|
req.AssetRequestSource = source;
|
||||||
|
req.Params = transferRequest.TransferInfo.Params;
|
||||||
|
req.AssetInf = asset;
|
||||||
|
req.NumPackets = CalculateNumPackets(asset.Data);
|
||||||
|
AssetRequests.Add(req);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
private void ProcessAssetQueue()
|
||||||
|
{
|
||||||
|
//should move the asset downloading to a module, like has been done with texture downloading
|
||||||
|
if (AssetRequests.Count == 0)
|
||||||
|
{
|
||||||
|
//no requests waiting
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// if less than 5, do all of them
|
||||||
|
int num = Math.Min(5, AssetRequests.Count);
|
||||||
|
|
||||||
|
AssetRequest req;
|
||||||
|
for (int i = 0; i < num; i++)
|
||||||
|
{
|
||||||
|
req = (AssetRequest) AssetRequests[i];
|
||||||
|
//Console.WriteLine("sending asset " + req.RequestAssetID);
|
||||||
|
TransferInfoPacket Transfer = new TransferInfoPacket();
|
||||||
|
Transfer.TransferInfo.ChannelType = 2;
|
||||||
|
Transfer.TransferInfo.Status = 0;
|
||||||
|
Transfer.TransferInfo.TargetType = 0;
|
||||||
|
if (req.AssetRequestSource == 2)
|
||||||
|
{
|
||||||
|
Transfer.TransferInfo.Params = new byte[20];
|
||||||
|
Array.Copy(req.RequestAssetID.GetBytes(), 0, Transfer.TransferInfo.Params, 0, 16);
|
||||||
|
int assType = (int) req.AssetInf.Type;
|
||||||
|
Array.Copy(Helpers.IntToBytes(assType), 0, Transfer.TransferInfo.Params, 16, 4);
|
||||||
|
}
|
||||||
|
else if (req.AssetRequestSource == 3)
|
||||||
|
{
|
||||||
|
Transfer.TransferInfo.Params = req.Params;
|
||||||
|
// Transfer.TransferInfo.Params = new byte[100];
|
||||||
|
//Array.Copy(req.RequestUser.AgentId.GetBytes(), 0, Transfer.TransferInfo.Params, 0, 16);
|
||||||
|
//Array.Copy(req.RequestUser.SessionId.GetBytes(), 0, Transfer.TransferInfo.Params, 16, 16);
|
||||||
|
}
|
||||||
|
Transfer.TransferInfo.Size = (int) req.AssetInf.Data.Length;
|
||||||
|
Transfer.TransferInfo.TransferID = req.TransferRequestID;
|
||||||
|
req.RequestUser.OutPacket(Transfer, ThrottleOutPacketType.Asset);
|
||||||
|
|
||||||
|
if (req.NumPackets == 1)
|
||||||
|
{
|
||||||
|
TransferPacketPacket TransferPacket = new TransferPacketPacket();
|
||||||
|
TransferPacket.TransferData.Packet = 0;
|
||||||
|
TransferPacket.TransferData.ChannelType = 2;
|
||||||
|
TransferPacket.TransferData.TransferID = req.TransferRequestID;
|
||||||
|
TransferPacket.TransferData.Data = req.AssetInf.Data;
|
||||||
|
TransferPacket.TransferData.Status = 1;
|
||||||
|
req.RequestUser.OutPacket(TransferPacket, ThrottleOutPacketType.Asset);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int processedLength = 0;
|
||||||
|
// libsecondlife hardcodes 1500 as the maximum data chunk size
|
||||||
|
int maxChunkSize = 1500;
|
||||||
|
int packetNumber = 0;
|
||||||
|
|
||||||
|
while (processedLength < req.AssetInf.Data.Length)
|
||||||
|
{
|
||||||
|
TransferPacketPacket TransferPacket = new TransferPacketPacket();
|
||||||
|
TransferPacket.TransferData.Packet = packetNumber;
|
||||||
|
TransferPacket.TransferData.ChannelType = 2;
|
||||||
|
TransferPacket.TransferData.TransferID = req.TransferRequestID;
|
||||||
|
|
||||||
|
int chunkSize = Math.Min(req.AssetInf.Data.Length - processedLength, maxChunkSize);
|
||||||
|
byte[] chunk = new byte[chunkSize];
|
||||||
|
Array.Copy(req.AssetInf.Data, processedLength, chunk, 0, chunk.Length);
|
||||||
|
|
||||||
|
TransferPacket.TransferData.Data = chunk;
|
||||||
|
|
||||||
|
// 0 indicates more packets to come, 1 indicates last packet
|
||||||
|
if (req.AssetInf.Data.Length - processedLength > maxChunkSize)
|
||||||
|
{
|
||||||
|
TransferPacket.TransferData.Status = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
TransferPacket.TransferData.Status = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
req.RequestUser.OutPacket(TransferPacket, ThrottleOutPacketType.Asset);
|
||||||
|
|
||||||
|
processedLength += chunkSize;
|
||||||
|
packetNumber++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//remove requests that have been completed
|
||||||
|
for (int i = 0; i < num; i++)
|
||||||
|
{
|
||||||
|
AssetRequests.RemoveAt(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
public class AssetRequest
|
||||||
|
{
|
||||||
|
public IClientAPI RequestUser;
|
||||||
|
public LLUUID RequestAssetID;
|
||||||
|
public AssetInfo AssetInf;
|
||||||
|
public TextureImage ImageInfo;
|
||||||
|
public LLUUID TransferRequestID;
|
||||||
|
public long DataPointer = 0;
|
||||||
|
public int NumPackets = 0;
|
||||||
|
public int PacketCounter = 0;
|
||||||
|
public bool IsTextureRequest;
|
||||||
|
public byte AssetRequestSource = 2;
|
||||||
|
public byte[] Params = null;
|
||||||
|
//public bool AssetInCache;
|
||||||
|
//public int TimeRequested;
|
||||||
|
public int DiscardLevel = -1;
|
||||||
|
|
||||||
|
public AssetRequest()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class AssetInfo : AssetBase
|
||||||
|
{
|
||||||
|
public AssetInfo()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public AssetInfo(AssetBase aBase)
|
||||||
|
{
|
||||||
|
Data = aBase.Data;
|
||||||
|
FullID = aBase.FullID;
|
||||||
|
Type = aBase.Type;
|
||||||
|
InvType = aBase.InvType;
|
||||||
|
Name = aBase.Name;
|
||||||
|
Description = aBase.Description;
|
||||||
|
MediaURL = aBase.MediaURL; //rex
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class TextureImage : AssetBase
|
||||||
|
{
|
||||||
|
public TextureImage()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public TextureImage(AssetBase aBase)
|
||||||
|
{
|
||||||
|
Data = aBase.Data;
|
||||||
|
FullID = aBase.FullID;
|
||||||
|
Type = aBase.Type;
|
||||||
|
InvType = aBase.InvType;
|
||||||
|
Name = aBase.Name;
|
||||||
|
Description = aBase.Description;
|
||||||
|
MediaURL = aBase.MediaURL; //rex
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public class AssetRequestsList
|
||||||
|
{
|
||||||
|
public LLUUID AssetID;
|
||||||
|
public List<NewAssetRequest> Requests = new List<NewAssetRequest>();
|
||||||
|
|
||||||
|
public AssetRequestsList(LLUUID assetID)
|
||||||
|
{
|
||||||
|
AssetID = assetID;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class NewAssetRequest
|
||||||
|
{
|
||||||
|
public LLUUID AssetID;
|
||||||
|
public AssetRequestCallback Callback;
|
||||||
|
|
||||||
|
public NewAssetRequest(LLUUID assetID, AssetRequestCallback callback)
|
||||||
|
{
|
||||||
|
AssetID = assetID;
|
||||||
|
Callback = callback;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,234 @@
|
||||||
|
/*
|
||||||
|
* 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 OpenSim 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.IO;
|
||||||
|
using Db4objects.Db4o;
|
||||||
|
using Db4objects.Db4o.Query;
|
||||||
|
using libsecondlife;
|
||||||
|
using OpenSim.Framework.Console;
|
||||||
|
|
||||||
|
namespace OpenSim.Framework.Communications.Cache
|
||||||
|
{
|
||||||
|
public class LocalAssetServer : AssetServerBase
|
||||||
|
{
|
||||||
|
private IObjectContainer db;
|
||||||
|
|
||||||
|
public LocalAssetServer()
|
||||||
|
{
|
||||||
|
bool yapfile;
|
||||||
|
yapfile = File.Exists(Path.Combine(Util.dataDir(), "regionassets.yap"));
|
||||||
|
|
||||||
|
db = Db4oFactory.OpenFile(Path.Combine(Util.dataDir(), "regionassets.yap"));
|
||||||
|
MainLog.Instance.Verbose("ASSETS", "Db4 Asset database creation");
|
||||||
|
|
||||||
|
if (!yapfile)
|
||||||
|
{
|
||||||
|
SetUpAssetDatabase();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void CreateAndCommitAsset(AssetBase asset)
|
||||||
|
{
|
||||||
|
AssetStorage store = new AssetStorage();
|
||||||
|
store.Data = asset.Data;
|
||||||
|
store.Name = asset.Name;
|
||||||
|
store.UUID = asset.FullID;
|
||||||
|
db.Set(store);
|
||||||
|
db.Commit();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Close()
|
||||||
|
{
|
||||||
|
base.Close();
|
||||||
|
|
||||||
|
if (db != null)
|
||||||
|
{
|
||||||
|
MainLog.Instance.Verbose("ASSETSERVER", "Closing local asset server database");
|
||||||
|
db.Close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// rex new function for "replace assets" functionality
|
||||||
|
public override LLUUID ExistsAsset(sbyte assetType, string name)
|
||||||
|
{
|
||||||
|
IObjectSet result = db.Query(new AssetTypeNameQuery(assetType, name));
|
||||||
|
AssetStorage foundAsset = null;
|
||||||
|
if (result.Count > 0)
|
||||||
|
{
|
||||||
|
foundAsset = (AssetStorage)result.Next();
|
||||||
|
return foundAsset.UUID;
|
||||||
|
}
|
||||||
|
return LLUUID.Zero;
|
||||||
|
}
|
||||||
|
|
||||||
|
// rex new function
|
||||||
|
public override bool ExistsAsset(LLUUID assetID)
|
||||||
|
{
|
||||||
|
IObjectSet result = db.Query(new AssetUUIDQuery(assetID));
|
||||||
|
if (result.Count > 0)
|
||||||
|
return true;
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// rex new function
|
||||||
|
public override AssetBase FetchAsset(LLUUID assetID)
|
||||||
|
{
|
||||||
|
byte[] idata = null;
|
||||||
|
bool found = false;
|
||||||
|
AssetStorage foundAsset = null;
|
||||||
|
IObjectSet result = db.Query(new AssetUUIDQuery(assetID));
|
||||||
|
if (result.Count > 0)
|
||||||
|
{
|
||||||
|
foundAsset = (AssetStorage)result.Next();
|
||||||
|
found = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
AssetBase asset = new AssetBase();
|
||||||
|
if (found)
|
||||||
|
{
|
||||||
|
asset.FullID = foundAsset.UUID;
|
||||||
|
asset.Type = foundAsset.Type;
|
||||||
|
asset.InvType = foundAsset.Type;
|
||||||
|
asset.Name = foundAsset.Name;
|
||||||
|
idata = foundAsset.Data;
|
||||||
|
asset.Data = idata;
|
||||||
|
|
||||||
|
return asset;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override AssetBase GetAsset(AssetRequest req)
|
||||||
|
{
|
||||||
|
byte[] idata = null;
|
||||||
|
bool found = false;
|
||||||
|
AssetStorage foundAsset = null;
|
||||||
|
IObjectSet result = db.Query(new AssetUUIDQuery(req.AssetID));
|
||||||
|
if (result.Count > 0)
|
||||||
|
{
|
||||||
|
foundAsset = (AssetStorage) result.Next();
|
||||||
|
found = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
AssetBase asset = new AssetBase();
|
||||||
|
if (found)
|
||||||
|
{
|
||||||
|
asset.FullID = foundAsset.UUID;
|
||||||
|
asset.Type = foundAsset.Type;
|
||||||
|
asset.InvType = foundAsset.Type;
|
||||||
|
asset.Name = foundAsset.Name;
|
||||||
|
idata = foundAsset.Data;
|
||||||
|
asset.Data = idata;
|
||||||
|
|
||||||
|
return asset;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void StoreAsset(AssetBase asset)
|
||||||
|
{
|
||||||
|
AssetStorage store = new AssetStorage();
|
||||||
|
store.Data = asset.Data;
|
||||||
|
store.Name = asset.Name;
|
||||||
|
store.UUID = asset.FullID;
|
||||||
|
db.Set(store);
|
||||||
|
|
||||||
|
CommitAssets();
|
||||||
|
}
|
||||||
|
|
||||||
|
// rex overrided function for "replace assets" functionality to work with local assetserver
|
||||||
|
public override void UpdateAsset(AssetBase asset)
|
||||||
|
{
|
||||||
|
lock (m_syncLock)
|
||||||
|
{
|
||||||
|
IObjectSet result = db.Query(new AssetUUIDQuery(asset.FullID));
|
||||||
|
AssetStorage foundAsset = null;
|
||||||
|
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < result.Count; i++)
|
||||||
|
{
|
||||||
|
foundAsset = (AssetStorage)result.Next();
|
||||||
|
db.Delete(foundAsset);
|
||||||
|
}
|
||||||
|
|
||||||
|
StoreAsset(asset);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void CommitAssets()
|
||||||
|
{
|
||||||
|
db.Commit();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual void SetUpAssetDatabase()
|
||||||
|
{
|
||||||
|
MainLog.Instance.Verbose("LOCAL ASSET SERVER", "Setting up asset database");
|
||||||
|
|
||||||
|
base.LoadDefaultAssets();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class AssetUUIDQuery : Predicate
|
||||||
|
{
|
||||||
|
private LLUUID _findID;
|
||||||
|
|
||||||
|
public AssetUUIDQuery(LLUUID find)
|
||||||
|
{
|
||||||
|
_findID = find;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Match(AssetStorage asset)
|
||||||
|
{
|
||||||
|
return (asset.UUID == _findID);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// rex new class for "replace assets" functionality
|
||||||
|
public class AssetTypeNameQuery : Predicate
|
||||||
|
{
|
||||||
|
private sbyte _findType;
|
||||||
|
private string _findName;
|
||||||
|
|
||||||
|
public AssetTypeNameQuery(sbyte type, string name)
|
||||||
|
{
|
||||||
|
_findType = type;
|
||||||
|
_findName = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Match(AssetStorage asset)
|
||||||
|
{
|
||||||
|
return ((asset.Type == _findType) && (asset.Name == _findName));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,193 @@
|
||||||
|
/*
|
||||||
|
* 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 OpenSim 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.Threading;
|
||||||
|
using libsecondlife;
|
||||||
|
using OpenSim.Framework.Console;
|
||||||
|
using OpenSim.Framework.AssetLoader.Filesystem;
|
||||||
|
|
||||||
|
namespace OpenSim.Framework.Communications.Cache
|
||||||
|
{
|
||||||
|
public abstract class AssetServerBase : IAssetServer
|
||||||
|
{
|
||||||
|
protected IAssetReceiver m_receiver;
|
||||||
|
protected BlockingQueue<AssetRequest> m_assetRequests;
|
||||||
|
protected Thread m_localAssetServerThread;
|
||||||
|
protected IAssetProvider m_assetProvider;
|
||||||
|
protected object m_syncLock = new object();
|
||||||
|
|
||||||
|
// Temporarily hardcoded - should be a plugin
|
||||||
|
protected IAssetLoader assetLoader = new AssetLoaderFileSystem();
|
||||||
|
|
||||||
|
protected abstract void StoreAsset(AssetBase asset);
|
||||||
|
protected abstract void CommitAssets();
|
||||||
|
|
||||||
|
public abstract LLUUID ExistsAsset(sbyte assetType, string name); // rex new function for "replace assets" functionality
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// This method must be implemented by a subclass to retrieve the asset named in the
|
||||||
|
/// AssetRequest. If the asset is not found, null should be returned.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="req"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
protected abstract AssetBase GetAsset(AssetRequest req);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Process an asset request. This method will call GetAsset(AssetRequest req)
|
||||||
|
/// on the subclass.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="req"></param>
|
||||||
|
protected virtual void ProcessRequest(AssetRequest req)
|
||||||
|
{
|
||||||
|
AssetBase asset = GetAsset(req);
|
||||||
|
|
||||||
|
if (asset != null)
|
||||||
|
{
|
||||||
|
MainLog.Instance.Verbose(
|
||||||
|
"ASSET", "Asset {0} received from asset server", req.AssetID);
|
||||||
|
|
||||||
|
m_receiver.AssetReceived(asset, req.IsTexture);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
MainLog.Instance.Error(
|
||||||
|
"ASSET", "Asset {0} not found by asset server", req.AssetID);
|
||||||
|
|
||||||
|
m_receiver.AssetNotFound(req.AssetID);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void LoadDefaultAssets()
|
||||||
|
{
|
||||||
|
MainLog.Instance.Verbose("ASSETSERVER", "Setting up asset database");
|
||||||
|
|
||||||
|
assetLoader.ForEachDefaultXmlAsset(StoreAsset);
|
||||||
|
|
||||||
|
CommitAssets();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public AssetServerBase()
|
||||||
|
{
|
||||||
|
MainLog.Instance.Verbose("ASSETSERVER", "Starting asset storage system");
|
||||||
|
m_assetRequests = new BlockingQueue<AssetRequest>();
|
||||||
|
|
||||||
|
m_localAssetServerThread = new Thread(RunRequests);
|
||||||
|
m_localAssetServerThread.IsBackground = true;
|
||||||
|
m_localAssetServerThread.Start();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void RunRequests()
|
||||||
|
{
|
||||||
|
while (true) // Since it's a 'blocking queue'
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
AssetRequest req = m_assetRequests.Dequeue();
|
||||||
|
|
||||||
|
ProcessRequest(req);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
MainLog.Instance.Error("ASSETSERVER", e.Message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetReceiver(IAssetReceiver receiver)
|
||||||
|
{
|
||||||
|
m_receiver = receiver;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RequestAsset(LLUUID assetID, bool isTexture)
|
||||||
|
{
|
||||||
|
AssetRequest req = new AssetRequest();
|
||||||
|
req.AssetID = assetID;
|
||||||
|
req.IsTexture = isTexture;
|
||||||
|
m_assetRequests.Enqueue(req);
|
||||||
|
|
||||||
|
MainLog.Instance.Verbose("ASSET", "Added {0} to request queue", assetID);
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void UpdateAsset(AssetBase asset)
|
||||||
|
{
|
||||||
|
lock (m_syncLock)
|
||||||
|
{
|
||||||
|
m_assetProvider.UpdateAsset(asset);
|
||||||
|
m_assetProvider.CommitAssets();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void StoreAndCommitAsset(AssetBase asset)
|
||||||
|
{
|
||||||
|
lock (m_syncLock)
|
||||||
|
{
|
||||||
|
StoreAsset(asset);
|
||||||
|
CommitAssets();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// rex, new function
|
||||||
|
public List<AssetBase> GetAssetList(int vAssetType)
|
||||||
|
{
|
||||||
|
lock (m_syncLock)
|
||||||
|
{
|
||||||
|
return m_assetProvider.GetAssetList(vAssetType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// rex, new function
|
||||||
|
public virtual AssetBase FetchAsset(LLUUID assetID)
|
||||||
|
{
|
||||||
|
lock (m_syncLock)
|
||||||
|
{
|
||||||
|
return m_assetProvider.FetchAsset(assetID);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// rex, new function
|
||||||
|
public virtual bool ExistsAsset(LLUUID assetID)
|
||||||
|
{
|
||||||
|
lock (m_syncLock)
|
||||||
|
{
|
||||||
|
return m_assetProvider.ExistsAsset(assetID);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void Close()
|
||||||
|
{
|
||||||
|
m_localAssetServerThread.Abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetServerInfo(string ServerUrl, string ServerKey)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,109 @@
|
||||||
|
/*
|
||||||
|
* 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 OpenSim 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 libsecondlife;
|
||||||
|
|
||||||
|
namespace OpenSim.Framework.Communications.Cache
|
||||||
|
{
|
||||||
|
public class AssetTransactionManager
|
||||||
|
{
|
||||||
|
// Fields
|
||||||
|
public CommunicationsManager CommsManager;
|
||||||
|
|
||||||
|
public Dictionary<LLUUID, AgentAssetTransactions> AgentTransactions =
|
||||||
|
new Dictionary<LLUUID, AgentAssetTransactions>();
|
||||||
|
|
||||||
|
private bool m_dumpAssetsToFile;
|
||||||
|
|
||||||
|
public AssetTransactionManager(CommunicationsManager commsManager, bool dumpAssetsToFile)
|
||||||
|
{
|
||||||
|
CommsManager = commsManager;
|
||||||
|
m_dumpAssetsToFile = dumpAssetsToFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Methods
|
||||||
|
public AgentAssetTransactions AddUser(LLUUID userID)
|
||||||
|
{
|
||||||
|
lock (AgentTransactions)
|
||||||
|
{
|
||||||
|
if (!AgentTransactions.ContainsKey(userID))
|
||||||
|
{
|
||||||
|
AgentAssetTransactions transactions = new AgentAssetTransactions(userID, this, m_dumpAssetsToFile);
|
||||||
|
AgentTransactions.Add(userID, transactions);
|
||||||
|
return transactions;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AgentAssetTransactions GetUserTransActions(LLUUID userID)
|
||||||
|
{
|
||||||
|
if (AgentTransactions.ContainsKey(userID))
|
||||||
|
{
|
||||||
|
return AgentTransactions[userID];
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void HandleInventoryFromTransaction(IClientAPI remoteClient, LLUUID transactionID, LLUUID folderID,
|
||||||
|
uint callbackID, string description, string name, sbyte invType,
|
||||||
|
sbyte type, byte wearableType, uint nextOwnerMask)
|
||||||
|
{
|
||||||
|
AgentAssetTransactions transactions = GetUserTransActions(remoteClient.AgentId);
|
||||||
|
if (transactions != null)
|
||||||
|
{
|
||||||
|
transactions.RequestCreateInventoryItem(remoteClient, transactionID, folderID, callbackID, description,
|
||||||
|
name, invType, type, wearableType, nextOwnerMask);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void HandleUDPUploadRequest(IClientAPI remoteClient, LLUUID assetID, LLUUID transaction, sbyte type,
|
||||||
|
byte[] data, bool storeLocal, bool tempFile)
|
||||||
|
{
|
||||||
|
// Console.WriteLine("asset upload of " + assetID);
|
||||||
|
AgentAssetTransactions transactions = GetUserTransActions(remoteClient.AgentId);
|
||||||
|
if (transactions != null)
|
||||||
|
{
|
||||||
|
AgentAssetTransactions.AssetXferUploader uploader = transactions.RequestXferUploader(transaction);
|
||||||
|
if (uploader != null)
|
||||||
|
{
|
||||||
|
uploader.Initialise(remoteClient, assetID, transaction, type, data, storeLocal, tempFile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void HandleXfer(IClientAPI remoteClient, ulong xferID, uint packetID, byte[] data)
|
||||||
|
{
|
||||||
|
AgentAssetTransactions transactions = GetUserTransActions(remoteClient.AgentId);
|
||||||
|
if (transactions != null)
|
||||||
|
{
|
||||||
|
transactions.HandleXfer(xferID, packetID, data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,444 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) Contributors, http://opensimulator.org/
|
||||||
|
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of the OpenSim Project nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
||||||
|
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using libsecondlife;
|
||||||
|
using libsecondlife.Packets;
|
||||||
|
using OpenSim.Framework.Servers;
|
||||||
|
using OpenSim.Region.Capabilities;
|
||||||
|
|
||||||
|
namespace OpenSim.Framework.Communications.Cache
|
||||||
|
{
|
||||||
|
public class AgentAssetTransactions
|
||||||
|
{
|
||||||
|
// Fields
|
||||||
|
public List<AssetCapsUploader> CapsUploaders = new List<AssetCapsUploader>();
|
||||||
|
public List<NoteCardCapsUpdate> NotecardUpdaters = new List<NoteCardCapsUpdate>();
|
||||||
|
public LLUUID UserID;
|
||||||
|
public Dictionary<LLUUID, AssetXferUploader> XferUploaders = new Dictionary<LLUUID, AssetXferUploader>();
|
||||||
|
public AssetTransactionManager Manager;
|
||||||
|
private bool m_dumpAssetsToFile;
|
||||||
|
|
||||||
|
// Methods
|
||||||
|
public AgentAssetTransactions(LLUUID agentID, AssetTransactionManager manager, bool dumpAssetsToFile)
|
||||||
|
{
|
||||||
|
UserID = agentID;
|
||||||
|
Manager = manager;
|
||||||
|
m_dumpAssetsToFile = dumpAssetsToFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AssetCapsUploader RequestCapsUploader()
|
||||||
|
{
|
||||||
|
AssetCapsUploader uploader = new AssetCapsUploader();
|
||||||
|
CapsUploaders.Add(uploader);
|
||||||
|
return uploader;
|
||||||
|
}
|
||||||
|
|
||||||
|
public NoteCardCapsUpdate RequestNoteCardUpdater()
|
||||||
|
{
|
||||||
|
NoteCardCapsUpdate update = new NoteCardCapsUpdate();
|
||||||
|
NotecardUpdaters.Add(update);
|
||||||
|
return update;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AssetXferUploader RequestXferUploader(LLUUID transactionID)
|
||||||
|
{
|
||||||
|
if (!XferUploaders.ContainsKey(transactionID))
|
||||||
|
{
|
||||||
|
AssetXferUploader uploader = new AssetXferUploader(this, m_dumpAssetsToFile);
|
||||||
|
|
||||||
|
XferUploaders.Add(transactionID, uploader);
|
||||||
|
return uploader;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void HandleXfer(ulong xferID, uint packetID, byte[] data)
|
||||||
|
{
|
||||||
|
foreach (AssetXferUploader uploader in XferUploaders.Values)
|
||||||
|
{
|
||||||
|
if (uploader.XferID == xferID)
|
||||||
|
{
|
||||||
|
uploader.HandleXferPacket(xferID, packetID, data);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RequestCreateInventoryItem(IClientAPI remoteClient, LLUUID transactionID, LLUUID folderID,
|
||||||
|
uint callbackID, string description, string name, sbyte invType,
|
||||||
|
sbyte type, byte wearableType, uint nextOwnerMask)
|
||||||
|
{
|
||||||
|
if (XferUploaders.ContainsKey(transactionID))
|
||||||
|
{
|
||||||
|
XferUploaders[transactionID].RequestCreateInventoryItem(remoteClient, transactionID, folderID,
|
||||||
|
callbackID, description, name, invType, type,
|
||||||
|
wearableType, nextOwnerMask);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public AssetBase GetTransactionAsset(LLUUID transactionID)
|
||||||
|
{
|
||||||
|
if (XferUploaders.ContainsKey(transactionID))
|
||||||
|
{
|
||||||
|
return XferUploaders[transactionID].GetAssetData();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Nested Types
|
||||||
|
public class AssetXferUploader
|
||||||
|
{
|
||||||
|
// Fields
|
||||||
|
public bool AddToInventory;
|
||||||
|
public AssetBase Asset;
|
||||||
|
public LLUUID InventFolder = LLUUID.Zero;
|
||||||
|
private IClientAPI ourClient;
|
||||||
|
public LLUUID TransactionID = LLUUID.Zero;
|
||||||
|
public bool UploadComplete;
|
||||||
|
public ulong XferID;
|
||||||
|
private string m_name = "";
|
||||||
|
private string m_description = "";
|
||||||
|
private sbyte type = 0;
|
||||||
|
private sbyte invType = 0;
|
||||||
|
private uint nextPerm = 0;
|
||||||
|
private bool m_finished = false;
|
||||||
|
private bool m_createItem = false;
|
||||||
|
private AgentAssetTransactions m_userTransactions;
|
||||||
|
private bool m_storeLocal;
|
||||||
|
private bool m_dumpAssetToFile;
|
||||||
|
|
||||||
|
public AssetXferUploader(AgentAssetTransactions transactions, bool dumpAssetToFile)
|
||||||
|
{
|
||||||
|
m_userTransactions = transactions;
|
||||||
|
m_dumpAssetToFile = dumpAssetToFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Methods
|
||||||
|
public void HandleXferPacket(ulong xferID, uint packetID, byte[] data)
|
||||||
|
{
|
||||||
|
if (XferID == xferID)
|
||||||
|
{
|
||||||
|
if (Asset.Data.Length > 1)
|
||||||
|
{
|
||||||
|
byte[] destinationArray = new byte[Asset.Data.Length + data.Length];
|
||||||
|
Array.Copy(Asset.Data, 0, destinationArray, 0, Asset.Data.Length);
|
||||||
|
Array.Copy(data, 0, destinationArray, Asset.Data.Length, data.Length);
|
||||||
|
Asset.Data = destinationArray;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
byte[] buffer2 = new byte[data.Length - 4];
|
||||||
|
Array.Copy(data, 4, buffer2, 0, data.Length - 4);
|
||||||
|
Asset.Data = buffer2;
|
||||||
|
}
|
||||||
|
ConfirmXferPacketPacket newPack = new ConfirmXferPacketPacket();
|
||||||
|
newPack.XferID.ID = xferID;
|
||||||
|
newPack.XferID.Packet = packetID;
|
||||||
|
ourClient.OutPacket(newPack, ThrottleOutPacketType.Asset);
|
||||||
|
if ((packetID & 0x80000000) != 0)
|
||||||
|
{
|
||||||
|
SendCompleteMessage();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Initialise(IClientAPI remoteClient, LLUUID assetID, LLUUID transaction, sbyte type, byte[] data,
|
||||||
|
bool storeLocal, bool tempFile)
|
||||||
|
{
|
||||||
|
ourClient = remoteClient;
|
||||||
|
Asset = new AssetBase();
|
||||||
|
Asset.FullID = assetID;
|
||||||
|
Asset.InvType = type;
|
||||||
|
Asset.Type = type;
|
||||||
|
Asset.Data = data;
|
||||||
|
Asset.Name = "blank";
|
||||||
|
Asset.Description = "empty";
|
||||||
|
Asset.Local = storeLocal;
|
||||||
|
Asset.Temporary = tempFile;
|
||||||
|
|
||||||
|
TransactionID = transaction;
|
||||||
|
m_storeLocal = storeLocal;
|
||||||
|
if (Asset.Data.Length > 2)
|
||||||
|
{
|
||||||
|
SendCompleteMessage();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ReqestStartXfer();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void ReqestStartXfer()
|
||||||
|
{
|
||||||
|
UploadComplete = false;
|
||||||
|
XferID = Util.GetNextXferID();
|
||||||
|
RequestXferPacket newPack = new RequestXferPacket();
|
||||||
|
newPack.XferID.ID = XferID;
|
||||||
|
newPack.XferID.VFileType = Asset.Type;
|
||||||
|
newPack.XferID.VFileID = Asset.FullID;
|
||||||
|
newPack.XferID.FilePath = 0;
|
||||||
|
newPack.XferID.Filename = new byte[0];
|
||||||
|
ourClient.OutPacket(newPack, ThrottleOutPacketType.Asset);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void SendCompleteMessage()
|
||||||
|
{
|
||||||
|
UploadComplete = true;
|
||||||
|
AssetUploadCompletePacket newPack = new AssetUploadCompletePacket();
|
||||||
|
newPack.AssetBlock.Type = Asset.Type;
|
||||||
|
newPack.AssetBlock.Success = true;
|
||||||
|
newPack.AssetBlock.UUID = Asset.FullID;
|
||||||
|
ourClient.OutPacket(newPack, ThrottleOutPacketType.Asset);
|
||||||
|
m_finished = true;
|
||||||
|
if (m_createItem)
|
||||||
|
{
|
||||||
|
DoCreateItem();
|
||||||
|
}
|
||||||
|
else if (m_storeLocal)
|
||||||
|
{
|
||||||
|
m_userTransactions.Manager.CommsManager.AssetCache.AddAsset(Asset);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Console.WriteLine("upload complete "+ this.TransactionID);
|
||||||
|
|
||||||
|
if (m_dumpAssetToFile)
|
||||||
|
{
|
||||||
|
DateTime now = DateTime.Now;
|
||||||
|
string filename =
|
||||||
|
String.Format("{6}_{7}_{0:d2}{1:d2}{2:d2}_{3:d2}{4:d2}{5:d2}.dat", now.Year, now.Month, now.Day,
|
||||||
|
now.Hour, now.Minute, now.Second, Asset.Name, Asset.Type);
|
||||||
|
SaveAssetToFile(filename, Asset.Data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
///Left this in and commented in case there are unforseen issues
|
||||||
|
//private void SaveAssetToFile(string filename, byte[] data)
|
||||||
|
//{
|
||||||
|
// FileStream fs = File.Create(filename);
|
||||||
|
// BinaryWriter bw = new BinaryWriter(fs);
|
||||||
|
// bw.Write(data);
|
||||||
|
// bw.Close();
|
||||||
|
// fs.Close();
|
||||||
|
//}
|
||||||
|
private void SaveAssetToFile(string filename, byte[] data)
|
||||||
|
{
|
||||||
|
string assetPath = "UserAssets";
|
||||||
|
if (!Directory.Exists(assetPath))
|
||||||
|
{
|
||||||
|
Directory.CreateDirectory(assetPath);
|
||||||
|
}
|
||||||
|
FileStream fs = File.Create(Path.Combine(assetPath, filename));
|
||||||
|
BinaryWriter bw = new BinaryWriter(fs);
|
||||||
|
bw.Write(data);
|
||||||
|
bw.Close();
|
||||||
|
fs.Close();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RequestCreateInventoryItem(IClientAPI remoteClient, LLUUID transactionID, LLUUID folderID,
|
||||||
|
uint callbackID, string description, string name, sbyte invType,
|
||||||
|
sbyte type, byte wearableType, uint nextOwnerMask)
|
||||||
|
{
|
||||||
|
if (TransactionID == transactionID)
|
||||||
|
{
|
||||||
|
InventFolder = folderID;
|
||||||
|
m_name = name;
|
||||||
|
m_description = description;
|
||||||
|
this.type = type;
|
||||||
|
this.invType = invType;
|
||||||
|
nextPerm = nextOwnerMask;
|
||||||
|
Asset.Name = name;
|
||||||
|
Asset.Description = description;
|
||||||
|
Asset.Type = type;
|
||||||
|
Asset.InvType = invType;
|
||||||
|
m_createItem = true;
|
||||||
|
if (m_finished)
|
||||||
|
{
|
||||||
|
DoCreateItem();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void DoCreateItem()
|
||||||
|
{
|
||||||
|
//really need to fix this call, if lbsa71 saw this he would die.
|
||||||
|
m_userTransactions.Manager.CommsManager.AssetCache.AddAsset(Asset);
|
||||||
|
CachedUserInfo userInfo =
|
||||||
|
m_userTransactions.Manager.CommsManager.UserProfileCacheService.GetUserDetails(ourClient.AgentId);
|
||||||
|
if (userInfo != null)
|
||||||
|
{
|
||||||
|
InventoryItemBase item = new InventoryItemBase();
|
||||||
|
item.avatarID = ourClient.AgentId;
|
||||||
|
item.creatorsID = ourClient.AgentId;
|
||||||
|
item.inventoryID = LLUUID.Random();
|
||||||
|
item.assetID = Asset.FullID;
|
||||||
|
item.inventoryDescription = m_description;
|
||||||
|
item.inventoryName = m_name;
|
||||||
|
item.assetType = type;
|
||||||
|
item.invType = invType;
|
||||||
|
item.parentFolderID = InventFolder;
|
||||||
|
item.inventoryCurrentPermissions = 2147483647;
|
||||||
|
item.inventoryNextPermissions = nextPerm;
|
||||||
|
|
||||||
|
userInfo.AddItem(ourClient.AgentId, item);
|
||||||
|
ourClient.SendInventoryItemCreateUpdate(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void UpdateInventoryItem(LLUUID itemID)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public AssetBase GetAssetData()
|
||||||
|
{
|
||||||
|
if (m_finished)
|
||||||
|
{
|
||||||
|
return Asset;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Nested Classes currently not in use (waiting for them to be enabled)
|
||||||
|
|
||||||
|
public class AssetCapsUploader
|
||||||
|
{
|
||||||
|
// Fields
|
||||||
|
private BaseHttpServer httpListener;
|
||||||
|
private LLUUID inventoryItemID;
|
||||||
|
private string m_assetDescription = "";
|
||||||
|
private string m_assetName = "";
|
||||||
|
private LLUUID m_folderID;
|
||||||
|
private LLUUID newAssetID;
|
||||||
|
private bool m_dumpImageToFile;
|
||||||
|
private string uploaderPath = "";
|
||||||
|
|
||||||
|
// Events
|
||||||
|
public event UpLoadedAsset OnUpLoad;
|
||||||
|
|
||||||
|
// Methods
|
||||||
|
public void Initialise(string assetName, string assetDescription, LLUUID assetID, LLUUID inventoryItem,
|
||||||
|
LLUUID folderID, string path, BaseHttpServer httpServer, bool dumpImageToFile)
|
||||||
|
{
|
||||||
|
m_assetName = assetName;
|
||||||
|
m_assetDescription = assetDescription;
|
||||||
|
m_folderID = folderID;
|
||||||
|
newAssetID = assetID;
|
||||||
|
inventoryItemID = inventoryItem;
|
||||||
|
uploaderPath = path;
|
||||||
|
httpListener = httpServer;
|
||||||
|
m_dumpImageToFile = dumpImageToFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SaveImageToFile(string filename, byte[] data)
|
||||||
|
{
|
||||||
|
FileStream output = File.Create(filename);
|
||||||
|
BinaryWriter writer = new BinaryWriter(output);
|
||||||
|
writer.Write(data);
|
||||||
|
writer.Close();
|
||||||
|
output.Close();
|
||||||
|
}
|
||||||
|
|
||||||
|
public string uploaderCaps(byte[] data, string path, string param)
|
||||||
|
{
|
||||||
|
LLUUID inventoryItemID = this.inventoryItemID;
|
||||||
|
string text = "";
|
||||||
|
LLSDAssetUploadComplete complete = new LLSDAssetUploadComplete();
|
||||||
|
complete.new_asset = newAssetID.ToString();
|
||||||
|
complete.new_inventory_item = inventoryItemID;
|
||||||
|
complete.state = "complete";
|
||||||
|
text = LLSDHelpers.SerialiseLLSDReply(complete);
|
||||||
|
httpListener.RemoveStreamHandler("POST", uploaderPath);
|
||||||
|
if (m_dumpImageToFile)
|
||||||
|
{
|
||||||
|
SaveImageToFile(m_assetName + ".jp2", data);
|
||||||
|
}
|
||||||
|
if (OnUpLoad != null)
|
||||||
|
{
|
||||||
|
OnUpLoad(m_assetName, "description", newAssetID, inventoryItemID, LLUUID.Zero, data, "", "");
|
||||||
|
}
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class NoteCardCapsUpdate
|
||||||
|
{
|
||||||
|
// Fields
|
||||||
|
private BaseHttpServer httpListener;
|
||||||
|
private LLUUID inventoryItemID;
|
||||||
|
private string m_assetName = "";
|
||||||
|
private LLUUID newAssetID;
|
||||||
|
private bool SaveImages = false;
|
||||||
|
private string uploaderPath = "";
|
||||||
|
|
||||||
|
// Events
|
||||||
|
public event UpLoadedAsset OnUpLoad;
|
||||||
|
|
||||||
|
// Methods
|
||||||
|
public void Initialise(LLUUID inventoryItem, string path, BaseHttpServer httpServer)
|
||||||
|
{
|
||||||
|
inventoryItemID = inventoryItem;
|
||||||
|
uploaderPath = path;
|
||||||
|
httpListener = httpServer;
|
||||||
|
newAssetID = LLUUID.Random();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SaveImageToFile(string filename, byte[] data)
|
||||||
|
{
|
||||||
|
FileStream output = File.Create(filename);
|
||||||
|
BinaryWriter writer = new BinaryWriter(output);
|
||||||
|
writer.Write(data);
|
||||||
|
writer.Close();
|
||||||
|
output.Close();
|
||||||
|
}
|
||||||
|
|
||||||
|
public string uploaderCaps(byte[] data, string path, string param)
|
||||||
|
{
|
||||||
|
LLUUID inventoryItemID = this.inventoryItemID;
|
||||||
|
string text = "";
|
||||||
|
LLSDAssetUploadComplete complete = new LLSDAssetUploadComplete();
|
||||||
|
complete.new_asset = newAssetID.ToString();
|
||||||
|
complete.new_inventory_item = inventoryItemID;
|
||||||
|
complete.state = "complete";
|
||||||
|
text = LLSDHelpers.SerialiseLLSDReply(complete);
|
||||||
|
httpListener.RemoveStreamHandler("POST", uploaderPath);
|
||||||
|
if (SaveImages)
|
||||||
|
{
|
||||||
|
SaveImageToFile(m_assetName + "notecard.txt", data);
|
||||||
|
}
|
||||||
|
if (OnUpLoad != null)
|
||||||
|
{
|
||||||
|
OnUpLoad(m_assetName, "description", newAssetID, inventoryItemID, LLUUID.Zero, data, "", "");
|
||||||
|
}
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,133 @@
|
||||||
|
/*
|
||||||
|
* 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 OpenSim 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 libsecondlife;
|
||||||
|
|
||||||
|
namespace OpenSim.Framework.Communications.Cache
|
||||||
|
{
|
||||||
|
public class CachedUserInfo
|
||||||
|
{
|
||||||
|
private readonly CommunicationsManager m_parentCommsManager;
|
||||||
|
// Fields
|
||||||
|
public InventoryFolderImpl RootFolder = null;
|
||||||
|
public UserProfileData UserProfile = null;
|
||||||
|
|
||||||
|
public CachedUserInfo(CommunicationsManager commsManager)
|
||||||
|
{
|
||||||
|
m_parentCommsManager = commsManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Methods
|
||||||
|
public void FolderReceive(LLUUID userID, InventoryFolderImpl folderInfo)
|
||||||
|
{
|
||||||
|
if (userID == UserProfile.UUID)
|
||||||
|
{
|
||||||
|
if (RootFolder == null)
|
||||||
|
{
|
||||||
|
if (folderInfo.parentID == LLUUID.Zero)
|
||||||
|
{
|
||||||
|
RootFolder = folderInfo;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (RootFolder.folderID == folderInfo.parentID)
|
||||||
|
{
|
||||||
|
if (!RootFolder.SubFolders.ContainsKey(folderInfo.folderID))
|
||||||
|
{
|
||||||
|
RootFolder.SubFolders.Add(folderInfo.folderID, folderInfo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
InventoryFolderImpl folder = RootFolder.HasSubFolder(folderInfo.parentID);
|
||||||
|
if (folder != null)
|
||||||
|
{
|
||||||
|
if (!folder.SubFolders.ContainsKey(folderInfo.folderID))
|
||||||
|
{
|
||||||
|
folder.SubFolders.Add(folderInfo.folderID, folderInfo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ItemReceive(LLUUID userID, InventoryItemBase itemInfo)
|
||||||
|
{
|
||||||
|
if ((userID == UserProfile.UUID) && (RootFolder != null))
|
||||||
|
{
|
||||||
|
if (itemInfo.parentFolderID == RootFolder.folderID)
|
||||||
|
{
|
||||||
|
if (!RootFolder.Items.ContainsKey(itemInfo.inventoryID))
|
||||||
|
{
|
||||||
|
RootFolder.Items.Add(itemInfo.inventoryID, itemInfo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
InventoryFolderImpl folder = RootFolder.HasSubFolder(itemInfo.parentFolderID);
|
||||||
|
if (folder != null)
|
||||||
|
{
|
||||||
|
if (!folder.Items.ContainsKey(itemInfo.inventoryID))
|
||||||
|
{
|
||||||
|
folder.Items.Add(itemInfo.inventoryID, itemInfo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddItem(LLUUID userID, InventoryItemBase itemInfo)
|
||||||
|
{
|
||||||
|
if ((userID == UserProfile.UUID) && (RootFolder != null))
|
||||||
|
{
|
||||||
|
ItemReceive(userID, itemInfo);
|
||||||
|
m_parentCommsManager.InventoryService.AddNewInventoryItem(userID, itemInfo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void UpdateItem(LLUUID userID, InventoryItemBase itemInfo)
|
||||||
|
{
|
||||||
|
if ((userID == UserProfile.UUID) && (RootFolder != null))
|
||||||
|
{
|
||||||
|
m_parentCommsManager.InventoryService.AddNewInventoryItem(userID, itemInfo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool DeleteItem(LLUUID userID, InventoryItemBase item)
|
||||||
|
{
|
||||||
|
bool result = false;
|
||||||
|
if ((userID == UserProfile.UUID) && (RootFolder != null))
|
||||||
|
{
|
||||||
|
result = RootFolder.DeleteItem(item.inventoryID);
|
||||||
|
if (result)
|
||||||
|
{
|
||||||
|
m_parentCommsManager.InventoryService.DeleteInventoryItem(userID, item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,128 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) Contributors, http://www.openmetaverse.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 OpenSim Project nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
||||||
|
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Xml.Serialization;
|
||||||
|
using OpenSim.Framework.Console;
|
||||||
|
using OpenSim.Framework.Servers;
|
||||||
|
|
||||||
|
namespace OpenSim.Framework.Communications.Cache
|
||||||
|
{
|
||||||
|
public class GridAssetClient : AssetServerBase
|
||||||
|
{
|
||||||
|
private string _assetServerUrl;
|
||||||
|
|
||||||
|
public GridAssetClient(string serverUrl)
|
||||||
|
{
|
||||||
|
_assetServerUrl = serverUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
#region IAssetServer Members
|
||||||
|
|
||||||
|
protected override AssetBase GetAsset(AssetRequest req)
|
||||||
|
{
|
||||||
|
Stream s = null;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
MainLog.Instance.Debug("ASSETCACHE", "Querying for {0}", req.AssetID.ToString());
|
||||||
|
|
||||||
|
RestClient rc = new RestClient(_assetServerUrl);
|
||||||
|
rc.AddResourcePath("assets");
|
||||||
|
rc.AddResourcePath(req.AssetID.ToString());
|
||||||
|
if (req.IsTexture)
|
||||||
|
rc.AddQueryParameter("texture");
|
||||||
|
|
||||||
|
rc.RequestMethod = "GET";
|
||||||
|
s = rc.Request();
|
||||||
|
|
||||||
|
if (s.Length > 0)
|
||||||
|
{
|
||||||
|
XmlSerializer xs = new XmlSerializer(typeof (AssetBase));
|
||||||
|
|
||||||
|
return (AssetBase) xs.Deserialize(s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
MainLog.Instance.Error("ASSETCACHE", e.Message);
|
||||||
|
MainLog.Instance.Debug("ASSETCACHE", "Getting asset {0}", req.AssetID.ToString());
|
||||||
|
MainLog.Instance.Error("ASSETCACHE", e.StackTrace);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public override void UpdateAsset(AssetBase asset)
|
||||||
|
{
|
||||||
|
throw new Exception("The method or operation is not implemented.");
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void StoreAsset(AssetBase asset)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// MemoryStream s = new MemoryStream();
|
||||||
|
|
||||||
|
// XmlSerializer xs = new XmlSerializer(typeof(AssetBase));
|
||||||
|
// xs.Serialize(s, asset);
|
||||||
|
// RestClient rc = new RestClient(_assetServerUrl);
|
||||||
|
MainLog.Instance.Verbose("ASSET", "Storing asset");
|
||||||
|
//rc.AddResourcePath("assets");
|
||||||
|
// rc.RequestMethod = "POST";
|
||||||
|
// rc.Request(s);
|
||||||
|
//MainLog.Instance.Verbose("ASSET", "Stored {0}", rc);
|
||||||
|
MainLog.Instance.Verbose("ASSET", "Sending to " + _assetServerUrl + "/assets/");
|
||||||
|
RestObjectPoster.BeginPostObject<AssetBase>(_assetServerUrl + "/assets/", asset);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
MainLog.Instance.Error("ASSETS", e.Message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void CommitAssets()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Close()
|
||||||
|
{
|
||||||
|
throw new Exception("The method or operation is not implemented.");
|
||||||
|
}
|
||||||
|
|
||||||
|
// rex new function for "replace assets" functionality
|
||||||
|
// TODO: implementation by someone
|
||||||
|
public override libsecondlife.LLUUID ExistsAsset(sbyte assetType, string name)
|
||||||
|
{
|
||||||
|
throw new Exception("The method or operation is not implemented.");
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,184 @@
|
||||||
|
/*
|
||||||
|
* 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 OpenSim 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 libsecondlife;
|
||||||
|
|
||||||
|
namespace OpenSim.Framework.Communications.Cache
|
||||||
|
{
|
||||||
|
public class InventoryFolderImpl : InventoryFolderBase
|
||||||
|
{
|
||||||
|
// Fields
|
||||||
|
public Dictionary<LLUUID, InventoryItemBase> Items = new Dictionary<LLUUID, InventoryItemBase>();
|
||||||
|
public Dictionary<LLUUID, InventoryFolderImpl> SubFolders = new Dictionary<LLUUID, InventoryFolderImpl>();
|
||||||
|
|
||||||
|
// Accessors
|
||||||
|
public int SubFoldersCount
|
||||||
|
{
|
||||||
|
get { return SubFolders.Count; }
|
||||||
|
}
|
||||||
|
|
||||||
|
// Constructors
|
||||||
|
public InventoryFolderImpl(InventoryFolderBase folderbase)
|
||||||
|
{
|
||||||
|
agentID = folderbase.agentID;
|
||||||
|
folderID = folderbase.folderID;
|
||||||
|
name = folderbase.name;
|
||||||
|
parentID = folderbase.parentID;
|
||||||
|
type = folderbase.type;
|
||||||
|
version = folderbase.version;
|
||||||
|
}
|
||||||
|
|
||||||
|
public InventoryFolderImpl()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// Methods
|
||||||
|
public InventoryFolderImpl CreateNewSubFolder(LLUUID folderID, string folderName, ushort type)
|
||||||
|
{
|
||||||
|
if (!SubFolders.ContainsKey(folderID))
|
||||||
|
{
|
||||||
|
InventoryFolderImpl subFold = new InventoryFolderImpl();
|
||||||
|
subFold.name = folderName;
|
||||||
|
subFold.folderID = folderID;
|
||||||
|
subFold.type = (short) type;
|
||||||
|
subFold.parentID = this.folderID;
|
||||||
|
subFold.agentID = agentID;
|
||||||
|
SubFolders.Add(subFold.folderID, subFold);
|
||||||
|
return subFold;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public InventoryItemBase HasItem(LLUUID itemID)
|
||||||
|
{
|
||||||
|
InventoryItemBase base2 = null;
|
||||||
|
if (Items.ContainsKey(itemID))
|
||||||
|
{
|
||||||
|
return Items[itemID];
|
||||||
|
}
|
||||||
|
foreach (InventoryFolderImpl folder in SubFolders.Values)
|
||||||
|
{
|
||||||
|
base2 = folder.HasItem(itemID);
|
||||||
|
if (base2 != null)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return base2;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool DeleteItem(LLUUID itemID)
|
||||||
|
{
|
||||||
|
bool found = false;
|
||||||
|
if (Items.ContainsKey(itemID))
|
||||||
|
{
|
||||||
|
Items.Remove(itemID);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
foreach (InventoryFolderImpl folder in SubFolders.Values)
|
||||||
|
{
|
||||||
|
found = folder.DeleteItem(itemID);
|
||||||
|
if (found == true)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return found;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public InventoryFolderImpl HasSubFolder(LLUUID folderID)
|
||||||
|
{
|
||||||
|
InventoryFolderImpl returnFolder = null;
|
||||||
|
if (SubFolders.ContainsKey(folderID))
|
||||||
|
{
|
||||||
|
returnFolder = SubFolders[folderID];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
foreach (InventoryFolderImpl folder in SubFolders.Values)
|
||||||
|
{
|
||||||
|
returnFolder = folder.HasSubFolder(folderID);
|
||||||
|
if (returnFolder != null)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return returnFolder;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<InventoryItemBase> RequestListOfItems()
|
||||||
|
{
|
||||||
|
List<InventoryItemBase> itemList = new List<InventoryItemBase>();
|
||||||
|
foreach (InventoryItemBase item in Items.Values)
|
||||||
|
{
|
||||||
|
itemList.Add(item);
|
||||||
|
}
|
||||||
|
return itemList;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<InventoryFolderBase> RequestListOfFolders()
|
||||||
|
{
|
||||||
|
List<InventoryFolderBase> folderList = new List<InventoryFolderBase>();
|
||||||
|
foreach (InventoryFolderBase folder in SubFolders.Values)
|
||||||
|
{
|
||||||
|
folderList.Add(folder);
|
||||||
|
}
|
||||||
|
return folderList;
|
||||||
|
}
|
||||||
|
|
||||||
|
// rex, new function
|
||||||
|
public void ClearFolder()
|
||||||
|
{
|
||||||
|
Items.Clear();
|
||||||
|
SubFolders.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
// rex, new function
|
||||||
|
public bool HasAssetID(LLUUID assetID)
|
||||||
|
{
|
||||||
|
foreach (InventoryItemBase item in Items.Values)
|
||||||
|
{
|
||||||
|
if (item.assetID == assetID)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (InventoryFolderImpl folder in SubFolders.Values)
|
||||||
|
{
|
||||||
|
if (folder.name != "World Library")
|
||||||
|
{
|
||||||
|
if (folder.HasAssetID(assetID))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,281 @@
|
||||||
|
/*
|
||||||
|
* 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 OpenSim 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 System.IO;
|
||||||
|
using System.Xml;
|
||||||
|
using libsecondlife;
|
||||||
|
using Nini.Config;
|
||||||
|
|
||||||
|
using OpenSim.Framework.Console;
|
||||||
|
|
||||||
|
namespace OpenSim.Framework.Communications.Cache
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Basically a hack to give us a Inventory library while we don't have a inventory server
|
||||||
|
/// once the server is fully implemented then should read the data from that
|
||||||
|
/// </summary>
|
||||||
|
public class LibraryRootFolder : InventoryFolderImpl
|
||||||
|
{
|
||||||
|
private LLUUID libOwner = new LLUUID("11111111-1111-0000-0000-000100bba000");
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Holds the root library folder and all its descendents. This is really only used during inventory
|
||||||
|
/// setup so that we don't have to repeatedly search the tree of library folders.
|
||||||
|
/// </summary>
|
||||||
|
protected Dictionary<LLUUID, InventoryFolderImpl> libraryFolders
|
||||||
|
= new Dictionary<LLUUID, InventoryFolderImpl>();
|
||||||
|
|
||||||
|
public LibraryRootFolder()
|
||||||
|
{
|
||||||
|
MainLog.Instance.Verbose("LIBRARYINVENTORY", "Loading library inventory");
|
||||||
|
|
||||||
|
agentID = libOwner;
|
||||||
|
folderID = new LLUUID("00000112-000f-0000-0000-000100bba000");
|
||||||
|
name = "OpenSim Library";
|
||||||
|
parentID = LLUUID.Zero;
|
||||||
|
type = (short) 8;
|
||||||
|
version = (ushort) 1;
|
||||||
|
|
||||||
|
libraryFolders.Add(folderID, this);
|
||||||
|
|
||||||
|
LoadLibraries(Path.Combine(Util.inventoryDir(), "Libraries.xml"));
|
||||||
|
|
||||||
|
// CreateLibraryItems();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Hardcoded item creation. Please don't add any more items here - future items should be created
|
||||||
|
/// in the xml in the bin/inventory folder.
|
||||||
|
/// </summary>
|
||||||
|
///
|
||||||
|
/// Commented the following out due to sending it all through xml, remove this section once this is provin to work stable.
|
||||||
|
///
|
||||||
|
//private void CreateLibraryItems()
|
||||||
|
//{
|
||||||
|
// InventoryItemBase item =
|
||||||
|
// CreateItem(new LLUUID("66c41e39-38f9-f75a-024e-585989bfaba9"),
|
||||||
|
// new LLUUID("66c41e39-38f9-f75a-024e-585989bfab73"), "Default Shape", "Default Shape",
|
||||||
|
// (int) AssetType.Bodypart, (int) InventoryType.Wearable, folderID);
|
||||||
|
// item.inventoryCurrentPermissions = 0;
|
||||||
|
// item.inventoryNextPermissions = 0;
|
||||||
|
// Items.Add(item.inventoryID, item);
|
||||||
|
|
||||||
|
// item =
|
||||||
|
// CreateItem(new LLUUID("77c41e39-38f9-f75a-024e-585989bfabc9"),
|
||||||
|
// new LLUUID("77c41e39-38f9-f75a-024e-585989bbabbb"), "Default Skin", "Default Skin",
|
||||||
|
// (int) AssetType.Bodypart, (int) InventoryType.Wearable, folderID);
|
||||||
|
// item.inventoryCurrentPermissions = 0;
|
||||||
|
// item.inventoryNextPermissions = 0;
|
||||||
|
// Items.Add(item.inventoryID, item);
|
||||||
|
|
||||||
|
// item =
|
||||||
|
// CreateItem(new LLUUID("77c41e39-38f9-f75a-0000-585989bf0000"),
|
||||||
|
// new LLUUID("00000000-38f9-1111-024e-222222111110"), "Default Shirt", "Default Shirt",
|
||||||
|
// (int) AssetType.Clothing, (int) InventoryType.Wearable, folderID);
|
||||||
|
// item.inventoryCurrentPermissions = 0;
|
||||||
|
// item.inventoryNextPermissions = 0;
|
||||||
|
// Items.Add(item.inventoryID, item);
|
||||||
|
|
||||||
|
// item =
|
||||||
|
// CreateItem(new LLUUID("77c41e39-38f9-f75a-0000-5859892f1111"),
|
||||||
|
// new LLUUID("00000000-38f9-1111-024e-222222111120"), "Default Pants", "Default Pants",
|
||||||
|
// (int) AssetType.Clothing, (int) InventoryType.Wearable, folderID);
|
||||||
|
// item.inventoryCurrentPermissions = 0;
|
||||||
|
// item.inventoryNextPermissions = 0;
|
||||||
|
// Items.Add(item.inventoryID, item);
|
||||||
|
//}
|
||||||
|
|
||||||
|
public InventoryItemBase CreateItem(LLUUID inventoryID, LLUUID assetID, string name, string description,
|
||||||
|
int assetType, int invType, LLUUID parentFolderID)
|
||||||
|
{
|
||||||
|
InventoryItemBase item = new InventoryItemBase();
|
||||||
|
item.avatarID = libOwner;
|
||||||
|
item.creatorsID = libOwner;
|
||||||
|
item.inventoryID = inventoryID;
|
||||||
|
item.assetID = assetID;
|
||||||
|
item.inventoryDescription = description;
|
||||||
|
item.inventoryName = name;
|
||||||
|
item.assetType = assetType;
|
||||||
|
item.invType = invType;
|
||||||
|
item.parentFolderID = parentFolderID;
|
||||||
|
item.inventoryBasePermissions = 0x7FFFFFFF;
|
||||||
|
item.inventoryEveryOnePermissions = 0x7FFFFFFF;
|
||||||
|
item.inventoryCurrentPermissions = 0x7FFFFFFF;
|
||||||
|
item.inventoryNextPermissions = 0x7FFFFFFF;
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Use the asset set information at path to load assets
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="path"></param>
|
||||||
|
/// <param name="assets"></param>
|
||||||
|
protected void LoadLibraries(string librariesControlPath)
|
||||||
|
{
|
||||||
|
MainLog.Instance.Verbose(
|
||||||
|
"LIBRARYINVENTORY", "Loading libraries control file {0}", librariesControlPath);
|
||||||
|
|
||||||
|
LoadFromFile(librariesControlPath, "Libraries control", ReadLibraryFromConfig);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Read a library set from config
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="config"></param>
|
||||||
|
protected void ReadLibraryFromConfig(IConfig config)
|
||||||
|
{
|
||||||
|
string foldersPath
|
||||||
|
= Path.Combine(
|
||||||
|
Util.inventoryDir(), config.GetString("foldersFile", ""));
|
||||||
|
|
||||||
|
LoadFromFile(foldersPath, "Library folders", ReadFolderFromConfig);
|
||||||
|
|
||||||
|
string itemsPath
|
||||||
|
= Path.Combine(
|
||||||
|
Util.inventoryDir(), config.GetString("itemsFile", ""));
|
||||||
|
|
||||||
|
LoadFromFile(itemsPath, "Library items", ReadItemFromConfig);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Read a library inventory folder from a loaded configuration
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="source"></param>
|
||||||
|
private void ReadFolderFromConfig(IConfig config)
|
||||||
|
{
|
||||||
|
InventoryFolderImpl folderInfo = new InventoryFolderImpl();
|
||||||
|
|
||||||
|
folderInfo.folderID = new LLUUID(config.GetString("folderID", folderID.ToString()));
|
||||||
|
folderInfo.name = config.GetString("name", "unknown");
|
||||||
|
folderInfo.parentID = new LLUUID(config.GetString("parentFolderID", folderID.ToString()));
|
||||||
|
folderInfo.type = (short)config.GetInt("type", 8);
|
||||||
|
|
||||||
|
folderInfo.agentID = libOwner;
|
||||||
|
folderInfo.version = 1;
|
||||||
|
|
||||||
|
if (libraryFolders.ContainsKey(folderInfo.parentID))
|
||||||
|
{
|
||||||
|
InventoryFolderImpl parentFolder = libraryFolders[folderInfo.parentID];
|
||||||
|
|
||||||
|
libraryFolders.Add(folderInfo.folderID, folderInfo);
|
||||||
|
parentFolder.SubFolders.Add(folderInfo.folderID, folderInfo);
|
||||||
|
|
||||||
|
// MainLog.Instance.Verbose(
|
||||||
|
// "LIBRARYINVENTORY", "Adding folder {0} ({1})", folderInfo.name, folderInfo.folderID);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
MainLog.Instance.Warn(
|
||||||
|
"LIBRARYINVENTORY",
|
||||||
|
"Couldn't add folder {0} ({1}) since parent folder with ID {2} does not exist!",
|
||||||
|
folderInfo.name, folderInfo.folderID, folderInfo.parentID);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Read a library inventory item metadata from a loaded configuration
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="source"></param>
|
||||||
|
private void ReadItemFromConfig(IConfig config)
|
||||||
|
{
|
||||||
|
InventoryItemBase item = new InventoryItemBase();
|
||||||
|
item.avatarID = libOwner;
|
||||||
|
item.creatorsID = libOwner;
|
||||||
|
item.inventoryID = new LLUUID(config.GetString("inventoryID", folderID.ToString()));
|
||||||
|
item.assetID = new LLUUID(config.GetString("assetID", LLUUID.Random().ToString()));
|
||||||
|
item.parentFolderID = new LLUUID(config.GetString("folderID", folderID.ToString()));
|
||||||
|
item.inventoryDescription = config.GetString("description", "");
|
||||||
|
item.inventoryName = config.GetString("name", "");
|
||||||
|
item.assetType = config.GetInt("assetType", 0);
|
||||||
|
item.invType = config.GetInt("inventoryType", 0);
|
||||||
|
item.inventoryCurrentPermissions = (uint)config.GetLong("currentPermissions", 0x7FFFFFFF);
|
||||||
|
item.inventoryNextPermissions = (uint)config.GetLong("nextPermissions", 0x7FFFFFFF);
|
||||||
|
item.inventoryEveryOnePermissions = (uint)config.GetLong("everyonePermissions", 0x7FFFFFFF);
|
||||||
|
item.inventoryBasePermissions = (uint)config.GetLong("basePermissions", 0x7FFFFFFF);
|
||||||
|
|
||||||
|
if (libraryFolders.ContainsKey(item.parentFolderID))
|
||||||
|
{
|
||||||
|
InventoryFolderImpl parentFolder = libraryFolders[item.parentFolderID];
|
||||||
|
|
||||||
|
parentFolder.Items.Add(item.inventoryID, item);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
MainLog.Instance.Warn(
|
||||||
|
"LIBRARYINVENTORY",
|
||||||
|
"Couldn't add item {0} ({1}) since parent folder with ID {2} does not exist!",
|
||||||
|
item.inventoryName, item.inventoryID, item.parentFolderID);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private delegate void ConfigAction(IConfig config);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Load the given configuration at a path and perform an action on each Config contained within it
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="path"></param>
|
||||||
|
/// <param name="fileDescription"></param>
|
||||||
|
/// <param name="action"></param>
|
||||||
|
private void LoadFromFile(string path, string fileDescription, ConfigAction action)
|
||||||
|
{
|
||||||
|
if (File.Exists(path))
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
XmlConfigSource source = new XmlConfigSource(path);
|
||||||
|
|
||||||
|
for (int i = 0; i < source.Configs.Count; i++)
|
||||||
|
{
|
||||||
|
action(source.Configs[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (XmlException e)
|
||||||
|
{
|
||||||
|
MainLog.Instance.Error(
|
||||||
|
"LIBRARYINVENTORY", "Error loading {0} : {1}", path, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
MainLog.Instance.Error(
|
||||||
|
"LIBRARYINVENTORY", "{0} file {1} does not exist!", fileDescription, path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks like a simple getter, but is written like this for some consistency with the other Request
|
||||||
|
/// methods in the superclass
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
public Dictionary<LLUUID, InventoryFolderImpl> RequestSelfAndDescendentFolders()
|
||||||
|
{
|
||||||
|
return libraryFolders;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,86 @@
|
||||||
|
// Rex, new file
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Xml;
|
||||||
|
using libsecondlife;
|
||||||
|
using Nini.Config;
|
||||||
|
|
||||||
|
using OpenSim.Framework.Console;
|
||||||
|
|
||||||
|
namespace OpenSim.Framework.Communications.Cache
|
||||||
|
{
|
||||||
|
// Rex, new class implementing the world assets folder
|
||||||
|
public class RexWorldAssetsFolder : InventoryFolderImpl
|
||||||
|
{
|
||||||
|
private LLUUID libOwner = new LLUUID("11111111-1111-0000-0000-000100bba001");
|
||||||
|
private InventoryFolderImpl m_WorldTexturesFolder;
|
||||||
|
private InventoryFolderImpl m_World3DModelsFolder;
|
||||||
|
private AssetCache AssetCache;
|
||||||
|
|
||||||
|
public RexWorldAssetsFolder(AssetCache vAssetCache)
|
||||||
|
{
|
||||||
|
MainLog.Instance.Verbose("LIBRARYINVENTORY", "Creating World library folder");
|
||||||
|
AssetCache = vAssetCache;
|
||||||
|
|
||||||
|
agentID = libOwner;
|
||||||
|
folderID = new LLUUID("00000112-000f-0000-0000-000100bba005");
|
||||||
|
name = "World Library";
|
||||||
|
parentID = new LLUUID("00000112-000f-0000-0000-000100bba000");
|
||||||
|
type = (short)8;
|
||||||
|
version = (ushort)1;
|
||||||
|
|
||||||
|
CreateNewSubFolder(new LLUUID("00000112-000f-0000-0000-000100bba006"), "Textures", (ushort)8);
|
||||||
|
m_WorldTexturesFolder = HasSubFolder("00000112-000f-0000-0000-000100bba006");
|
||||||
|
|
||||||
|
CreateNewSubFolder(new LLUUID("00000112-000f-0000-0000-000100bba007"), "3D Models", (ushort)8);
|
||||||
|
m_World3DModelsFolder = HasSubFolder("00000112-000f-0000-0000-000100bba007");
|
||||||
|
}
|
||||||
|
|
||||||
|
public InventoryItemBase CreateItem(LLUUID inventoryID, LLUUID assetID, string name, string description,
|
||||||
|
int assetType, int invType, LLUUID parentFolderID)
|
||||||
|
{
|
||||||
|
InventoryItemBase item = new InventoryItemBase();
|
||||||
|
item.avatarID = libOwner;
|
||||||
|
item.creatorsID = libOwner;
|
||||||
|
item.inventoryID = inventoryID;
|
||||||
|
item.assetID = assetID;
|
||||||
|
item.inventoryDescription = description;
|
||||||
|
item.inventoryName = name;
|
||||||
|
item.assetType = assetType;
|
||||||
|
item.invType = invType;
|
||||||
|
item.parentFolderID = parentFolderID;
|
||||||
|
item.inventoryBasePermissions = 0x7FFFFFFF;
|
||||||
|
item.inventoryEveryOnePermissions = 0x7FFFFFFF;
|
||||||
|
item.inventoryCurrentPermissions = 0x7FFFFFFF;
|
||||||
|
item.inventoryNextPermissions = 0x7FFFFFFF;
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Rex, function added.
|
||||||
|
public void UpdateWorldAssetFolders()
|
||||||
|
{
|
||||||
|
// Textures
|
||||||
|
List<AssetBase> allTex = AssetCache.GetAssetList(0);
|
||||||
|
m_WorldTexturesFolder.ClearFolder();
|
||||||
|
|
||||||
|
InventoryItemBase item;
|
||||||
|
foreach (AssetBase asset in allTex)
|
||||||
|
{
|
||||||
|
item = CreateItem(LLUUID.Random(), asset.FullID, asset.Name, asset.Description, (int)AssetType.Texture, (int)InventoryType.Texture, m_WorldTexturesFolder.folderID);
|
||||||
|
m_WorldTexturesFolder.Items.Add(item.inventoryID, item);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3D Models
|
||||||
|
List<AssetBase> allModels = AssetCache.GetAssetList(6);
|
||||||
|
m_World3DModelsFolder.ClearFolder();
|
||||||
|
foreach (AssetBase asset in allModels)
|
||||||
|
{
|
||||||
|
if (asset.Name != "Primitive")
|
||||||
|
{
|
||||||
|
item = CreateItem(LLUUID.Random(), asset.FullID, asset.Name, asset.Description, 43, 6, m_World3DModelsFolder.folderID);
|
||||||
|
m_World3DModelsFolder.Items.Add(item.inventoryID, item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,107 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) Contributors, http://www.openmetaverse.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 OpenSim 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 OpenSim.Framework.Console;
|
||||||
|
|
||||||
|
namespace OpenSim.Framework.Communications.Cache
|
||||||
|
{
|
||||||
|
public class SQLAssetServer : AssetServerBase
|
||||||
|
{
|
||||||
|
public SQLAssetServer(string pluginName)
|
||||||
|
{
|
||||||
|
AddPlugin(pluginName);
|
||||||
|
}
|
||||||
|
|
||||||
|
public SQLAssetServer(IAssetProvider assetProvider)
|
||||||
|
{
|
||||||
|
m_assetProvider = assetProvider;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddPlugin(string FileName)
|
||||||
|
{
|
||||||
|
MainLog.Instance.Verbose("SQLAssetServer", "AssetStorage: Attempting to load " + FileName);
|
||||||
|
Assembly pluginAssembly = Assembly.LoadFrom(FileName);
|
||||||
|
|
||||||
|
foreach (Type pluginType in pluginAssembly.GetTypes())
|
||||||
|
{
|
||||||
|
if (!pluginType.IsAbstract)
|
||||||
|
{
|
||||||
|
Type typeInterface = pluginType.GetInterface("IAssetProvider", true);
|
||||||
|
|
||||||
|
if (typeInterface != null)
|
||||||
|
{
|
||||||
|
IAssetProvider plug =
|
||||||
|
(IAssetProvider) Activator.CreateInstance(pluginAssembly.GetType(pluginType.ToString()));
|
||||||
|
m_assetProvider = plug;
|
||||||
|
m_assetProvider.Initialise();
|
||||||
|
|
||||||
|
MainLog.Instance.Verbose("AssetStorage",
|
||||||
|
"Added " + m_assetProvider.Name + " " +
|
||||||
|
m_assetProvider.Version);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public override void Close()
|
||||||
|
{
|
||||||
|
base.Close();
|
||||||
|
|
||||||
|
m_assetProvider.CommitAssets();
|
||||||
|
}
|
||||||
|
|
||||||
|
// rex new function for "replace assets" functionality
|
||||||
|
public override libsecondlife.LLUUID ExistsAsset(sbyte assetType, string name)
|
||||||
|
{
|
||||||
|
return m_assetProvider.ExistsAsset(assetType, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override AssetBase GetAsset(AssetRequest req)
|
||||||
|
{
|
||||||
|
AssetBase asset;
|
||||||
|
lock (m_syncLock)
|
||||||
|
{
|
||||||
|
asset = m_assetProvider.FetchAsset(req.AssetID);
|
||||||
|
}
|
||||||
|
|
||||||
|
return asset;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void StoreAsset(AssetBase asset)
|
||||||
|
{
|
||||||
|
m_assetProvider.CreateAsset(asset);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void CommitAssets()
|
||||||
|
{
|
||||||
|
m_assetProvider.CommitAssets();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,368 @@
|
||||||
|
/*
|
||||||
|
* 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 OpenSim 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 libsecondlife;
|
||||||
|
using OpenSim.Framework.Console;
|
||||||
|
|
||||||
|
namespace OpenSim.Framework.Communications.Cache
|
||||||
|
{
|
||||||
|
public class UserProfileCacheService
|
||||||
|
{
|
||||||
|
// Fields
|
||||||
|
private readonly CommunicationsManager m_parent;
|
||||||
|
private readonly Dictionary<LLUUID, CachedUserInfo> m_userProfiles = new Dictionary<LLUUID, CachedUserInfo>();
|
||||||
|
|
||||||
|
public LibraryRootFolder libraryRoot = new LibraryRootFolder();
|
||||||
|
public RexWorldAssetsFolder worldlibraryRoot = null; // rex added
|
||||||
|
|
||||||
|
// Methods
|
||||||
|
public UserProfileCacheService(CommunicationsManager parent)
|
||||||
|
{
|
||||||
|
m_parent = parent;
|
||||||
|
// rex, added worldlibrary
|
||||||
|
if (GlobalSettings.Instance.ConfigSource.Configs["Startup"].GetBoolean("worldlibraryfolder", true))
|
||||||
|
{
|
||||||
|
worldlibraryRoot = new RexWorldAssetsFolder(m_parent.AssetCache);
|
||||||
|
libraryRoot.CreateNewSubFolder(new LLUUID("00000112-000f-0000-0000-000100bba005"), "World Library", (ushort)8);
|
||||||
|
}
|
||||||
|
// rexend
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A new user has moved into a region in this instance
|
||||||
|
/// so get info from servers
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="userID"></param>
|
||||||
|
public void AddNewUser(LLUUID userID)
|
||||||
|
{
|
||||||
|
// Potential fix - Multithreading issue.
|
||||||
|
lock (m_userProfiles)
|
||||||
|
{
|
||||||
|
if (!m_userProfiles.ContainsKey(userID))
|
||||||
|
{
|
||||||
|
CachedUserInfo userInfo = new CachedUserInfo(m_parent);
|
||||||
|
userInfo.UserProfile = m_parent.UserService.GetUserProfile(userID, "");
|
||||||
|
|
||||||
|
if (userInfo.UserProfile != null)
|
||||||
|
{
|
||||||
|
// The request itself will occur when the agent finishes logging on to the region
|
||||||
|
// so there's no need to do it here.
|
||||||
|
//RequestInventoryForUser(userID, userInfo);
|
||||||
|
m_userProfiles.Add(userID, userInfo);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
MainLog.Instance.Error("USERCACHE", "User profile for user {0} not found", userID);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Rex mode
|
||||||
|
/// <summary>
|
||||||
|
/// A new user has moved into a region in this instance
|
||||||
|
/// so get info from servers
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="userID"></param>
|
||||||
|
public void AddNewUser(LLUUID userID, string authAddr)
|
||||||
|
{
|
||||||
|
// Potential fix - Multithreading issue.
|
||||||
|
lock (m_userProfiles)
|
||||||
|
{
|
||||||
|
if (!m_userProfiles.ContainsKey(userID))
|
||||||
|
{
|
||||||
|
CachedUserInfo userInfo = new CachedUserInfo(m_parent);
|
||||||
|
userInfo.UserProfile = m_parent.UserService.GetUserProfile(userID, authAddr);
|
||||||
|
|
||||||
|
if (userInfo.UserProfile != null)
|
||||||
|
{
|
||||||
|
//RequestInventoryForUser(userID, userInfo);
|
||||||
|
// The request itself will occur when the agent finishes logging on to the region
|
||||||
|
// so there's no need to do it here.
|
||||||
|
//RequestInventoryForUser(userID, userInfo);
|
||||||
|
m_userProfiles.Add(userID, userInfo);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
System.Console.WriteLine("CACHE", "User profile for user not found");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void UpdateUserInventory(LLUUID userID)
|
||||||
|
{
|
||||||
|
CachedUserInfo userInfo = GetUserDetails(userID);
|
||||||
|
if (userInfo != null)
|
||||||
|
{
|
||||||
|
RequestInventoryForUser(userID, userInfo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public CachedUserInfo GetUserDetails(LLUUID userID)
|
||||||
|
{
|
||||||
|
if (m_userProfiles.ContainsKey(userID))
|
||||||
|
return m_userProfiles[userID];
|
||||||
|
else
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void HandleCreateInventoryFolder(IClientAPI remoteClient, LLUUID folderID, ushort folderType,
|
||||||
|
string folderName, LLUUID parentID)
|
||||||
|
{
|
||||||
|
CachedUserInfo userProfile;
|
||||||
|
|
||||||
|
if (m_userProfiles.TryGetValue(remoteClient.AgentId, out userProfile))
|
||||||
|
{
|
||||||
|
if (userProfile.RootFolder != null)
|
||||||
|
{
|
||||||
|
if (userProfile.RootFolder.folderID == parentID)
|
||||||
|
{
|
||||||
|
InventoryFolderImpl createdFolder =
|
||||||
|
userProfile.RootFolder.CreateNewSubFolder(folderID, folderName, folderType);
|
||||||
|
|
||||||
|
if (createdFolder != null)
|
||||||
|
{
|
||||||
|
InventoryFolderBase createdBaseFolder = new InventoryFolderBase();
|
||||||
|
createdBaseFolder.agentID = createdFolder.agentID;
|
||||||
|
createdBaseFolder.folderID = createdFolder.folderID;
|
||||||
|
createdBaseFolder.name = createdFolder.name;
|
||||||
|
createdBaseFolder.parentID = createdFolder.parentID;
|
||||||
|
createdBaseFolder.type = createdFolder.type;
|
||||||
|
createdBaseFolder.version = createdFolder.version;
|
||||||
|
m_parent.InventoryService.AddNewInventoryFolder(remoteClient.AgentId, createdBaseFolder);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
InventoryFolderImpl folder = userProfile.RootFolder.HasSubFolder(parentID);
|
||||||
|
if (folder != null)
|
||||||
|
{
|
||||||
|
folder.CreateNewSubFolder(folderID, folderName, folderType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void HandleUpdateInventoryFolder(IClientAPI remoteClient, LLUUID folderID, ushort type, string name,
|
||||||
|
LLUUID parentID)
|
||||||
|
{
|
||||||
|
CachedUserInfo userProfile;
|
||||||
|
|
||||||
|
if (m_userProfiles.TryGetValue(remoteClient.AgentId, out userProfile))
|
||||||
|
{
|
||||||
|
if (userProfile.RootFolder != null)
|
||||||
|
{
|
||||||
|
InventoryFolderBase baseFolder = new InventoryFolderBase();
|
||||||
|
baseFolder.agentID = remoteClient.AgentId;
|
||||||
|
baseFolder.folderID = folderID;
|
||||||
|
baseFolder.name = name;
|
||||||
|
baseFolder.parentID = parentID;
|
||||||
|
baseFolder.type = (short) type;
|
||||||
|
baseFolder.version = userProfile.RootFolder.version;
|
||||||
|
m_parent.InventoryService.AddNewInventoryFolder(remoteClient.AgentId, baseFolder);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void HandleMoveInventoryFolder(IClientAPI remoteClient, LLUUID folderID, LLUUID parentID)
|
||||||
|
{
|
||||||
|
CachedUserInfo userProfile;
|
||||||
|
|
||||||
|
if (m_userProfiles.TryGetValue(remoteClient.AgentId, out userProfile))
|
||||||
|
{
|
||||||
|
if (userProfile.RootFolder != null)
|
||||||
|
{
|
||||||
|
InventoryFolderBase baseFolder = new InventoryFolderBase();
|
||||||
|
baseFolder.agentID = remoteClient.AgentId;
|
||||||
|
baseFolder.folderID = folderID;
|
||||||
|
baseFolder.parentID = parentID;
|
||||||
|
m_parent.InventoryService.MoveInventoryFolder(remoteClient.AgentId, baseFolder);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Tell the client about the various child items and folders contained in the requested folder.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="remoteClient"></param>
|
||||||
|
/// <param name="folderID"></param>
|
||||||
|
/// <param name="ownerID"></param>
|
||||||
|
/// <param name="fetchFolders"></param>
|
||||||
|
/// <param name="fetchItems"></param>
|
||||||
|
/// <param name="sortOrder"></param>
|
||||||
|
public void HandleFetchInventoryDescendents(IClientAPI remoteClient, LLUUID folderID, LLUUID ownerID,
|
||||||
|
bool fetchFolders, bool fetchItems, int sortOrder)
|
||||||
|
{
|
||||||
|
// XXX We're not handling sortOrder yet!
|
||||||
|
|
||||||
|
InventoryFolderImpl fold = null;
|
||||||
|
|
||||||
|
// rex, added worldassetfolder
|
||||||
|
if (worldlibraryRoot != null)
|
||||||
|
{
|
||||||
|
if (folderID == worldlibraryRoot.folderID)
|
||||||
|
{
|
||||||
|
remoteClient.SendInventoryFolderDetails(
|
||||||
|
worldlibraryRoot.agentID, worldlibraryRoot.folderID, worldlibraryRoot.RequestListOfItems(),
|
||||||
|
worldlibraryRoot.RequestListOfFolders(), fetchFolders, fetchItems);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if ((fold = worldlibraryRoot.HasSubFolder(folderID)) != null)
|
||||||
|
{
|
||||||
|
worldlibraryRoot.UpdateWorldAssetFolders();
|
||||||
|
remoteClient.SendInventoryFolderDetails(
|
||||||
|
worldlibraryRoot.agentID, folderID, fold.RequestListOfItems(),
|
||||||
|
fold.RequestListOfFolders(), fetchFolders, fetchItems);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// rex-end
|
||||||
|
|
||||||
|
if (folderID == libraryRoot.folderID)
|
||||||
|
{
|
||||||
|
remoteClient.SendInventoryFolderDetails(
|
||||||
|
libraryRoot.agentID, libraryRoot.folderID, libraryRoot.RequestListOfItems(),
|
||||||
|
libraryRoot.RequestListOfFolders(), fetchFolders, fetchItems);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((fold = libraryRoot.HasSubFolder(folderID)) != null)
|
||||||
|
{
|
||||||
|
remoteClient.SendInventoryFolderDetails(
|
||||||
|
libraryRoot.agentID, folderID, fold.RequestListOfItems(),
|
||||||
|
fold.RequestListOfFolders(), fetchFolders, fetchItems);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
CachedUserInfo userProfile;
|
||||||
|
if (m_userProfiles.TryGetValue(remoteClient.AgentId, out userProfile))
|
||||||
|
{
|
||||||
|
if (userProfile.RootFolder != null)
|
||||||
|
{
|
||||||
|
if (userProfile.RootFolder.folderID == folderID)
|
||||||
|
{
|
||||||
|
remoteClient.SendInventoryFolderDetails(
|
||||||
|
remoteClient.AgentId, folderID, userProfile.RootFolder.RequestListOfItems(),
|
||||||
|
userProfile.RootFolder.RequestListOfFolders(),
|
||||||
|
fetchFolders, fetchItems);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if ((fold = userProfile.RootFolder.HasSubFolder(folderID)) != null)
|
||||||
|
{
|
||||||
|
remoteClient.SendInventoryFolderDetails(
|
||||||
|
remoteClient.AgentId, folderID, fold.RequestListOfItems(),
|
||||||
|
fold.RequestListOfFolders(), fetchFolders, fetchItems);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
MainLog.Instance.Error(
|
||||||
|
"INVENTORYCACHE", "Could not find root folder for user {0}", remoteClient.Name);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
MainLog.Instance.Error(
|
||||||
|
"INVENTORYCACHE",
|
||||||
|
"Could not find user profile for {0} for folder {1}",
|
||||||
|
remoteClient.Name, folderID);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we've reached this point then we couldn't find the folder, even though the client thinks
|
||||||
|
// it exists
|
||||||
|
MainLog.Instance.Error(
|
||||||
|
"INVENTORYCACHE",
|
||||||
|
"Could not find folder {0} for user {1}",
|
||||||
|
folderID, remoteClient.Name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void HandlePurgeInventoryDescendents(IClientAPI remoteClient, LLUUID folderID)
|
||||||
|
{
|
||||||
|
CachedUserInfo userProfile;
|
||||||
|
if (m_userProfiles.TryGetValue(remoteClient.AgentId, out userProfile))
|
||||||
|
{
|
||||||
|
if (userProfile.RootFolder != null)
|
||||||
|
{
|
||||||
|
InventoryFolderImpl subFolder = userProfile.RootFolder.HasSubFolder(folderID);
|
||||||
|
if (subFolder != null)
|
||||||
|
{
|
||||||
|
List<InventoryItemBase> items = subFolder.RequestListOfItems();
|
||||||
|
foreach (InventoryItemBase item in items)
|
||||||
|
{
|
||||||
|
userProfile.DeleteItem(remoteClient.AgentId, item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void HandleFetchInventory(IClientAPI remoteClient, LLUUID itemID, LLUUID ownerID)
|
||||||
|
{
|
||||||
|
if (ownerID == libraryRoot.agentID)
|
||||||
|
{
|
||||||
|
//Console.WriteLine("request info for library item");
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
CachedUserInfo userProfile;
|
||||||
|
if (m_userProfiles.TryGetValue(remoteClient.AgentId, out userProfile))
|
||||||
|
{
|
||||||
|
if (userProfile.RootFolder != null)
|
||||||
|
{
|
||||||
|
InventoryItemBase item = userProfile.RootFolder.HasItem(itemID);
|
||||||
|
if (item != null)
|
||||||
|
{
|
||||||
|
remoteClient.SendInventoryItemDetails(ownerID, item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void RequestInventoryForUser(LLUUID userID, CachedUserInfo userInfo)
|
||||||
|
{
|
||||||
|
m_parent.InventoryService.RequestInventoryForUser(userID, userInfo.FolderReceive, userInfo.ItemReceive);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,812 @@
|
||||||
|
/*
|
||||||
|
* 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 OpenSim 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 libsecondlife;
|
||||||
|
using OpenSim.Framework;
|
||||||
|
using OpenSim.Framework.Communications.Cache;
|
||||||
|
using OpenSim.Framework.Console;
|
||||||
|
using OpenSim.Framework.Servers;
|
||||||
|
|
||||||
|
namespace OpenSim.Region.Capabilities
|
||||||
|
{
|
||||||
|
public delegate void UpLoadedAsset(
|
||||||
|
string assetName, string description, LLUUID assetID, LLUUID inventoryItem, LLUUID parentFolder,
|
||||||
|
byte[] data, string inventoryType, string assetType);
|
||||||
|
|
||||||
|
public delegate LLUUID UpdateItem(LLUUID itemID, byte[] data);
|
||||||
|
|
||||||
|
public delegate void UpdateTaskScript(LLUUID itemID, LLUUID primID, bool isScriptRunning, byte[] data);
|
||||||
|
|
||||||
|
public delegate void NewInventoryItem(LLUUID userID, InventoryItemBase item);
|
||||||
|
|
||||||
|
// rex, added for asset replace functionality
|
||||||
|
public delegate bool InventoryAssetCheck(LLUUID userID, LLUUID assetID);
|
||||||
|
|
||||||
|
public delegate LLUUID ItemUpdatedCallback(LLUUID userID, LLUUID itemID, byte[] data);
|
||||||
|
|
||||||
|
public delegate void TaskScriptUpdatedCallback(LLUUID userID, LLUUID itemID, LLUUID primID,
|
||||||
|
bool isScriptRunning, byte[] data);
|
||||||
|
|
||||||
|
public class Caps
|
||||||
|
{
|
||||||
|
private string m_httpListenerHostName;
|
||||||
|
private uint m_httpListenPort;
|
||||||
|
|
||||||
|
private string m_capsObjectPath = "00001-";
|
||||||
|
private string m_requestPath = "0000/";
|
||||||
|
private string m_mapLayerPath = "0001/";
|
||||||
|
private string m_newInventory = "0002/";
|
||||||
|
//private string m_requestTexture = "0003/";
|
||||||
|
private string m_notecardUpdatePath = "0004/";
|
||||||
|
private string m_notecardTaskUpdatePath = "0005/";
|
||||||
|
|
||||||
|
//private string eventQueue = "0100/";
|
||||||
|
private BaseHttpServer m_httpListener;
|
||||||
|
private LLUUID m_agentID;
|
||||||
|
private AssetCache m_assetCache;
|
||||||
|
private int m_eventQueueCount = 1;
|
||||||
|
private Queue<string> m_capsEventQueue = new Queue<string>();
|
||||||
|
private bool m_dumpAssetsToFile;
|
||||||
|
private bool m_replaceAssets;
|
||||||
|
|
||||||
|
// These are callbacks which will be setup by the scene so that we can update scene data when we
|
||||||
|
// receive capability calls
|
||||||
|
public NewInventoryItem AddNewInventoryItem = null;
|
||||||
|
public InventoryAssetCheck CheckInventoryForAsset = null;
|
||||||
|
public ItemUpdatedCallback ItemUpdatedCall = null;
|
||||||
|
public TaskScriptUpdatedCallback TaskScriptUpdatedCall = null;
|
||||||
|
|
||||||
|
public Caps(AssetCache assetCache, BaseHttpServer httpServer, string httpListen, uint httpPort, string capsPath,
|
||||||
|
LLUUID agent, bool dumpAssetsToFile)
|
||||||
|
{
|
||||||
|
m_assetCache = assetCache;
|
||||||
|
m_capsObjectPath = capsPath;
|
||||||
|
m_httpListener = httpServer;
|
||||||
|
m_httpListenerHostName = httpListen;
|
||||||
|
m_httpListenPort = httpPort;
|
||||||
|
m_agentID = agent;
|
||||||
|
m_dumpAssetsToFile = dumpAssetsToFile;
|
||||||
|
|
||||||
|
m_replaceAssets = (GlobalSettings.Instance.ConfigSource.Configs["Startup"].GetBoolean("replace_assets", true));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
public void RegisterHandlers()
|
||||||
|
{
|
||||||
|
MainLog.Instance.Verbose("CAPS", "Registering CAPS handlers");
|
||||||
|
string capsBase = "/CAPS/" + m_capsObjectPath;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
m_httpListener.AddStreamHandler(
|
||||||
|
new LLSDStreamhandler<LLSDMapRequest, LLSDMapLayerResponse>("POST", capsBase + m_mapLayerPath,
|
||||||
|
GetMapLayer));
|
||||||
|
m_httpListener.AddStreamHandler(
|
||||||
|
new LLSDStreamhandler<LLSDAssetUploadRequest, LLSDAssetUploadResponse>("POST",
|
||||||
|
capsBase + m_newInventory,
|
||||||
|
NewAgentInventoryRequest));
|
||||||
|
|
||||||
|
AddLegacyCapsHandler(m_httpListener, m_requestPath, CapsRequest);
|
||||||
|
//AddLegacyCapsHandler(m_httpListener, m_requestTexture , RequestTexture);
|
||||||
|
AddLegacyCapsHandler(m_httpListener, m_notecardUpdatePath, NoteCardAgentInventory);
|
||||||
|
AddLegacyCapsHandler(m_httpListener, m_notecardTaskUpdatePath, ScriptTaskInventory);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
MainLog.Instance.Error("CAPS", e.ToString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//[Obsolete("Use BaseHttpServer.AddStreamHandler(new LLSDStreamHandler( LLSDMethod delegate )) instead.")]
|
||||||
|
//Commented out the obsolete as at this time the first caps request can not use the new Caps method
|
||||||
|
//as the sent type is a array and not a map and the deserialising doesn't deal properly with arrays.
|
||||||
|
private void AddLegacyCapsHandler(BaseHttpServer httpListener, string path, RestMethod restMethod)
|
||||||
|
{
|
||||||
|
string capsBase = "/CAPS/" + m_capsObjectPath;
|
||||||
|
httpListener.AddStreamHandler(new RestStreamHandler("POST", capsBase + path, restMethod));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Construct a client response detailing all the capabilities this server can provide.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="request"></param>
|
||||||
|
/// <param name="path"></param>
|
||||||
|
/// <param name="param"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public string CapsRequest(string request, string path, string param)
|
||||||
|
{
|
||||||
|
//Console.WriteLine("caps request " + request);
|
||||||
|
string result = LLSDHelpers.SerialiseLLSDReply(GetCapabilities());
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Return an LLSDCapsDetails listing all the capabilities this server can provide
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
protected LLSDCapsDetails GetCapabilities()
|
||||||
|
{
|
||||||
|
LLSDCapsDetails caps = new LLSDCapsDetails();
|
||||||
|
string capsBaseUrl = "http://" + m_httpListenerHostName + ":" + m_httpListenPort.ToString() + "/CAPS/" +
|
||||||
|
m_capsObjectPath;
|
||||||
|
caps.MapLayer = capsBaseUrl + m_mapLayerPath;
|
||||||
|
// caps.RequestTextureDownload = capsBaseUrl + m_requestTexture;
|
||||||
|
caps.NewFileAgentInventory = capsBaseUrl + m_newInventory;
|
||||||
|
caps.UpdateNotecardAgentInventory = capsBaseUrl + m_notecardUpdatePath;
|
||||||
|
caps.UpdateScriptAgentInventory = capsBaseUrl + m_notecardUpdatePath;
|
||||||
|
caps.UpdateScriptTaskInventory = capsBaseUrl + m_notecardTaskUpdatePath;
|
||||||
|
return caps;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="mapReq"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public LLSDMapLayerResponse GetMapLayer(LLSDMapRequest mapReq)
|
||||||
|
{
|
||||||
|
LLSDMapLayerResponse mapResponse = new LLSDMapLayerResponse();
|
||||||
|
mapResponse.LayerData.Array.Add(GetLLSDMapLayerResponse());
|
||||||
|
return mapResponse;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
protected LLSDMapLayer GetLLSDMapLayerResponse()
|
||||||
|
{
|
||||||
|
LLSDMapLayer mapLayer = new LLSDMapLayer();
|
||||||
|
mapLayer.Right = 5000;
|
||||||
|
mapLayer.Top = 5000;
|
||||||
|
mapLayer.ImageID = new LLUUID("00000000-0000-0000-9999-000000000006");
|
||||||
|
return mapLayer;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="request"></param>
|
||||||
|
/// <param name="path"></param>
|
||||||
|
/// <param name="param"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public string RequestTexture(string request, string path, string param)
|
||||||
|
{
|
||||||
|
Console.WriteLine("texture request " + request);
|
||||||
|
// Needs implementing (added to remove compiler warning)
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
#region EventQueue (Currently not enabled)
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="request"></param>
|
||||||
|
/// <param name="path"></param>
|
||||||
|
/// <param name="param"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public string ProcessEventQueue(string request, string path, string param)
|
||||||
|
{
|
||||||
|
string res = "";
|
||||||
|
|
||||||
|
if (m_capsEventQueue.Count > 0)
|
||||||
|
{
|
||||||
|
lock (m_capsEventQueue)
|
||||||
|
{
|
||||||
|
string item = m_capsEventQueue.Dequeue();
|
||||||
|
res = item;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
res = CreateEmptyEventResponse();
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="caps"></param>
|
||||||
|
/// <param name="ipAddressPort"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public string CreateEstablishAgentComms(string caps, string ipAddressPort)
|
||||||
|
{
|
||||||
|
LLSDCapEvent eventItem = new LLSDCapEvent();
|
||||||
|
eventItem.id = m_eventQueueCount;
|
||||||
|
//should be creating a EstablishAgentComms item, but there isn't a class for it yet
|
||||||
|
eventItem.events.Array.Add(new LLSDEmpty());
|
||||||
|
string res = LLSDHelpers.SerialiseLLSDReply(eventItem);
|
||||||
|
m_eventQueueCount++;
|
||||||
|
|
||||||
|
m_capsEventQueue.Enqueue(res);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
public string CreateEmptyEventResponse()
|
||||||
|
{
|
||||||
|
LLSDCapEvent eventItem = new LLSDCapEvent();
|
||||||
|
eventItem.id = m_eventQueueCount;
|
||||||
|
eventItem.events.Array.Add(new LLSDEmpty());
|
||||||
|
string res = LLSDHelpers.SerialiseLLSDReply(eventItem);
|
||||||
|
m_eventQueueCount++;
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Callback for a client request for an upload url for a script task
|
||||||
|
/// inventory update
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="request"></param>
|
||||||
|
/// <param name="path"></param>
|
||||||
|
/// <param name="param"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public string ScriptTaskInventory(string request, string path, string param)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// MainLog.Instance.Debug("CAPS", "request: {0}, path: {1}, param: {2}", request, path, param);
|
||||||
|
|
||||||
|
Hashtable hash = (Hashtable) LLSD.LLSDDeserialize(Helpers.StringToField(request));
|
||||||
|
LLSDTaskScriptUpdate llsdUpdateRequest = new LLSDTaskScriptUpdate();
|
||||||
|
LLSDHelpers.DeserialiseLLSDMap(hash, llsdUpdateRequest);
|
||||||
|
|
||||||
|
string capsBase = "/CAPS/" + m_capsObjectPath;
|
||||||
|
string uploaderPath = Util.RandomClass.Next(5000, 8000).ToString("0000");
|
||||||
|
|
||||||
|
TaskInventoryScriptUpdater uploader =
|
||||||
|
new TaskInventoryScriptUpdater(
|
||||||
|
llsdUpdateRequest.item_id,
|
||||||
|
llsdUpdateRequest.task_id,
|
||||||
|
llsdUpdateRequest.is_script_running,
|
||||||
|
capsBase + uploaderPath,
|
||||||
|
m_httpListener,
|
||||||
|
m_dumpAssetsToFile);
|
||||||
|
uploader.OnUpLoad += TaskScriptUpdated;
|
||||||
|
|
||||||
|
m_httpListener.AddStreamHandler(
|
||||||
|
new BinaryStreamHandler("POST", capsBase + uploaderPath, uploader.uploaderCaps));
|
||||||
|
string uploaderURL = "http://" + m_httpListenerHostName + ":" + m_httpListenPort.ToString() + capsBase +
|
||||||
|
uploaderPath;
|
||||||
|
|
||||||
|
LLSDAssetUploadResponse uploadResponse = new LLSDAssetUploadResponse();
|
||||||
|
uploadResponse.uploader = uploaderURL;
|
||||||
|
uploadResponse.state = "upload";
|
||||||
|
|
||||||
|
// MainLog.Instance.Verbose(
|
||||||
|
// "CAPS",
|
||||||
|
// "ScriptTaskInventory response: {0}",
|
||||||
|
// LLSDHelpers.SerialiseLLSDReply(uploadResponse));
|
||||||
|
|
||||||
|
return LLSDHelpers.SerialiseLLSDReply(uploadResponse);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
MainLog.Instance.Error("CAPS", e.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Callback for a client request for an upload url for a notecard (or script)
|
||||||
|
/// agent inventory update
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="request"></param>
|
||||||
|
/// <param name="path"></param>
|
||||||
|
/// <param name="param"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public string NoteCardAgentInventory(string request, string path, string param)
|
||||||
|
{
|
||||||
|
//libsecondlife.StructuredData.LLSDMap hash = (libsecondlife.StructuredData.LLSDMap)libsecondlife.StructuredData.LLSDParser.DeserializeBinary(Helpers.StringToField(request));
|
||||||
|
Hashtable hash = (Hashtable) LLSD.LLSDDeserialize(Helpers.StringToField(request));
|
||||||
|
LLSDItemUpdate llsdRequest = new LLSDItemUpdate();
|
||||||
|
LLSDHelpers.DeserialiseLLSDMap(hash, llsdRequest);
|
||||||
|
|
||||||
|
string capsBase = "/CAPS/" + m_capsObjectPath;
|
||||||
|
string uploaderPath = Util.RandomClass.Next(5000, 8000).ToString("0000");
|
||||||
|
|
||||||
|
ItemUpdater uploader =
|
||||||
|
new ItemUpdater(llsdRequest.item_id, capsBase + uploaderPath, m_httpListener, m_dumpAssetsToFile);
|
||||||
|
uploader.OnUpLoad += ItemUpdated;
|
||||||
|
|
||||||
|
m_httpListener.AddStreamHandler(
|
||||||
|
new BinaryStreamHandler("POST", capsBase + uploaderPath, uploader.uploaderCaps));
|
||||||
|
string uploaderURL = "http://" + m_httpListenerHostName + ":" + m_httpListenPort.ToString() + capsBase +
|
||||||
|
uploaderPath;
|
||||||
|
|
||||||
|
LLSDAssetUploadResponse uploadResponse = new LLSDAssetUploadResponse();
|
||||||
|
uploadResponse.uploader = uploaderURL;
|
||||||
|
uploadResponse.state = "upload";
|
||||||
|
|
||||||
|
// MainLog.Instance.Verbose(
|
||||||
|
// "CAPS",
|
||||||
|
// "NoteCardAgentInventory response: {0}",
|
||||||
|
// LLSDHelpers.SerialiseLLSDReply(uploadResponse));
|
||||||
|
|
||||||
|
return LLSDHelpers.SerialiseLLSDReply(uploadResponse);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="llsdRequest"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public LLSDAssetUploadResponse NewAgentInventoryRequest(LLSDAssetUploadRequest llsdRequest)
|
||||||
|
{
|
||||||
|
//Console.WriteLine("asset upload request via CAPS" + llsdRequest.inventory_type +" , "+ llsdRequest.asset_type);
|
||||||
|
|
||||||
|
string assetName = llsdRequest.name;
|
||||||
|
string assetDes = llsdRequest.description;
|
||||||
|
string capsBase = "/CAPS/" + m_capsObjectPath;
|
||||||
|
LLUUID newAsset = LLUUID.Random();
|
||||||
|
LLUUID newInvItem = LLUUID.Random();
|
||||||
|
LLUUID parentFolder = llsdRequest.folder_id;
|
||||||
|
string uploaderPath = Util.RandomClass.Next(5000, 8000).ToString("0000");
|
||||||
|
|
||||||
|
// rex, modified for "replace assets" functionality
|
||||||
|
if (m_replaceAssets)
|
||||||
|
{
|
||||||
|
// Check for asset replace upload
|
||||||
|
sbyte assType = 0;
|
||||||
|
sbyte inType = 0;
|
||||||
|
ParseAssetAndInventoryType(llsdRequest.asset_type, llsdRequest.inventory_type, out assType, out inType);
|
||||||
|
LLUUID dupID = m_assetCache.ExistsAsset(assType, llsdRequest.name);
|
||||||
|
if (dupID != LLUUID.Zero)
|
||||||
|
{
|
||||||
|
// If duplicate (same name and same assettype) found, use old asset UUID
|
||||||
|
newAsset = dupID;
|
||||||
|
// If user already has this asset in inventory, create no item
|
||||||
|
if (CheckInventoryForAsset != null)
|
||||||
|
{
|
||||||
|
if (CheckInventoryForAsset(m_agentID, dupID))
|
||||||
|
newInvItem = LLUUID.Zero;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// rexend
|
||||||
|
|
||||||
|
AssetUploader uploader =
|
||||||
|
new AssetUploader(assetName, assetDes, newAsset, newInvItem, parentFolder, llsdRequest.inventory_type,
|
||||||
|
llsdRequest.asset_type, capsBase + uploaderPath, m_httpListener, m_dumpAssetsToFile);
|
||||||
|
m_httpListener.AddStreamHandler(
|
||||||
|
new BinaryStreamHandler("POST", capsBase + uploaderPath, uploader.uploaderCaps));
|
||||||
|
string uploaderURL = "http://" + m_httpListenerHostName + ":" + m_httpListenPort.ToString() + capsBase +
|
||||||
|
uploaderPath;
|
||||||
|
|
||||||
|
LLSDAssetUploadResponse uploadResponse = new LLSDAssetUploadResponse();
|
||||||
|
uploadResponse.uploader = uploaderURL;
|
||||||
|
uploadResponse.state = "upload";
|
||||||
|
uploader.OnUpLoad += UploadCompleteHandler;
|
||||||
|
return uploadResponse;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="assetID"></param>
|
||||||
|
/// <param name="inventoryItem"></param>
|
||||||
|
/// <param name="data"></param>
|
||||||
|
public void UploadCompleteHandler(string assetName, string assetDescription, LLUUID assetID,
|
||||||
|
LLUUID inventoryItem, LLUUID parentFolder, byte[] data, string inventoryType,
|
||||||
|
string assetType)
|
||||||
|
{
|
||||||
|
sbyte assType = 0;
|
||||||
|
sbyte inType = 0;
|
||||||
|
|
||||||
|
// rex, modified to use extracted method, because needed in multiple places
|
||||||
|
ParseAssetAndInventoryType(assetType, inventoryType, out assType, out inType);
|
||||||
|
|
||||||
|
AssetBase asset;
|
||||||
|
asset = new AssetBase();
|
||||||
|
asset.FullID = assetID;
|
||||||
|
asset.Type = assType;
|
||||||
|
asset.InvType = inType;
|
||||||
|
asset.Name = assetName;
|
||||||
|
asset.Data = data;
|
||||||
|
|
||||||
|
// rex, modified for "replace assets" functionality
|
||||||
|
bool replace = (m_assetCache.ExistsAsset(assetID));
|
||||||
|
if (replace)
|
||||||
|
{
|
||||||
|
m_assetCache.ReplaceAsset(asset);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_assetCache.AddAsset(asset);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (inventoryItem != LLUUID.Zero)
|
||||||
|
{
|
||||||
|
InventoryItemBase item = new InventoryItemBase();
|
||||||
|
item.avatarID = m_agentID;
|
||||||
|
item.creatorsID = m_agentID;
|
||||||
|
item.inventoryID = inventoryItem;
|
||||||
|
item.assetID = asset.FullID;
|
||||||
|
item.inventoryDescription = assetDescription;
|
||||||
|
item.inventoryName = assetName;
|
||||||
|
item.assetType = assType;
|
||||||
|
item.invType = inType;
|
||||||
|
item.parentFolderID = parentFolder;
|
||||||
|
item.inventoryCurrentPermissions = 2147483647;
|
||||||
|
item.inventoryNextPermissions = 2147483647;
|
||||||
|
|
||||||
|
if (AddNewInventoryItem != null)
|
||||||
|
{
|
||||||
|
AddNewInventoryItem(m_agentID, item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// rexend
|
||||||
|
}
|
||||||
|
|
||||||
|
// rex, new function (extracted method) with added Ogre asset support
|
||||||
|
private void ParseAssetAndInventoryType(string assetType, string inventoryType, out sbyte assType, out sbyte inType)
|
||||||
|
{
|
||||||
|
inType = 0;
|
||||||
|
assType = 0;
|
||||||
|
|
||||||
|
if (inventoryType == "sound")
|
||||||
|
{
|
||||||
|
inType = 1;
|
||||||
|
assType = 1;
|
||||||
|
}
|
||||||
|
else if (inventoryType == "animation")
|
||||||
|
{
|
||||||
|
inType = 19;
|
||||||
|
assType = 20;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (assetType == "ogremesh")
|
||||||
|
{
|
||||||
|
inType = 6;
|
||||||
|
assType = 43;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (assetType == "ogrepart")
|
||||||
|
{
|
||||||
|
inType = 41;
|
||||||
|
assType = 47;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Called when new asset data for an agent inventory item update has been uploaded.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="itemID">Item to update</param>
|
||||||
|
/// <param name="data">New asset data</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public LLUUID ItemUpdated(LLUUID itemID, byte[] data)
|
||||||
|
{
|
||||||
|
if (ItemUpdatedCall != null)
|
||||||
|
{
|
||||||
|
return ItemUpdatedCall(m_agentID, itemID, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
return LLUUID.Zero;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Called when new asset data for an agent inventory item update has been uploaded.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="itemID">Item to update</param>
|
||||||
|
/// <param name="primID">Prim containing item to update</param>
|
||||||
|
/// <param name="isScriptRunning">Signals whether the script to update is currently running</param>
|
||||||
|
/// <param name="data">New asset data</param>
|
||||||
|
public void TaskScriptUpdated(LLUUID itemID, LLUUID primID, bool isScriptRunning, byte[] data)
|
||||||
|
{
|
||||||
|
if (TaskScriptUpdatedCall != null)
|
||||||
|
{
|
||||||
|
TaskScriptUpdatedCall(m_agentID, itemID, primID, isScriptRunning, data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class AssetUploader
|
||||||
|
{
|
||||||
|
public event UpLoadedAsset OnUpLoad;
|
||||||
|
|
||||||
|
private string uploaderPath = "";
|
||||||
|
private LLUUID newAssetID;
|
||||||
|
private LLUUID inventoryItemID;
|
||||||
|
private LLUUID parentFolder;
|
||||||
|
private BaseHttpServer httpListener;
|
||||||
|
private bool m_dumpAssetsToFile;
|
||||||
|
private string m_assetName = "";
|
||||||
|
private string m_assetDes = "";
|
||||||
|
|
||||||
|
private string m_invType = "";
|
||||||
|
private string m_assetType = "";
|
||||||
|
|
||||||
|
public AssetUploader(string assetName, string description, LLUUID assetID, LLUUID inventoryItem,
|
||||||
|
LLUUID parentFolderID, string invType, string assetType, string path,
|
||||||
|
BaseHttpServer httpServer, bool dumpAssetsToFile)
|
||||||
|
{
|
||||||
|
m_assetName = assetName;
|
||||||
|
m_assetDes = description;
|
||||||
|
newAssetID = assetID;
|
||||||
|
inventoryItemID = inventoryItem;
|
||||||
|
uploaderPath = path;
|
||||||
|
httpListener = httpServer;
|
||||||
|
parentFolder = parentFolderID;
|
||||||
|
m_assetType = assetType;
|
||||||
|
m_invType = invType;
|
||||||
|
m_dumpAssetsToFile = dumpAssetsToFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="data"></param>
|
||||||
|
/// <param name="path"></param>
|
||||||
|
/// <param name="param"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public string uploaderCaps(byte[] data, string path, string param)
|
||||||
|
{
|
||||||
|
LLUUID inv = inventoryItemID;
|
||||||
|
string res = "";
|
||||||
|
LLSDAssetUploadComplete uploadComplete = new LLSDAssetUploadComplete();
|
||||||
|
uploadComplete.new_asset = newAssetID.ToString();
|
||||||
|
uploadComplete.new_inventory_item = inv;
|
||||||
|
uploadComplete.state = "complete";
|
||||||
|
|
||||||
|
res = LLSDHelpers.SerialiseLLSDReply(uploadComplete);
|
||||||
|
|
||||||
|
httpListener.RemoveStreamHandler("POST", uploaderPath);
|
||||||
|
|
||||||
|
if (m_dumpAssetsToFile)
|
||||||
|
{
|
||||||
|
SaveAssetToFile(m_assetName + ".jp2", data);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (OnUpLoad != null)
|
||||||
|
{
|
||||||
|
OnUpLoad(m_assetName, m_assetDes, newAssetID, inv, parentFolder, data, m_invType, m_assetType);
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
///Left this in and commented in case there are unforseen issues
|
||||||
|
//private void SaveAssetToFile(string filename, byte[] data)
|
||||||
|
//{
|
||||||
|
// FileStream fs = File.Create(filename);
|
||||||
|
// BinaryWriter bw = new BinaryWriter(fs);
|
||||||
|
// bw.Write(data);
|
||||||
|
// bw.Close();
|
||||||
|
// fs.Close();
|
||||||
|
//}
|
||||||
|
private void SaveAssetToFile(string filename, byte[] data)
|
||||||
|
{
|
||||||
|
string assetPath = "UserAssets";
|
||||||
|
if (!Directory.Exists(assetPath))
|
||||||
|
{
|
||||||
|
Directory.CreateDirectory(assetPath);
|
||||||
|
}
|
||||||
|
FileStream fs = File.Create(Path.Combine(assetPath, filename));
|
||||||
|
BinaryWriter bw = new BinaryWriter(fs);
|
||||||
|
bw.Write(data);
|
||||||
|
bw.Close();
|
||||||
|
fs.Close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// This class is a callback invoked when a client sends asset data to
|
||||||
|
/// an agent inventory notecard update url
|
||||||
|
/// </summary>
|
||||||
|
public class ItemUpdater
|
||||||
|
{
|
||||||
|
public event UpdateItem OnUpLoad;
|
||||||
|
|
||||||
|
private string uploaderPath = "";
|
||||||
|
private LLUUID inventoryItemID;
|
||||||
|
private BaseHttpServer httpListener;
|
||||||
|
private bool m_dumpAssetToFile;
|
||||||
|
|
||||||
|
public ItemUpdater(LLUUID inventoryItem, string path, BaseHttpServer httpServer, bool dumpAssetToFile)
|
||||||
|
{
|
||||||
|
m_dumpAssetToFile = dumpAssetToFile;
|
||||||
|
|
||||||
|
inventoryItemID = inventoryItem;
|
||||||
|
uploaderPath = path;
|
||||||
|
httpListener = httpServer;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="data"></param>
|
||||||
|
/// <param name="path"></param>
|
||||||
|
/// <param name="param"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public string uploaderCaps(byte[] data, string path, string param)
|
||||||
|
{
|
||||||
|
LLUUID inv = inventoryItemID;
|
||||||
|
string res = "";
|
||||||
|
LLSDAssetUploadComplete uploadComplete = new LLSDAssetUploadComplete();
|
||||||
|
LLUUID assetID = LLUUID.Zero;
|
||||||
|
|
||||||
|
if (OnUpLoad != null)
|
||||||
|
{
|
||||||
|
assetID = OnUpLoad(inv, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
uploadComplete.new_asset = assetID.ToString();
|
||||||
|
uploadComplete.new_inventory_item = inv;
|
||||||
|
uploadComplete.state = "complete";
|
||||||
|
|
||||||
|
res = LLSDHelpers.SerialiseLLSDReply(uploadComplete);
|
||||||
|
|
||||||
|
httpListener.RemoveStreamHandler("POST", uploaderPath);
|
||||||
|
|
||||||
|
if (m_dumpAssetToFile)
|
||||||
|
{
|
||||||
|
SaveAssetToFile("updateditem" + Util.RandomClass.Next(1, 1000) + ".dat", data);
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
///Left this in and commented in case there are unforseen issues
|
||||||
|
//private void SaveAssetToFile(string filename, byte[] data)
|
||||||
|
//{
|
||||||
|
// FileStream fs = File.Create(filename);
|
||||||
|
// BinaryWriter bw = new BinaryWriter(fs);
|
||||||
|
// bw.Write(data);
|
||||||
|
// bw.Close();
|
||||||
|
// fs.Close();
|
||||||
|
//}
|
||||||
|
private void SaveAssetToFile(string filename, byte[] data)
|
||||||
|
{
|
||||||
|
string assetPath = "UserAssets";
|
||||||
|
if (!Directory.Exists(assetPath))
|
||||||
|
{
|
||||||
|
Directory.CreateDirectory(assetPath);
|
||||||
|
}
|
||||||
|
FileStream fs = File.Create(Path.Combine(assetPath, filename));
|
||||||
|
BinaryWriter bw = new BinaryWriter(fs);
|
||||||
|
bw.Write(data);
|
||||||
|
bw.Close();
|
||||||
|
fs.Close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// This class is a callback invoked when a client sends asset data to
|
||||||
|
/// a task inventory script update url
|
||||||
|
/// </summary>
|
||||||
|
public class TaskInventoryScriptUpdater
|
||||||
|
{
|
||||||
|
public event UpdateTaskScript OnUpLoad;
|
||||||
|
|
||||||
|
private string uploaderPath = "";
|
||||||
|
private LLUUID inventoryItemID;
|
||||||
|
private LLUUID primID;
|
||||||
|
private bool isScriptRunning;
|
||||||
|
private BaseHttpServer httpListener;
|
||||||
|
private bool m_dumpAssetToFile;
|
||||||
|
|
||||||
|
public TaskInventoryScriptUpdater(LLUUID inventoryItemID, LLUUID primID, int isScriptRunning,
|
||||||
|
string path, BaseHttpServer httpServer, bool dumpAssetToFile)
|
||||||
|
{
|
||||||
|
m_dumpAssetToFile = dumpAssetToFile;
|
||||||
|
|
||||||
|
this.inventoryItemID = inventoryItemID;
|
||||||
|
this.primID = primID;
|
||||||
|
|
||||||
|
// This comes in over the packet as an integer, but actually appears to be treated as a bool
|
||||||
|
this.isScriptRunning = (0 == isScriptRunning ? false : true);
|
||||||
|
|
||||||
|
uploaderPath = path;
|
||||||
|
httpListener = httpServer;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="data"></param>
|
||||||
|
/// <param name="path"></param>
|
||||||
|
/// <param name="param"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public string uploaderCaps(byte[] data, string path, string param)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// MainLog.Instance.Verbose(
|
||||||
|
// "CAPS",
|
||||||
|
// "TaskInventoryScriptUpdater received data: {0}, path: {1}, param: {2}",
|
||||||
|
// data, path, param);
|
||||||
|
|
||||||
|
string res = "";
|
||||||
|
LLSDTaskInventoryUploadComplete uploadComplete = new LLSDTaskInventoryUploadComplete();
|
||||||
|
|
||||||
|
if (OnUpLoad != null)
|
||||||
|
{
|
||||||
|
OnUpLoad(inventoryItemID, primID, isScriptRunning, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
uploadComplete.item_id = inventoryItemID;
|
||||||
|
uploadComplete.task_id = primID;
|
||||||
|
uploadComplete.state = "complete";
|
||||||
|
|
||||||
|
res = LLSDHelpers.SerialiseLLSDReply(uploadComplete);
|
||||||
|
|
||||||
|
httpListener.RemoveStreamHandler("POST", uploaderPath);
|
||||||
|
|
||||||
|
if (m_dumpAssetToFile)
|
||||||
|
{
|
||||||
|
SaveAssetToFile("updatedtaskscript" + Util.RandomClass.Next(1, 1000) + ".dat", data);
|
||||||
|
}
|
||||||
|
|
||||||
|
// MainLog.Instance.Verbose("CAPS", "TaskInventoryScriptUpdater.uploaderCaps res: {0}", res);
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
MainLog.Instance.Error("CAPS", e.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
// XXX Maybe this should be some meaningful error packet
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
///Left this in and commented in case there are unforseen issues
|
||||||
|
//private void SaveAssetToFile(string filename, byte[] data)
|
||||||
|
//{
|
||||||
|
// FileStream fs = File.Create(filename);
|
||||||
|
// BinaryWriter bw = new BinaryWriter(fs);
|
||||||
|
// bw.Write(data);
|
||||||
|
// bw.Close();
|
||||||
|
// fs.Close();
|
||||||
|
//}
|
||||||
|
private void SaveAssetToFile(string filename, byte[] data)
|
||||||
|
{
|
||||||
|
string assetPath = "UserAssets";
|
||||||
|
if (!Directory.Exists(assetPath))
|
||||||
|
{
|
||||||
|
Directory.CreateDirectory(assetPath);
|
||||||
|
}
|
||||||
|
FileStream fs = File.Create(Path.Combine(assetPath, filename));
|
||||||
|
BinaryWriter bw = new BinaryWriter(fs);
|
||||||
|
bw.Write(data);
|
||||||
|
bw.Close();
|
||||||
|
fs.Close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,680 @@
|
||||||
|
/*
|
||||||
|
* 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 OpenSim Project nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
||||||
|
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Globalization;
|
||||||
|
using System.IO;
|
||||||
|
using System.Security.Cryptography;
|
||||||
|
using System.Text;
|
||||||
|
using System.Xml;
|
||||||
|
using libsecondlife;
|
||||||
|
|
||||||
|
namespace OpenSim.Region.Capabilities
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Borrowed from (a older version of ) libsl for now, as their new llsd code doesn't work we our decoding code.
|
||||||
|
/// </summary>
|
||||||
|
public static class LLSD
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
public class LLSDParseException : Exception
|
||||||
|
{
|
||||||
|
public LLSDParseException(string message) : base(message)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
public class LLSDSerializeException : Exception
|
||||||
|
{
|
||||||
|
public LLSDSerializeException(string message) : base(message)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="b"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static object LLSDDeserialize(byte[] b)
|
||||||
|
{
|
||||||
|
return LLSDDeserialize(new MemoryStream(b, false));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="st"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static object LLSDDeserialize(Stream st)
|
||||||
|
{
|
||||||
|
XmlTextReader reader = new XmlTextReader(st);
|
||||||
|
reader.Read();
|
||||||
|
SkipWS(reader);
|
||||||
|
|
||||||
|
if (reader.NodeType != XmlNodeType.Element || reader.LocalName != "llsd")
|
||||||
|
throw new LLSDParseException("Expected <llsd>");
|
||||||
|
|
||||||
|
reader.Read();
|
||||||
|
object ret = LLSDParseOne(reader);
|
||||||
|
SkipWS(reader);
|
||||||
|
|
||||||
|
if (reader.NodeType != XmlNodeType.EndElement || reader.LocalName != "llsd")
|
||||||
|
throw new LLSDParseException("Expected </llsd>");
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="obj"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static byte[] LLSDSerialize(object obj)
|
||||||
|
{
|
||||||
|
StringWriter sw = new StringWriter();
|
||||||
|
XmlTextWriter writer = new XmlTextWriter(sw);
|
||||||
|
writer.Formatting = Formatting.None;
|
||||||
|
|
||||||
|
writer.WriteStartElement(String.Empty, "llsd", String.Empty);
|
||||||
|
LLSDWriteOne(writer, obj);
|
||||||
|
writer.WriteEndElement();
|
||||||
|
|
||||||
|
writer.Close();
|
||||||
|
|
||||||
|
return Encoding.UTF8.GetBytes(sw.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="writer"></param>
|
||||||
|
/// <param name="obj"></param>
|
||||||
|
public static void LLSDWriteOne(XmlTextWriter writer, object obj)
|
||||||
|
{
|
||||||
|
if (obj == null)
|
||||||
|
{
|
||||||
|
writer.WriteStartElement(String.Empty, "undef", String.Empty);
|
||||||
|
writer.WriteEndElement();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (obj is string)
|
||||||
|
{
|
||||||
|
writer.WriteStartElement(String.Empty, "string", String.Empty);
|
||||||
|
writer.WriteString((string) obj);
|
||||||
|
writer.WriteEndElement();
|
||||||
|
}
|
||||||
|
else if (obj is int)
|
||||||
|
{
|
||||||
|
writer.WriteStartElement(String.Empty, "integer", String.Empty);
|
||||||
|
writer.WriteString(obj.ToString());
|
||||||
|
writer.WriteEndElement();
|
||||||
|
}
|
||||||
|
else if (obj is double)
|
||||||
|
{
|
||||||
|
writer.WriteStartElement(String.Empty, "real", String.Empty);
|
||||||
|
writer.WriteString(obj.ToString());
|
||||||
|
writer.WriteEndElement();
|
||||||
|
}
|
||||||
|
else if (obj is bool)
|
||||||
|
{
|
||||||
|
bool b = (bool) obj;
|
||||||
|
writer.WriteStartElement(String.Empty, "boolean", String.Empty);
|
||||||
|
writer.WriteString(b ? "1" : "0");
|
||||||
|
writer.WriteEndElement();
|
||||||
|
}
|
||||||
|
else if (obj is ulong)
|
||||||
|
{
|
||||||
|
throw new Exception("ulong in LLSD is currently not implemented, fix me!");
|
||||||
|
}
|
||||||
|
else if (obj is LLUUID)
|
||||||
|
{
|
||||||
|
LLUUID u = (LLUUID) obj;
|
||||||
|
writer.WriteStartElement(String.Empty, "uuid", String.Empty);
|
||||||
|
writer.WriteString(u.ToString());
|
||||||
|
writer.WriteEndElement();
|
||||||
|
}
|
||||||
|
else if (obj is Hashtable)
|
||||||
|
{
|
||||||
|
Hashtable h = obj as Hashtable;
|
||||||
|
writer.WriteStartElement(String.Empty, "map", String.Empty);
|
||||||
|
foreach (string key in h.Keys)
|
||||||
|
{
|
||||||
|
writer.WriteStartElement(String.Empty, "key", String.Empty);
|
||||||
|
writer.WriteString(key);
|
||||||
|
writer.WriteEndElement();
|
||||||
|
LLSDWriteOne(writer, h[key]);
|
||||||
|
}
|
||||||
|
writer.WriteEndElement();
|
||||||
|
}
|
||||||
|
else if (obj is ArrayList)
|
||||||
|
{
|
||||||
|
ArrayList a = obj as ArrayList;
|
||||||
|
writer.WriteStartElement(String.Empty, "array", String.Empty);
|
||||||
|
foreach (object item in a)
|
||||||
|
{
|
||||||
|
LLSDWriteOne(writer, item);
|
||||||
|
}
|
||||||
|
writer.WriteEndElement();
|
||||||
|
}
|
||||||
|
else if (obj is byte[])
|
||||||
|
{
|
||||||
|
byte[] b = obj as byte[];
|
||||||
|
writer.WriteStartElement(String.Empty, "binary", String.Empty);
|
||||||
|
|
||||||
|
writer.WriteStartAttribute(String.Empty, "encoding", String.Empty);
|
||||||
|
writer.WriteString("base64");
|
||||||
|
writer.WriteEndAttribute();
|
||||||
|
|
||||||
|
//// Calculate the length of the base64 output
|
||||||
|
//long length = (long)(4.0d * b.Length / 3.0d);
|
||||||
|
//if (length % 4 != 0) length += 4 - (length % 4);
|
||||||
|
|
||||||
|
//// Create the char[] for base64 output and fill it
|
||||||
|
//char[] tmp = new char[length];
|
||||||
|
//int i = Convert.ToBase64CharArray(b, 0, b.Length, tmp, 0);
|
||||||
|
|
||||||
|
//writer.WriteString(new String(tmp));
|
||||||
|
|
||||||
|
writer.WriteString(Convert.ToBase64String(b));
|
||||||
|
writer.WriteEndElement();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new LLSDSerializeException("Unknown type " + obj.GetType().Name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="reader"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static object LLSDParseOne(XmlTextReader reader)
|
||||||
|
{
|
||||||
|
SkipWS(reader);
|
||||||
|
if (reader.NodeType != XmlNodeType.Element)
|
||||||
|
throw new LLSDParseException("Expected an element");
|
||||||
|
|
||||||
|
string dtype = reader.LocalName;
|
||||||
|
object ret = null;
|
||||||
|
|
||||||
|
switch (dtype)
|
||||||
|
{
|
||||||
|
case "undef":
|
||||||
|
{
|
||||||
|
if (reader.IsEmptyElement)
|
||||||
|
{
|
||||||
|
reader.Read();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
reader.Read();
|
||||||
|
SkipWS(reader);
|
||||||
|
ret = null;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case "boolean":
|
||||||
|
{
|
||||||
|
if (reader.IsEmptyElement)
|
||||||
|
{
|
||||||
|
reader.Read();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
reader.Read();
|
||||||
|
string s = reader.ReadString().Trim();
|
||||||
|
|
||||||
|
if (s == String.Empty || s == "false" || s == "0")
|
||||||
|
ret = false;
|
||||||
|
else if (s == "true" || s == "1")
|
||||||
|
ret = true;
|
||||||
|
else
|
||||||
|
throw new LLSDParseException("Bad boolean value " + s);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case "integer":
|
||||||
|
{
|
||||||
|
if (reader.IsEmptyElement)
|
||||||
|
{
|
||||||
|
reader.Read();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
reader.Read();
|
||||||
|
ret = Convert.ToInt32(reader.ReadString().Trim());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case "real":
|
||||||
|
{
|
||||||
|
if (reader.IsEmptyElement)
|
||||||
|
{
|
||||||
|
reader.Read();
|
||||||
|
return 0.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
reader.Read();
|
||||||
|
ret = Convert.ToDouble(reader.ReadString().Trim());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case "uuid":
|
||||||
|
{
|
||||||
|
if (reader.IsEmptyElement)
|
||||||
|
{
|
||||||
|
reader.Read();
|
||||||
|
return LLUUID.Zero;
|
||||||
|
}
|
||||||
|
|
||||||
|
reader.Read();
|
||||||
|
ret = new LLUUID(reader.ReadString().Trim());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case "string":
|
||||||
|
{
|
||||||
|
if (reader.IsEmptyElement)
|
||||||
|
{
|
||||||
|
reader.Read();
|
||||||
|
return String.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
reader.Read();
|
||||||
|
ret = reader.ReadString();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case "binary":
|
||||||
|
{
|
||||||
|
if (reader.IsEmptyElement)
|
||||||
|
{
|
||||||
|
reader.Read();
|
||||||
|
return new byte[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (reader.GetAttribute("encoding") != null &&
|
||||||
|
reader.GetAttribute("encoding") != "base64")
|
||||||
|
{
|
||||||
|
throw new LLSDParseException("Unknown encoding: " + reader.GetAttribute("encoding"));
|
||||||
|
}
|
||||||
|
|
||||||
|
reader.Read();
|
||||||
|
FromBase64Transform b64 = new FromBase64Transform(FromBase64TransformMode.IgnoreWhiteSpaces);
|
||||||
|
byte[] inp = Encoding.ASCII.GetBytes(reader.ReadString());
|
||||||
|
ret = b64.TransformFinalBlock(inp, 0, inp.Length);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case "date":
|
||||||
|
{
|
||||||
|
reader.Read();
|
||||||
|
throw new Exception("LLSD TODO: date");
|
||||||
|
}
|
||||||
|
case "map":
|
||||||
|
{
|
||||||
|
return LLSDParseMap(reader);
|
||||||
|
}
|
||||||
|
case "array":
|
||||||
|
{
|
||||||
|
return LLSDParseArray(reader);
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
throw new LLSDParseException("Unknown element <" + dtype + ">");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (reader.NodeType != XmlNodeType.EndElement || reader.LocalName != dtype)
|
||||||
|
{
|
||||||
|
throw new LLSDParseException("Expected </" + dtype + ">");
|
||||||
|
}
|
||||||
|
|
||||||
|
reader.Read();
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="reader"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static Hashtable LLSDParseMap(XmlTextReader reader)
|
||||||
|
{
|
||||||
|
Hashtable ret = new Hashtable();
|
||||||
|
|
||||||
|
if (reader.NodeType != XmlNodeType.Element || reader.LocalName != "map")
|
||||||
|
throw new LLSDParseException("Expected <map>");
|
||||||
|
|
||||||
|
if (reader.IsEmptyElement)
|
||||||
|
{
|
||||||
|
reader.Read();
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
reader.Read();
|
||||||
|
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
SkipWS(reader);
|
||||||
|
if (reader.NodeType == XmlNodeType.EndElement && reader.LocalName == "map")
|
||||||
|
{
|
||||||
|
reader.Read();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (reader.NodeType != XmlNodeType.Element || reader.LocalName != "key")
|
||||||
|
throw new LLSDParseException("Expected <key>");
|
||||||
|
|
||||||
|
string key = reader.ReadString();
|
||||||
|
|
||||||
|
if (reader.NodeType != XmlNodeType.EndElement || reader.LocalName != "key")
|
||||||
|
throw new LLSDParseException("Expected </key>");
|
||||||
|
|
||||||
|
reader.Read();
|
||||||
|
object val = LLSDParseOne(reader);
|
||||||
|
ret[key] = val;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret; // TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="reader"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static ArrayList LLSDParseArray(XmlTextReader reader)
|
||||||
|
{
|
||||||
|
ArrayList ret = new ArrayList();
|
||||||
|
|
||||||
|
if (reader.NodeType != XmlNodeType.Element || reader.LocalName != "array")
|
||||||
|
throw new LLSDParseException("Expected <array>");
|
||||||
|
|
||||||
|
if (reader.IsEmptyElement)
|
||||||
|
{
|
||||||
|
reader.Read();
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
reader.Read();
|
||||||
|
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
SkipWS(reader);
|
||||||
|
|
||||||
|
if (reader.NodeType == XmlNodeType.EndElement && reader.LocalName == "array")
|
||||||
|
{
|
||||||
|
reader.Read();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret.Insert(ret.Count, LLSDParseOne(reader));
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret; // TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="count"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
private static string GetSpaces(int count)
|
||||||
|
{
|
||||||
|
StringBuilder b = new StringBuilder();
|
||||||
|
for (int i = 0; i < count; i++) b.Append(" ");
|
||||||
|
return b.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="obj"></param>
|
||||||
|
/// <param name="indent"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static String LLSDDump(object obj, int indent)
|
||||||
|
{
|
||||||
|
if (obj == null)
|
||||||
|
{
|
||||||
|
return GetSpaces(indent) + "- undef\n";
|
||||||
|
}
|
||||||
|
else if (obj is string)
|
||||||
|
{
|
||||||
|
return GetSpaces(indent) + "- string \"" + (string) obj + "\"\n";
|
||||||
|
}
|
||||||
|
else if (obj is int)
|
||||||
|
{
|
||||||
|
return GetSpaces(indent) + "- integer " + obj.ToString() + "\n";
|
||||||
|
}
|
||||||
|
else if (obj is double)
|
||||||
|
{
|
||||||
|
return GetSpaces(indent) + "- float " + obj.ToString() + "\n";
|
||||||
|
}
|
||||||
|
else if (obj is LLUUID)
|
||||||
|
{
|
||||||
|
return GetSpaces(indent) + "- uuid " + ((LLUUID) obj).ToString() + Environment.NewLine;
|
||||||
|
}
|
||||||
|
else if (obj is Hashtable)
|
||||||
|
{
|
||||||
|
StringBuilder ret = new StringBuilder();
|
||||||
|
ret.Append(GetSpaces(indent) + "- map" + Environment.NewLine);
|
||||||
|
Hashtable map = (Hashtable) obj;
|
||||||
|
|
||||||
|
foreach (string key in map.Keys)
|
||||||
|
{
|
||||||
|
ret.Append(GetSpaces(indent + 2) + "- key \"" + key + "\"" + Environment.NewLine);
|
||||||
|
ret.Append(LLSDDump(map[key], indent + 3));
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret.ToString();
|
||||||
|
}
|
||||||
|
else if (obj is ArrayList)
|
||||||
|
{
|
||||||
|
StringBuilder ret = new StringBuilder();
|
||||||
|
ret.Append(GetSpaces(indent) + "- array\n");
|
||||||
|
ArrayList list = (ArrayList) obj;
|
||||||
|
|
||||||
|
foreach (object item in list)
|
||||||
|
{
|
||||||
|
ret.Append(LLSDDump(item, indent + 2));
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret.ToString();
|
||||||
|
}
|
||||||
|
else if (obj is byte[])
|
||||||
|
{
|
||||||
|
return GetSpaces(indent) + "- binary\n" + Helpers.FieldToHexString((byte[]) obj, GetSpaces(indent)) +
|
||||||
|
Environment.NewLine;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return GetSpaces(indent) + "- unknown type " + obj.GetType().Name + Environment.NewLine;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static object ParseTerseLLSD(string llsd)
|
||||||
|
{
|
||||||
|
int notused;
|
||||||
|
return ParseTerseLLSD(llsd, out notused);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static object ParseTerseLLSD(string llsd, out int endPos)
|
||||||
|
{
|
||||||
|
if (llsd.Length == 0)
|
||||||
|
{
|
||||||
|
endPos = 0;
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Identify what type of object this is
|
||||||
|
switch (llsd[0])
|
||||||
|
{
|
||||||
|
case '!':
|
||||||
|
throw new LLSDParseException("Undefined value type encountered");
|
||||||
|
case '1':
|
||||||
|
endPos = 1;
|
||||||
|
return true;
|
||||||
|
case '0':
|
||||||
|
endPos = 1;
|
||||||
|
return false;
|
||||||
|
case 'i':
|
||||||
|
{
|
||||||
|
if (llsd.Length < 2) throw new LLSDParseException("Integer value type with no value");
|
||||||
|
int value;
|
||||||
|
endPos = FindEnd(llsd, 1);
|
||||||
|
|
||||||
|
if (Int32.TryParse(llsd.Substring(1, endPos - 1), out value))
|
||||||
|
return value;
|
||||||
|
else
|
||||||
|
throw new LLSDParseException("Failed to parse integer value type");
|
||||||
|
}
|
||||||
|
case 'r':
|
||||||
|
{
|
||||||
|
if (llsd.Length < 2) throw new LLSDParseException("Real value type with no value");
|
||||||
|
double value;
|
||||||
|
endPos = FindEnd(llsd, 1);
|
||||||
|
|
||||||
|
if (Double.TryParse(llsd.Substring(1, endPos - 1), NumberStyles.Float,
|
||||||
|
Helpers.EnUsCulture.NumberFormat, out value))
|
||||||
|
return value;
|
||||||
|
else
|
||||||
|
throw new LLSDParseException("Failed to parse double value type");
|
||||||
|
}
|
||||||
|
case 'u':
|
||||||
|
{
|
||||||
|
if (llsd.Length < 17) throw new LLSDParseException("LLUUID value type with no value");
|
||||||
|
LLUUID value;
|
||||||
|
endPos = FindEnd(llsd, 1);
|
||||||
|
|
||||||
|
if (LLUUID.TryParse(llsd.Substring(1, endPos - 1), out value))
|
||||||
|
return value;
|
||||||
|
else
|
||||||
|
throw new LLSDParseException("Failed to parse LLUUID value type");
|
||||||
|
}
|
||||||
|
case 'b':
|
||||||
|
//byte[] value = new byte[llsd.Length - 1];
|
||||||
|
// This isn't the actual binary LLSD format, just the terse format sent
|
||||||
|
// at login so I don't even know if there is a binary type
|
||||||
|
throw new LLSDParseException("Binary value type is unimplemented");
|
||||||
|
case 's':
|
||||||
|
case 'l':
|
||||||
|
if (llsd.Length < 2) throw new LLSDParseException("String value type with no value");
|
||||||
|
endPos = FindEnd(llsd, 1);
|
||||||
|
return llsd.Substring(1, endPos - 1);
|
||||||
|
case 'd':
|
||||||
|
// Never seen one before, don't know what the format is
|
||||||
|
throw new LLSDParseException("Date value type is unimplemented");
|
||||||
|
case '[':
|
||||||
|
{
|
||||||
|
if (llsd.IndexOf(']') == -1) throw new LLSDParseException("Invalid array");
|
||||||
|
|
||||||
|
int pos = 0;
|
||||||
|
ArrayList array = new ArrayList();
|
||||||
|
|
||||||
|
while (llsd[pos] != ']')
|
||||||
|
{
|
||||||
|
++pos;
|
||||||
|
|
||||||
|
// Advance past comma if need be
|
||||||
|
if (llsd[pos] == ',') ++pos;
|
||||||
|
|
||||||
|
// Allow a single whitespace character
|
||||||
|
if (pos < llsd.Length && llsd[pos] == ' ') ++pos;
|
||||||
|
|
||||||
|
int end;
|
||||||
|
array.Add(ParseTerseLLSD(llsd.Substring(pos), out end));
|
||||||
|
pos += end;
|
||||||
|
}
|
||||||
|
|
||||||
|
endPos = pos + 1;
|
||||||
|
return array;
|
||||||
|
}
|
||||||
|
case '{':
|
||||||
|
{
|
||||||
|
if (llsd.IndexOf('}') == -1) throw new LLSDParseException("Invalid map");
|
||||||
|
|
||||||
|
int pos = 0;
|
||||||
|
Hashtable hashtable = new Hashtable();
|
||||||
|
|
||||||
|
while (llsd[pos] != '}')
|
||||||
|
{
|
||||||
|
++pos;
|
||||||
|
|
||||||
|
// Advance past comma if need be
|
||||||
|
if (llsd[pos] == ',') ++pos;
|
||||||
|
|
||||||
|
// Allow a single whitespace character
|
||||||
|
if (pos < llsd.Length && llsd[pos] == ' ') ++pos;
|
||||||
|
|
||||||
|
if (llsd[pos] != '\'') throw new LLSDParseException("Expected a map key");
|
||||||
|
int endquote = llsd.IndexOf('\'', pos + 1);
|
||||||
|
if (endquote == -1 || (endquote + 1) >= llsd.Length || llsd[endquote + 1] != ':')
|
||||||
|
throw new LLSDParseException("Invalid map format");
|
||||||
|
string key = llsd.Substring(pos, endquote - pos);
|
||||||
|
key = key.Replace("'", String.Empty);
|
||||||
|
pos += (endquote - pos) + 2;
|
||||||
|
|
||||||
|
int end;
|
||||||
|
hashtable.Add(key, ParseTerseLLSD(llsd.Substring(pos), out end));
|
||||||
|
pos += end;
|
||||||
|
}
|
||||||
|
|
||||||
|
endPos = pos + 1;
|
||||||
|
return hashtable;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
throw new Exception("Unknown value type");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int FindEnd(string llsd, int start)
|
||||||
|
{
|
||||||
|
int end = llsd.IndexOfAny(new char[] {',', ']', '}'});
|
||||||
|
if (end == -1) end = llsd.Length - 1;
|
||||||
|
return end;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="reader"></param>
|
||||||
|
private static void SkipWS(XmlTextReader reader)
|
||||||
|
{
|
||||||
|
while (
|
||||||
|
reader.NodeType == XmlNodeType.Comment ||
|
||||||
|
reader.NodeType == XmlNodeType.Whitespace ||
|
||||||
|
reader.NodeType == XmlNodeType.SignificantWhitespace ||
|
||||||
|
reader.NodeType == XmlNodeType.XmlDeclaration)
|
||||||
|
{
|
||||||
|
reader.Read();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,41 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) Contributors, http://opensimulator.org/
|
||||||
|
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of the OpenSim 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.Region.Capabilities
|
||||||
|
{
|
||||||
|
[LLSDType("ARRAY")]
|
||||||
|
public class LLSDArray
|
||||||
|
{
|
||||||
|
public ArrayList Array = new ArrayList();
|
||||||
|
|
||||||
|
public LLSDArray()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,44 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) Contributors, http://opensimulator.org/
|
||||||
|
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of the OpenSim 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 libsecondlife;
|
||||||
|
|
||||||
|
namespace OpenSim.Region.Capabilities
|
||||||
|
{
|
||||||
|
[LLSDType("MAP")]
|
||||||
|
public class LLSDAssetUploadComplete
|
||||||
|
{
|
||||||
|
public string new_asset = "";
|
||||||
|
public LLUUID new_inventory_item = LLUUID.Zero;
|
||||||
|
public string state = "";
|
||||||
|
//public bool success = false;
|
||||||
|
|
||||||
|
public LLSDAssetUploadComplete()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,46 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) Contributors, http://opensimulator.org/
|
||||||
|
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of the OpenSim 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 libsecondlife;
|
||||||
|
|
||||||
|
namespace OpenSim.Region.Capabilities
|
||||||
|
{
|
||||||
|
[LLSDMap]
|
||||||
|
public class LLSDAssetUploadRequest
|
||||||
|
{
|
||||||
|
public string asset_type = "";
|
||||||
|
public string description = "";
|
||||||
|
public LLUUID folder_id = LLUUID.Zero;
|
||||||
|
public string inventory_type = "";
|
||||||
|
public string name = "";
|
||||||
|
|
||||||
|
public LLSDAssetUploadRequest()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,41 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) Contributors, http://opensimulator.org/
|
||||||
|
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of the OpenSim 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.Region.Capabilities
|
||||||
|
{
|
||||||
|
[LLSDMap]
|
||||||
|
public class LLSDAssetUploadResponse
|
||||||
|
{
|
||||||
|
public string uploader = "";
|
||||||
|
public string state = "";
|
||||||
|
|
||||||
|
public LLSDAssetUploadResponse()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,40 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) Contributors, http://opensimulator.org/
|
||||||
|
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of the OpenSim 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.Region.Capabilities
|
||||||
|
{
|
||||||
|
[LLSDType("MAP")]
|
||||||
|
public class LLSDCapEvent
|
||||||
|
{
|
||||||
|
public int id = 0;
|
||||||
|
public LLSDArray events = new LLSDArray();
|
||||||
|
|
||||||
|
public LLSDCapEvent()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,48 @@
|
||||||
|
/*
|
||||||
|
* 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 OpenSim 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.Region.Capabilities
|
||||||
|
{
|
||||||
|
[LLSDType("MAP")]
|
||||||
|
public class LLSDCapsDetails
|
||||||
|
{
|
||||||
|
public string MapLayer = "";
|
||||||
|
public string NewFileAgentInventory = "";
|
||||||
|
//public string EventQueueGet = "";
|
||||||
|
// public string RequestTextureDownload = "";
|
||||||
|
// public string ChatSessionRequest = "";
|
||||||
|
public string UpdateNotecardAgentInventory = "";
|
||||||
|
public string UpdateScriptAgentInventory = "";
|
||||||
|
public string UpdateScriptTaskInventory = "";
|
||||||
|
// public string ParcelVoiceInfoRequest = "";
|
||||||
|
|
||||||
|
public LLSDCapsDetails()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,37 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) Contributors, http://opensimulator.org/
|
||||||
|
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of the OpenSim 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.Region.Capabilities
|
||||||
|
{
|
||||||
|
[LLSDType("MAP")]
|
||||||
|
public class LLSDEmpty
|
||||||
|
{
|
||||||
|
public LLSDEmpty()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,151 @@
|
||||||
|
/*
|
||||||
|
* 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 OpenSim Project nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
||||||
|
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
using System;
|
||||||
|
using System.Collections;
|
||||||
|
using System.IO;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Xml;
|
||||||
|
|
||||||
|
namespace OpenSim.Region.Capabilities
|
||||||
|
{
|
||||||
|
public class LLSDHelpers
|
||||||
|
{
|
||||||
|
public static string SerialiseLLSDReply(object obj)
|
||||||
|
{
|
||||||
|
StringWriter sw = new StringWriter();
|
||||||
|
XmlTextWriter writer = new XmlTextWriter(sw);
|
||||||
|
writer.Formatting = Formatting.None;
|
||||||
|
writer.WriteStartElement(String.Empty, "llsd", String.Empty);
|
||||||
|
SerializeLLSDType(writer, obj);
|
||||||
|
writer.WriteEndElement();
|
||||||
|
writer.Close();
|
||||||
|
return sw.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void SerializeLLSDType(XmlTextWriter writer, object obj)
|
||||||
|
{
|
||||||
|
Type myType = obj.GetType();
|
||||||
|
LLSDType[] llsdattributes = (LLSDType[]) myType.GetCustomAttributes(typeof (LLSDType), false);
|
||||||
|
if (llsdattributes.Length > 0)
|
||||||
|
{
|
||||||
|
switch (llsdattributes[0].ObjectType)
|
||||||
|
{
|
||||||
|
case "MAP":
|
||||||
|
writer.WriteStartElement(String.Empty, "map", String.Empty);
|
||||||
|
FieldInfo[] fields = myType.GetFields();
|
||||||
|
for (int i = 0; i < fields.Length; i++)
|
||||||
|
{
|
||||||
|
object fieldValue = fields[i].GetValue(obj);
|
||||||
|
LLSDType[] fieldAttributes =
|
||||||
|
(LLSDType[]) fieldValue.GetType().GetCustomAttributes(typeof (LLSDType), false);
|
||||||
|
if (fieldAttributes.Length > 0)
|
||||||
|
{
|
||||||
|
writer.WriteStartElement(String.Empty, "key", String.Empty);
|
||||||
|
writer.WriteString(fields[i].Name);
|
||||||
|
writer.WriteEndElement();
|
||||||
|
SerializeLLSDType(writer, fieldValue);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
writer.WriteStartElement(String.Empty, "key", String.Empty);
|
||||||
|
writer.WriteString(fields[i].Name);
|
||||||
|
writer.WriteEndElement();
|
||||||
|
LLSD.LLSDWriteOne(writer, fieldValue);
|
||||||
|
// libsecondlife.StructuredData.LLSDParser.SerializeXmlElement(
|
||||||
|
// writer, libsecondlife.StructuredData.LLSD.FromObject(fieldValue));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
writer.WriteEndElement();
|
||||||
|
break;
|
||||||
|
case "ARRAY":
|
||||||
|
// LLSDArray arrayObject = obj as LLSDArray;
|
||||||
|
// ArrayList a = arrayObject.Array;
|
||||||
|
ArrayList a = (ArrayList) obj.GetType().GetField("Array").GetValue(obj);
|
||||||
|
if (a != null)
|
||||||
|
{
|
||||||
|
writer.WriteStartElement(String.Empty, "array", String.Empty);
|
||||||
|
foreach (object item in a)
|
||||||
|
{
|
||||||
|
SerializeLLSDType(writer, item);
|
||||||
|
}
|
||||||
|
writer.WriteEndElement();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LLSD.LLSDWriteOne(writer, obj);
|
||||||
|
//libsecondlife.StructuredData.LLSDParser.SerializeXmlElement(
|
||||||
|
// writer, libsecondlife.StructuredData.LLSD.FromObject(obj));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static object DeserialiseLLSDMap(Hashtable llsd, object obj)
|
||||||
|
{
|
||||||
|
Type myType = obj.GetType();
|
||||||
|
LLSDType[] llsdattributes = (LLSDType[]) myType.GetCustomAttributes(typeof (LLSDType), false);
|
||||||
|
if (llsdattributes.Length > 0)
|
||||||
|
{
|
||||||
|
switch (llsdattributes[0].ObjectType)
|
||||||
|
{
|
||||||
|
case "MAP":
|
||||||
|
IDictionaryEnumerator enumerator = llsd.GetEnumerator();
|
||||||
|
while (enumerator.MoveNext())
|
||||||
|
{
|
||||||
|
FieldInfo field = myType.GetField((string) enumerator.Key);
|
||||||
|
if (field != null)
|
||||||
|
{
|
||||||
|
// if (enumerator.Value is libsecondlife.StructuredData.LLSDMap)
|
||||||
|
if (enumerator.Value is Hashtable)
|
||||||
|
{
|
||||||
|
object fieldValue = field.GetValue(obj);
|
||||||
|
DeserialiseLLSDMap((Hashtable) enumerator.Value, fieldValue);
|
||||||
|
// DeserialiseLLSDMap((libsecondlife.StructuredData.LLSDMap) enumerator.Value, fieldValue);
|
||||||
|
}
|
||||||
|
else if (enumerator.Value is ArrayList)
|
||||||
|
{
|
||||||
|
object fieldValue = field.GetValue(obj);
|
||||||
|
fieldValue.GetType().GetField("Array").SetValue(fieldValue, enumerator.Value);
|
||||||
|
//TODO
|
||||||
|
// the LLSD map/array types in the array need to be deserialised
|
||||||
|
// but first we need to know the right class to deserialise them into.
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
field.SetValue(obj, enumerator.Value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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 OpenSim 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 libsecondlife;
|
||||||
|
|
||||||
|
namespace OpenSim.Region.Capabilities
|
||||||
|
{
|
||||||
|
[LLSDMap]
|
||||||
|
public class LLSDItemUpdate
|
||||||
|
{
|
||||||
|
public LLUUID item_id;
|
||||||
|
|
||||||
|
public LLSDItemUpdate()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,45 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) Contributors, http://opensimulator.org/
|
||||||
|
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of the OpenSim 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 libsecondlife;
|
||||||
|
|
||||||
|
namespace OpenSim.Region.Capabilities
|
||||||
|
{
|
||||||
|
[LLSDType("MAP")]
|
||||||
|
public class LLSDMapLayer
|
||||||
|
{
|
||||||
|
public int Left = 0;
|
||||||
|
public int Right = 0;
|
||||||
|
public int Top = 0;
|
||||||
|
public int Bottom = 0;
|
||||||
|
public LLUUID ImageID = LLUUID.Zero;
|
||||||
|
|
||||||
|
public LLSDMapLayer()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,40 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) Contributors, http://opensimulator.org/
|
||||||
|
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of the OpenSim 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.Region.Capabilities
|
||||||
|
{
|
||||||
|
[LLSDType("MAP")]
|
||||||
|
public class LLSDMapLayerResponse
|
||||||
|
{
|
||||||
|
public LLSDMapRequest AgentData = new LLSDMapRequest();
|
||||||
|
public LLSDArray LayerData = new LLSDArray();
|
||||||
|
|
||||||
|
public LLSDMapLayerResponse()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,40 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) Contributors, http://opensimulator.org/
|
||||||
|
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of the OpenSim 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.Region.Capabilities
|
||||||
|
{
|
||||||
|
[LLSDType("MAP")]
|
||||||
|
public class LLSDMapRequest
|
||||||
|
{
|
||||||
|
public int Flags = 0;
|
||||||
|
|
||||||
|
public LLSDMapRequest()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,32 @@
|
||||||
|
/*
|
||||||
|
* 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 OpenSim 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.Region.Capabilities
|
||||||
|
{
|
||||||
|
public delegate TResponse LLSDMethod<TRequest, TResponse>(TRequest request);
|
||||||
|
}
|
|
@ -0,0 +1,69 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) Contributors, http://opensimulator.org/
|
||||||
|
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of the OpenSim Project nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS AS IS AND ANY
|
||||||
|
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System.Collections;
|
||||||
|
using System.IO;
|
||||||
|
using System.Text;
|
||||||
|
using OpenSim.Framework.Servers;
|
||||||
|
|
||||||
|
namespace OpenSim.Region.Capabilities
|
||||||
|
{
|
||||||
|
public class LLSDStreamhandler<TRequest, TResponse> : BaseStreamHandler
|
||||||
|
where TRequest : new()
|
||||||
|
{
|
||||||
|
private LLSDMethod<TRequest, TResponse> m_method;
|
||||||
|
|
||||||
|
public LLSDStreamhandler(string httpMethod, string path, LLSDMethod<TRequest, TResponse> method)
|
||||||
|
: base(httpMethod, path)
|
||||||
|
{
|
||||||
|
m_method = method;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override byte[] Handle(string path, Stream request)
|
||||||
|
{
|
||||||
|
//Encoding encoding = Encoding.UTF8;
|
||||||
|
//StreamReader streamReader = new StreamReader(request, false);
|
||||||
|
|
||||||
|
//string requestBody = streamReader.ReadToEnd();
|
||||||
|
//streamReader.Close();
|
||||||
|
|
||||||
|
// libsecondlife.StructuredData.LLSDMap hash = (libsecondlife.StructuredData.LLSDMap)
|
||||||
|
// libsecondlife.StructuredData.LLSDParser.DeserializeXml(new XmlTextReader(request));
|
||||||
|
|
||||||
|
Hashtable hash = (Hashtable) LLSD.LLSDDeserialize(request);
|
||||||
|
TRequest llsdRequest = new TRequest();
|
||||||
|
LLSDHelpers.DeserialiseLLSDMap(hash, llsdRequest);
|
||||||
|
|
||||||
|
TResponse response = m_method(llsdRequest);
|
||||||
|
|
||||||
|
Encoding encoding = new UTF8Encoding(false);
|
||||||
|
|
||||||
|
return encoding.GetBytes(LLSDHelpers.SerialiseLLSDReply(response));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,50 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) Contributors, http://opensimulator.org/
|
||||||
|
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of the OpenSim 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 libsecondlife;
|
||||||
|
|
||||||
|
namespace OpenSim.Region.Capabilities
|
||||||
|
{
|
||||||
|
[LLSDMap]
|
||||||
|
public class LLSDTaskInventoryUploadComplete
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The task inventory item that was updated
|
||||||
|
/// </summary>
|
||||||
|
public LLUUID item_id;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The task that was updated
|
||||||
|
/// </summary>
|
||||||
|
public LLUUID task_id;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// State of the upload. So far have only even seen this set to "complete"
|
||||||
|
/// </summary>
|
||||||
|
public string state;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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 OpenSim 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 libsecondlife;
|
||||||
|
|
||||||
|
namespace OpenSim.Region.Capabilities
|
||||||
|
{
|
||||||
|
[LLSDMap]
|
||||||
|
public class LLSDTaskScriptUpdate
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The item containing the script to update
|
||||||
|
/// </summary>
|
||||||
|
public LLUUID item_id;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The task containing the script
|
||||||
|
/// </summary>
|
||||||
|
public LLUUID task_id;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Signals whether the script is currently active
|
||||||
|
/// </summary>
|
||||||
|
public int is_script_running;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,40 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) Contributors, http://opensimulator.org/
|
||||||
|
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of the OpenSim 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.Region.Capabilities
|
||||||
|
{
|
||||||
|
[LLSDType("MAP")]
|
||||||
|
public class LLSDTest
|
||||||
|
{
|
||||||
|
public int Test1 = 20;
|
||||||
|
public int Test2 = 10;
|
||||||
|
|
||||||
|
public LLSDTest()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,55 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) Contributors, http://opensimulator.org/
|
||||||
|
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of the OpenSim Project nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
||||||
|
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace OpenSim.Region.Capabilities
|
||||||
|
{
|
||||||
|
[AttributeUsage(AttributeTargets.Class)]
|
||||||
|
public class LLSDType : Attribute
|
||||||
|
{
|
||||||
|
protected string myType;
|
||||||
|
|
||||||
|
public LLSDType(string type)
|
||||||
|
{
|
||||||
|
myType = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string ObjectType
|
||||||
|
{
|
||||||
|
get { return myType; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[AttributeUsage(AttributeTargets.Class)]
|
||||||
|
public class LLSDMap : LLSDType
|
||||||
|
{
|
||||||
|
public LLSDMap() : base("MAP")
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,228 @@
|
||||||
|
/*
|
||||||
|
* 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 OpenSim 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 libsecondlife;
|
||||||
|
using OpenSim.Framework.Communications.Cache;
|
||||||
|
using OpenSim.Framework.Console;
|
||||||
|
using OpenSim.Framework.Servers;
|
||||||
|
|
||||||
|
namespace OpenSim.Framework.Communications
|
||||||
|
{
|
||||||
|
public class CommunicationsManager
|
||||||
|
{
|
||||||
|
protected IUserService m_userService;
|
||||||
|
|
||||||
|
public IUserService UserService
|
||||||
|
{
|
||||||
|
get { return m_userService; }
|
||||||
|
}
|
||||||
|
|
||||||
|
protected IGridServices m_gridService;
|
||||||
|
|
||||||
|
public IGridServices GridService
|
||||||
|
{
|
||||||
|
get { return m_gridService; }
|
||||||
|
}
|
||||||
|
|
||||||
|
protected IInventoryServices m_inventoryService;
|
||||||
|
|
||||||
|
public IInventoryServices InventoryService
|
||||||
|
{
|
||||||
|
get { return m_inventoryService; }
|
||||||
|
}
|
||||||
|
|
||||||
|
protected IInterRegionCommunications m_interRegion;
|
||||||
|
|
||||||
|
public IInterRegionCommunications InterRegion
|
||||||
|
{
|
||||||
|
get { return m_interRegion; }
|
||||||
|
}
|
||||||
|
|
||||||
|
protected UserProfileCacheService m_userProfileCacheService;
|
||||||
|
|
||||||
|
public UserProfileCacheService UserProfileCacheService
|
||||||
|
{
|
||||||
|
get { return m_userProfileCacheService; }
|
||||||
|
}
|
||||||
|
|
||||||
|
protected AssetTransactionManager m_transactionsManager;
|
||||||
|
|
||||||
|
public AssetTransactionManager TransactionsManager
|
||||||
|
{
|
||||||
|
get { return m_transactionsManager; }
|
||||||
|
}
|
||||||
|
|
||||||
|
protected AssetCache m_assetCache;
|
||||||
|
|
||||||
|
public AssetCache AssetCache
|
||||||
|
{
|
||||||
|
get { return m_assetCache; }
|
||||||
|
}
|
||||||
|
|
||||||
|
protected NetworkServersInfo m_networkServersInfo;
|
||||||
|
|
||||||
|
public NetworkServersInfo NetworkServersInfo
|
||||||
|
{
|
||||||
|
get { return m_networkServersInfo; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public CommunicationsManager(NetworkServersInfo serversInfo, BaseHttpServer httpServer, AssetCache assetCache,
|
||||||
|
bool dumpAssetsToFile)
|
||||||
|
{
|
||||||
|
m_networkServersInfo = serversInfo;
|
||||||
|
m_assetCache = assetCache;
|
||||||
|
m_userProfileCacheService = new UserProfileCacheService(this);
|
||||||
|
m_transactionsManager = new AssetTransactionManager(this, dumpAssetsToFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void doCreate(string[] cmmdParams)
|
||||||
|
{
|
||||||
|
switch (cmmdParams[0])
|
||||||
|
{
|
||||||
|
case "user":
|
||||||
|
string firstName;
|
||||||
|
string lastName;
|
||||||
|
string password;
|
||||||
|
uint regX = 1000;
|
||||||
|
uint regY = 1000;
|
||||||
|
|
||||||
|
if (cmmdParams.Length < 2)
|
||||||
|
{
|
||||||
|
firstName = MainLog.Instance.CmdPrompt("First name", "Default");
|
||||||
|
lastName = MainLog.Instance.CmdPrompt("Last name", "User");
|
||||||
|
password = MainLog.Instance.PasswdPrompt("Password");
|
||||||
|
regX = Convert.ToUInt32(MainLog.Instance.CmdPrompt("Start Region X", "1000"));
|
||||||
|
regY = Convert.ToUInt32(MainLog.Instance.CmdPrompt("Start Region Y", "1000"));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
firstName = cmmdParams[1];
|
||||||
|
lastName = cmmdParams[2];
|
||||||
|
password = cmmdParams[3];
|
||||||
|
regX = Convert.ToUInt32(cmmdParams[4]);
|
||||||
|
regY = Convert.ToUInt32(cmmdParams[5]);
|
||||||
|
}
|
||||||
|
|
||||||
|
AddUser(firstName, lastName, password, regX, regY);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public LLUUID AddUser(string firstName, string lastName, string password, uint regX, uint regY)
|
||||||
|
{
|
||||||
|
string md5PasswdHash = Util.Md5Hash(Util.Md5Hash(password) + ":" + "");
|
||||||
|
|
||||||
|
m_userService.AddUserProfile(firstName, lastName, md5PasswdHash, regX, regY);
|
||||||
|
UserProfileData userProf = UserService.GetUserProfile(firstName, lastName, "");
|
||||||
|
if (userProf == null)
|
||||||
|
{
|
||||||
|
return LLUUID.Zero;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_inventoryService.CreateNewUserInventory(userProf.UUID);
|
||||||
|
System.Console.WriteLine("Created new inventory set for " + firstName + " " + lastName);
|
||||||
|
return userProf.UUID;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Friend Methods
|
||||||
|
/// <summary>
|
||||||
|
/// Adds a new friend to the database for XUser
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="friendlistowner">The agent that who's friends list is being added to</param>
|
||||||
|
/// <param name="friend">The agent that being added to the friends list of the friends list owner</param>
|
||||||
|
/// <param name="perms">A uint bit vector for set perms that the friend being added has; 0 = none, 1=This friend can see when they sign on, 2 = map, 4 edit objects </param>
|
||||||
|
public void AddNewUserFriend(LLUUID friendlistowner, LLUUID friend, uint perms)
|
||||||
|
{
|
||||||
|
m_userService.AddNewUserFriend(friendlistowner, friend, perms);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Delete friend on friendlistowner's friendlist.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="friendlistowner">The agent that who's friends list is being updated</param>
|
||||||
|
/// <param name="friend">The Ex-friend agent</param>
|
||||||
|
public void RemoveUserFriend(LLUUID friendlistowner, LLUUID friend)
|
||||||
|
{
|
||||||
|
m_userService.RemoveUserFriend(friendlistowner, friend);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Update permissions for friend on friendlistowner's friendlist.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="friendlistowner">The agent that who's friends list is being updated</param>
|
||||||
|
/// <param name="friend">The agent that is getting or loosing permissions</param>
|
||||||
|
/// <param name="perms">A uint bit vector for set perms that the friend being added has; 0 = none, 1=This friend can see when they sign on, 2 = map, 4 edit objects </param>
|
||||||
|
public void UpdateUserFriendPerms(LLUUID friendlistowner, LLUUID friend, uint perms)
|
||||||
|
{
|
||||||
|
m_userService.UpdateUserFriendPerms(friendlistowner, friend, perms);
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Returns a list of FriendsListItems that describe the friends and permissions in the friend relationship for LLUUID friendslistowner
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="friendlistowner">The agent that we're retreiving the friends Data.</param>
|
||||||
|
public List<FriendListItem> GetUserFriendList(LLUUID friendlistowner)
|
||||||
|
{
|
||||||
|
return m_userService.GetUserFriendList(friendlistowner);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Packet Handlers
|
||||||
|
|
||||||
|
public void HandleUUIDNameRequest(LLUUID uuid, IClientAPI remote_client)
|
||||||
|
{
|
||||||
|
if (uuid == m_userProfileCacheService.libraryRoot.agentID)
|
||||||
|
{
|
||||||
|
remote_client.SendNameReply(uuid, "Mr", "OpenSim");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
UserProfileData profileData = m_userService.GetUserProfile(uuid, "");
|
||||||
|
if (profileData != null)
|
||||||
|
{
|
||||||
|
LLUUID profileId = profileData.UUID;
|
||||||
|
string firstname = profileData.username;
|
||||||
|
string lastname = profileData.surname;
|
||||||
|
|
||||||
|
remote_client.SendNameReply(profileId, firstname, lastname);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<AvatarPickerAvatar> GenerateAgentPickerRequestResponse(LLUUID queryID, string query)
|
||||||
|
{
|
||||||
|
List<AvatarPickerAvatar> pickerlist = m_userService.GenerateAgentPickerRequestResponse(queryID, query);
|
||||||
|
return pickerlist;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
|
@ -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 OpenSim 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;
|
||||||
|
|
||||||
|
namespace OpenSim.Framework.Communications
|
||||||
|
{
|
||||||
|
public interface IGridServices
|
||||||
|
{
|
||||||
|
string gdebugRegionName { get; set; }
|
||||||
|
RegionCommsListener RegisterRegion(RegionInfo regionInfos);
|
||||||
|
bool DeregisterRegion(RegionInfo regionInfo);
|
||||||
|
List<SimpleRegionInfo> RequestNeighbours(uint x, uint y);
|
||||||
|
RegionInfo RequestNeighbourInfo(ulong regionHandle);
|
||||||
|
Dictionary<string, string> GetGridSettings();
|
||||||
|
List<MapBlockData> RequestNeighbourMapBlocks(int minX, int minY, int maxX, int maxY);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,48 @@
|
||||||
|
/*
|
||||||
|
* 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 OpenSim 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 libsecondlife;
|
||||||
|
|
||||||
|
namespace OpenSim.Framework.Communications
|
||||||
|
{
|
||||||
|
public interface IInterRegionCommunications
|
||||||
|
{
|
||||||
|
string rdebugRegionName { get; set; }
|
||||||
|
bool InformRegionOfChildAgent(ulong regionHandle, AgentCircuitData agentData);
|
||||||
|
bool InformRegionOfPrimCrossing(ulong regionHandle, LLUUID primID, string objData);
|
||||||
|
bool RegionUp(SearializableRegionInfo region, ulong regionhandle);
|
||||||
|
bool ChildAgentUpdate(ulong regionHandle, ChildAgentDataUpdate cAgentData);
|
||||||
|
|
||||||
|
bool ExpectAvatarCrossing(ulong regionHandle, LLUUID agentID, LLVector3 position, bool isFlying);
|
||||||
|
bool ExpectPrimCrossing(ulong regionHandle, LLUUID primID, LLVector3 position, bool isFlying);
|
||||||
|
|
||||||
|
bool AcknowledgeAgentCrossed(ulong regionHandle, LLUUID agentId);
|
||||||
|
bool AcknowledgePrimCrossed(ulong regionHandle, LLUUID primID);
|
||||||
|
|
||||||
|
void TellRegionToCloseChildConnection(ulong regionHandle, LLUUID agentID);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,55 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) Contributors, http://opensimulator.org/
|
||||||
|
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of the OpenSim 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 libsecondlife;
|
||||||
|
using OpenSim.Framework.Communications.Cache;
|
||||||
|
|
||||||
|
namespace OpenSim.Framework.Communications
|
||||||
|
{
|
||||||
|
public delegate void InventoryFolderInfo(LLUUID userID, InventoryFolderImpl folderInfo);
|
||||||
|
|
||||||
|
public delegate void InventoryItemInfo(LLUUID userID, InventoryItemBase itemInfo);
|
||||||
|
|
||||||
|
public interface IInventoryServices
|
||||||
|
{
|
||||||
|
void RequestInventoryForUser(LLUUID userID, InventoryFolderInfo folderCallBack, InventoryItemInfo itemCallBack);
|
||||||
|
void AddNewInventoryFolder(LLUUID userID, InventoryFolderBase folder);
|
||||||
|
void MoveInventoryFolder(LLUUID userID, InventoryFolderBase folder);
|
||||||
|
void AddNewInventoryItem(LLUUID userID, InventoryItemBase item);
|
||||||
|
void DeleteInventoryItem(LLUUID userID, InventoryItemBase item);
|
||||||
|
void CreateNewUserInventory(LLUUID user);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the root folder plus any folders in root (so down one level in the Inventory folders tree)
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="userID"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
List<InventoryFolderBase> RequestFirstLevelFolders(LLUUID userID);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,390 @@
|
||||||
|
/*
|
||||||
|
* 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 OpenSim Project nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS AS IS AND ANY
|
||||||
|
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Reflection;
|
||||||
|
using libsecondlife;
|
||||||
|
using OpenSim.Framework.Console;
|
||||||
|
|
||||||
|
namespace OpenSim.Framework.Communications
|
||||||
|
{
|
||||||
|
public abstract class InventoryServiceBase : IInventoryServices
|
||||||
|
{
|
||||||
|
protected Dictionary<string, IInventoryData> m_plugins = new Dictionary<string, IInventoryData>();
|
||||||
|
//protected IAssetServer m_assetServer;
|
||||||
|
|
||||||
|
public InventoryServiceBase()
|
||||||
|
{
|
||||||
|
//m_assetServer = assetServer;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Adds a new user server plugin - plugins will be requested in the order they were loaded.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="FileName">The filename to the user server plugin DLL</param>
|
||||||
|
public void AddPlugin(string FileName)
|
||||||
|
{
|
||||||
|
if (!String.IsNullOrEmpty(FileName))
|
||||||
|
{
|
||||||
|
MainLog.Instance.Verbose("AGENTINVENTORY", "Inventorystorage: Attempting to load " + FileName);
|
||||||
|
Assembly pluginAssembly = Assembly.LoadFrom(FileName);
|
||||||
|
|
||||||
|
foreach (Type pluginType in pluginAssembly.GetTypes())
|
||||||
|
{
|
||||||
|
if (!pluginType.IsAbstract)
|
||||||
|
{
|
||||||
|
Type typeInterface = pluginType.GetInterface("IInventoryData", true);
|
||||||
|
|
||||||
|
if (typeInterface != null)
|
||||||
|
{
|
||||||
|
IInventoryData plug =
|
||||||
|
(IInventoryData) Activator.CreateInstance(pluginAssembly.GetType(pluginType.ToString()));
|
||||||
|
plug.Initialise();
|
||||||
|
m_plugins.Add(plug.getName(), plug);
|
||||||
|
MainLog.Instance.Verbose("AGENTINVENTORY", "Added IInventoryData Interface");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<InventoryFolderBase> RequestFirstLevelFolders(Guid rawUserID)
|
||||||
|
{
|
||||||
|
LLUUID userID = new LLUUID(rawUserID);
|
||||||
|
return RequestFirstLevelFolders(userID);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the root folder plus any folders in root (so down one level in the Inventory folders tree)
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="userID"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public List<InventoryFolderBase> RequestFirstLevelFolders(LLUUID userID)
|
||||||
|
{
|
||||||
|
List<InventoryFolderBase> inventoryList = new List<InventoryFolderBase>();
|
||||||
|
InventoryFolderBase rootFolder = null;
|
||||||
|
|
||||||
|
foreach (KeyValuePair<string, IInventoryData> plugin in m_plugins)
|
||||||
|
{
|
||||||
|
rootFolder = plugin.Value.getUserRootFolder(userID);
|
||||||
|
if (rootFolder != null)
|
||||||
|
{
|
||||||
|
MainLog.Instance.Verbose(
|
||||||
|
"INVENTORY",
|
||||||
|
"Found root folder for user with ID " + userID + ". Retrieving inventory contents.");
|
||||||
|
|
||||||
|
inventoryList = plugin.Value.getInventoryFolders(rootFolder.folderID);
|
||||||
|
inventoryList.Insert(0, rootFolder);
|
||||||
|
return inventoryList;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MainLog.Instance.Warn(
|
||||||
|
"INVENTORY", "Could not find a root folder belonging to user with ID " + userID);
|
||||||
|
|
||||||
|
return inventoryList;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the root folder for a user
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="userID"></param>
|
||||||
|
/// <returns>null if no root folder was found</returns>
|
||||||
|
public InventoryFolderBase RequestUsersRoot(LLUUID userID)
|
||||||
|
{
|
||||||
|
foreach (KeyValuePair<string, IInventoryData> plugin in m_plugins)
|
||||||
|
{
|
||||||
|
return plugin.Value.getUserRootFolder(userID);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
public void MoveInventoryFolder(LLUUID userID, InventoryFolderBase folder)
|
||||||
|
{
|
||||||
|
foreach (KeyValuePair<string, IInventoryData> plugin in m_plugins)
|
||||||
|
{
|
||||||
|
plugin.Value.moveInventoryFolder(folder);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="parentFolderID"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public List<InventoryFolderBase> RequestSubFolders(LLUUID parentFolderID)
|
||||||
|
{
|
||||||
|
List<InventoryFolderBase> inventoryList = new List<InventoryFolderBase>();
|
||||||
|
foreach (KeyValuePair<string, IInventoryData> plugin in m_plugins)
|
||||||
|
{
|
||||||
|
return plugin.Value.getInventoryFolders(parentFolderID);
|
||||||
|
}
|
||||||
|
return inventoryList;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<InventoryItemBase> RequestFolderItems(LLUUID folderID)
|
||||||
|
{
|
||||||
|
List<InventoryItemBase> itemsList = new List<InventoryItemBase>();
|
||||||
|
foreach (KeyValuePair<string, IInventoryData> plugin in m_plugins)
|
||||||
|
{
|
||||||
|
itemsList = plugin.Value.getInventoryInFolder(folderID);
|
||||||
|
return itemsList;
|
||||||
|
}
|
||||||
|
return itemsList;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddFolder(InventoryFolderBase folder)
|
||||||
|
{
|
||||||
|
foreach (KeyValuePair<string, IInventoryData> plugin in m_plugins)
|
||||||
|
{
|
||||||
|
plugin.Value.addInventoryFolder(folder);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void MoveFolder(InventoryFolderBase folder)
|
||||||
|
{
|
||||||
|
foreach (KeyValuePair<string, IInventoryData> plugin in m_plugins)
|
||||||
|
{
|
||||||
|
plugin.Value.moveInventoryFolder(folder);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddItem(InventoryItemBase item)
|
||||||
|
{
|
||||||
|
foreach (KeyValuePair<string, IInventoryData> plugin in m_plugins)
|
||||||
|
{
|
||||||
|
plugin.Value.addInventoryItem(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void DeleteItem(InventoryItemBase item)
|
||||||
|
{
|
||||||
|
foreach (KeyValuePair<string, IInventoryData> plugin in m_plugins)
|
||||||
|
{
|
||||||
|
plugin.Value.deleteInventoryItem(item.inventoryID);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="inventory"></param>
|
||||||
|
public void AddNewInventorySet(UsersInventory inventory)
|
||||||
|
{
|
||||||
|
foreach (InventoryFolderBase folder in inventory.Folders.Values)
|
||||||
|
{
|
||||||
|
AddFolder(folder);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Create a new set of inventory folders for the given user.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="user"></param>
|
||||||
|
public void CreateNewUserInventory(LLUUID user)
|
||||||
|
{
|
||||||
|
InventoryFolderBase existingRootFolder = RequestUsersRoot(user);
|
||||||
|
|
||||||
|
if (null != existingRootFolder)
|
||||||
|
{
|
||||||
|
MainLog.Instance.Error(
|
||||||
|
"AGENTINVENTORY",
|
||||||
|
"Did not create a new inventory for user {0} since they already have "
|
||||||
|
+ "a root inventory folder with id {1}", user, existingRootFolder);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
UsersInventory inven = new UsersInventory();
|
||||||
|
inven.CreateNewInventorySet(user);
|
||||||
|
AddNewInventorySet(inven);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class UsersInventory
|
||||||
|
{
|
||||||
|
public Dictionary<LLUUID, InventoryFolderBase> Folders = new Dictionary<LLUUID, InventoryFolderBase>();
|
||||||
|
public Dictionary<LLUUID, InventoryItemBase> Items = new Dictionary<LLUUID, InventoryItemBase>();
|
||||||
|
|
||||||
|
public UsersInventory()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void CreateNewInventorySet(LLUUID user)
|
||||||
|
{
|
||||||
|
InventoryFolderBase folder = new InventoryFolderBase();
|
||||||
|
folder.parentID = LLUUID.Zero;
|
||||||
|
folder.agentID = user;
|
||||||
|
folder.folderID = LLUUID.Random();
|
||||||
|
folder.name = "My Inventory";
|
||||||
|
folder.type = 8;
|
||||||
|
folder.version = 1;
|
||||||
|
Folders.Add(folder.folderID, folder);
|
||||||
|
|
||||||
|
LLUUID rootFolder = folder.folderID;
|
||||||
|
|
||||||
|
folder = new InventoryFolderBase();
|
||||||
|
folder.parentID = rootFolder;
|
||||||
|
folder.agentID = user;
|
||||||
|
folder.folderID = LLUUID.Random();
|
||||||
|
folder.name = "Accessories";
|
||||||
|
folder.type = 8;
|
||||||
|
folder.version = 1;
|
||||||
|
Folders.Add(folder.folderID, folder);
|
||||||
|
|
||||||
|
folder = new InventoryFolderBase();
|
||||||
|
folder.parentID = rootFolder;
|
||||||
|
folder.agentID = user;
|
||||||
|
folder.folderID = LLUUID.Random();
|
||||||
|
folder.name = "Animations";
|
||||||
|
folder.type = 20;
|
||||||
|
folder.version = 1;
|
||||||
|
Folders.Add(folder.folderID, folder);
|
||||||
|
|
||||||
|
folder = new InventoryFolderBase();
|
||||||
|
folder.parentID = rootFolder;
|
||||||
|
folder.agentID = user;
|
||||||
|
folder.folderID = LLUUID.Random();
|
||||||
|
folder.name = "BodyParts";
|
||||||
|
folder.type = 13;
|
||||||
|
folder.version = 1;
|
||||||
|
Folders.Add(folder.folderID, folder);
|
||||||
|
|
||||||
|
folder = new InventoryFolderBase();
|
||||||
|
folder.parentID = rootFolder;
|
||||||
|
folder.agentID = user;
|
||||||
|
folder.folderID = LLUUID.Random();
|
||||||
|
folder.name = "Clothing";
|
||||||
|
folder.type = 5;
|
||||||
|
folder.version = 1;
|
||||||
|
Folders.Add(folder.folderID, folder);
|
||||||
|
|
||||||
|
folder = new InventoryFolderBase();
|
||||||
|
folder.parentID = rootFolder;
|
||||||
|
folder.agentID = user;
|
||||||
|
folder.folderID = LLUUID.Random();
|
||||||
|
folder.name = "Gestures";
|
||||||
|
folder.type = 21;
|
||||||
|
folder.version = 1;
|
||||||
|
Folders.Add(folder.folderID, folder);
|
||||||
|
|
||||||
|
folder = new InventoryFolderBase();
|
||||||
|
folder.parentID = rootFolder;
|
||||||
|
folder.agentID = user;
|
||||||
|
folder.folderID = LLUUID.Random();
|
||||||
|
folder.name = "Landmarks";
|
||||||
|
folder.type = 3;
|
||||||
|
folder.version = 1;
|
||||||
|
Folders.Add(folder.folderID, folder);
|
||||||
|
|
||||||
|
folder = new InventoryFolderBase();
|
||||||
|
folder.parentID = rootFolder;
|
||||||
|
folder.agentID = user;
|
||||||
|
folder.folderID = LLUUID.Random();
|
||||||
|
folder.name = "Lost And Found";
|
||||||
|
folder.type = 3;
|
||||||
|
folder.version = 1;
|
||||||
|
Folders.Add(folder.folderID, folder);
|
||||||
|
|
||||||
|
folder = new InventoryFolderBase();
|
||||||
|
folder.parentID = rootFolder;
|
||||||
|
folder.agentID = user;
|
||||||
|
folder.folderID = LLUUID.Random();
|
||||||
|
folder.name = "Notecards";
|
||||||
|
folder.type = 7;
|
||||||
|
folder.version = 1;
|
||||||
|
Folders.Add(folder.folderID, folder);
|
||||||
|
|
||||||
|
folder = new InventoryFolderBase();
|
||||||
|
folder.parentID = rootFolder;
|
||||||
|
folder.agentID = user;
|
||||||
|
folder.folderID = LLUUID.Random();
|
||||||
|
folder.name = "Objects";
|
||||||
|
folder.type = 6;
|
||||||
|
folder.version = 1;
|
||||||
|
Folders.Add(folder.folderID, folder);
|
||||||
|
|
||||||
|
folder = new InventoryFolderBase();
|
||||||
|
folder.parentID = rootFolder;
|
||||||
|
folder.agentID = user;
|
||||||
|
folder.folderID = LLUUID.Random();
|
||||||
|
folder.name = "Photo Album";
|
||||||
|
folder.type = 15;
|
||||||
|
folder.version = 1;
|
||||||
|
Folders.Add(folder.folderID, folder);
|
||||||
|
|
||||||
|
folder = new InventoryFolderBase();
|
||||||
|
folder.parentID = rootFolder;
|
||||||
|
folder.agentID = user;
|
||||||
|
folder.folderID = LLUUID.Random();
|
||||||
|
folder.name = "Scripts";
|
||||||
|
folder.type = 10;
|
||||||
|
folder.version = 1;
|
||||||
|
Folders.Add(folder.folderID, folder);
|
||||||
|
|
||||||
|
folder = new InventoryFolderBase();
|
||||||
|
folder.parentID = rootFolder;
|
||||||
|
folder.agentID = user;
|
||||||
|
folder.folderID = LLUUID.Random();
|
||||||
|
folder.name = "Sounds";
|
||||||
|
folder.type = 1;
|
||||||
|
folder.version = 1;
|
||||||
|
Folders.Add(folder.folderID, folder);
|
||||||
|
|
||||||
|
folder = new InventoryFolderBase();
|
||||||
|
folder.parentID = rootFolder;
|
||||||
|
folder.agentID = user;
|
||||||
|
folder.folderID = LLUUID.Random();
|
||||||
|
folder.name = "Textures";
|
||||||
|
folder.type = 0;
|
||||||
|
folder.version = 1;
|
||||||
|
Folders.Add(folder.folderID, folder);
|
||||||
|
|
||||||
|
folder = new InventoryFolderBase();
|
||||||
|
folder.parentID = rootFolder;
|
||||||
|
folder.agentID = user;
|
||||||
|
folder.folderID = LLUUID.Random();
|
||||||
|
folder.name = "Trash";
|
||||||
|
folder.type = 14;
|
||||||
|
folder.version = 1;
|
||||||
|
Folders.Add(folder.folderID, folder);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract void RequestInventoryForUser(LLUUID userID, InventoryFolderInfo folderCallBack,
|
||||||
|
InventoryItemInfo itemCallBack);
|
||||||
|
|
||||||
|
public abstract void AddNewInventoryFolder(LLUUID userID, InventoryFolderBase folder);
|
||||||
|
public abstract void MoveExistingInventoryFolder(InventoryFolderBase folder);
|
||||||
|
public abstract void AddNewInventoryItem(LLUUID userID, InventoryItemBase item);
|
||||||
|
public abstract void DeleteInventoryItem(LLUUID userID, InventoryItemBase item);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,768 @@
|
||||||
|
/*
|
||||||
|
* 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 OpenSim 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 libsecondlife;
|
||||||
|
using libsecondlife.StructuredData;
|
||||||
|
using Nwc.XmlRpc;
|
||||||
|
using OpenSim.Framework.Console;
|
||||||
|
|
||||||
|
namespace OpenSim.Framework.UserManagement
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// A temp class to handle login response.
|
||||||
|
/// Should make use of UserProfileManager where possible.
|
||||||
|
/// </summary>
|
||||||
|
public class LoginResponse
|
||||||
|
{
|
||||||
|
private Hashtable loginFlagsHash;
|
||||||
|
private Hashtable globalTexturesHash;
|
||||||
|
private Hashtable loginError;
|
||||||
|
private Hashtable uiConfigHash;
|
||||||
|
|
||||||
|
private ArrayList loginFlags;
|
||||||
|
private ArrayList globalTextures;
|
||||||
|
private ArrayList eventCategories;
|
||||||
|
private ArrayList uiConfig;
|
||||||
|
private ArrayList classifiedCategories;
|
||||||
|
private ArrayList inventoryRoot;
|
||||||
|
private ArrayList initialOutfit;
|
||||||
|
private ArrayList agentInventory;
|
||||||
|
private ArrayList inventoryLibraryOwner;
|
||||||
|
private ArrayList inventoryLibRoot;
|
||||||
|
private ArrayList inventoryLibrary;
|
||||||
|
|
||||||
|
private UserInfo userProfile;
|
||||||
|
|
||||||
|
private LLUUID agentID;
|
||||||
|
private LLUUID sessionID;
|
||||||
|
private LLUUID secureSessionID;
|
||||||
|
|
||||||
|
// Login Flags
|
||||||
|
private string dst;
|
||||||
|
private string stipendSinceLogin;
|
||||||
|
private string gendered;
|
||||||
|
private string everLoggedIn;
|
||||||
|
private string login;
|
||||||
|
private uint simPort;
|
||||||
|
private string simAddress;
|
||||||
|
private string agentAccess;
|
||||||
|
private Int32 circuitCode;
|
||||||
|
private uint regionX;
|
||||||
|
private uint regionY;
|
||||||
|
|
||||||
|
// Login
|
||||||
|
private string firstname;
|
||||||
|
private string lastname;
|
||||||
|
|
||||||
|
// REX (client version string)
|
||||||
|
private string clientVersion = "not set";
|
||||||
|
|
||||||
|
// Global Textures
|
||||||
|
private string sunTexture;
|
||||||
|
private string cloudTexture;
|
||||||
|
private string moonTexture;
|
||||||
|
|
||||||
|
// Error Flags
|
||||||
|
private string errorReason;
|
||||||
|
private string errorMessage;
|
||||||
|
|
||||||
|
// Response
|
||||||
|
private XmlRpcResponse xmlRpcResponse;
|
||||||
|
private XmlRpcResponse defaultXmlRpcResponse;
|
||||||
|
|
||||||
|
private string welcomeMessage;
|
||||||
|
private string startLocation;
|
||||||
|
private string allowFirstLife;
|
||||||
|
private string home;
|
||||||
|
private string seedCapability;
|
||||||
|
private string lookAt;
|
||||||
|
|
||||||
|
private BuddyList m_buddyList = null;
|
||||||
|
|
||||||
|
public LoginResponse()
|
||||||
|
{
|
||||||
|
loginFlags = new ArrayList();
|
||||||
|
globalTextures = new ArrayList();
|
||||||
|
eventCategories = new ArrayList();
|
||||||
|
uiConfig = new ArrayList();
|
||||||
|
classifiedCategories = new ArrayList();
|
||||||
|
|
||||||
|
loginError = new Hashtable();
|
||||||
|
uiConfigHash = new Hashtable();
|
||||||
|
|
||||||
|
defaultXmlRpcResponse = new XmlRpcResponse();
|
||||||
|
userProfile = new UserInfo();
|
||||||
|
inventoryRoot = new ArrayList();
|
||||||
|
initialOutfit = new ArrayList();
|
||||||
|
agentInventory = new ArrayList();
|
||||||
|
inventoryLibrary = new ArrayList();
|
||||||
|
inventoryLibraryOwner = new ArrayList();
|
||||||
|
|
||||||
|
xmlRpcResponse = new XmlRpcResponse();
|
||||||
|
defaultXmlRpcResponse = new XmlRpcResponse();
|
||||||
|
|
||||||
|
SetDefaultValues();
|
||||||
|
} // LoginServer
|
||||||
|
|
||||||
|
public void SetDefaultValues()
|
||||||
|
{
|
||||||
|
DST = "N";
|
||||||
|
StipendSinceLogin = "N";
|
||||||
|
Gendered = "Y";
|
||||||
|
EverLoggedIn = "Y";
|
||||||
|
login = "false";
|
||||||
|
firstname = "Test";
|
||||||
|
lastname = "User";
|
||||||
|
agentAccess = "M";
|
||||||
|
startLocation = "last";
|
||||||
|
allowFirstLife = "Y";
|
||||||
|
|
||||||
|
SunTexture = "cce0f112-878f-4586-a2e2-a8f104bba271";
|
||||||
|
CloudTexture = "dc4b9f0b-d008-45c6-96a4-01dd947ac621";
|
||||||
|
MoonTexture = "ec4b9f0b-d008-45c6-96a4-01dd947ac621";
|
||||||
|
|
||||||
|
ErrorMessage = "You have entered an invalid name/password combination. Check Caps/lock.";
|
||||||
|
ErrorReason = "key";
|
||||||
|
welcomeMessage = "Welcome to OpenSim!";
|
||||||
|
seedCapability = "";
|
||||||
|
home = "{'region_handle':[r" + (1000*256).ToString() + ",r" + (1000*256).ToString() + "], 'position':[r" +
|
||||||
|
userProfile.homepos.X.ToString() + ",r" + userProfile.homepos.Y.ToString() + ",r" +
|
||||||
|
userProfile.homepos.Z.ToString() + "], 'look_at':[r" + userProfile.homelookat.X.ToString() + ",r" +
|
||||||
|
userProfile.homelookat.Y.ToString() + ",r" + userProfile.homelookat.Z.ToString() + "]}";
|
||||||
|
lookAt = "[r0.99949799999999999756,r0.03166859999999999814,r0]";
|
||||||
|
RegionX = (uint) 255232;
|
||||||
|
RegionY = (uint) 254976;
|
||||||
|
|
||||||
|
clientVersion = "not set"; //rex
|
||||||
|
|
||||||
|
// Classifieds;
|
||||||
|
AddClassifiedCategory((Int32) 1, "Shopping");
|
||||||
|
AddClassifiedCategory((Int32) 2, "Land Rental");
|
||||||
|
AddClassifiedCategory((Int32) 3, "Property Rental");
|
||||||
|
AddClassifiedCategory((Int32) 4, "Special Attraction");
|
||||||
|
AddClassifiedCategory((Int32) 5, "New Products");
|
||||||
|
AddClassifiedCategory((Int32) 6, "Employment");
|
||||||
|
AddClassifiedCategory((Int32) 7, "Wanted");
|
||||||
|
AddClassifiedCategory((Int32) 8, "Service");
|
||||||
|
AddClassifiedCategory((Int32) 9, "Personal");
|
||||||
|
|
||||||
|
|
||||||
|
SessionID = LLUUID.Random();
|
||||||
|
SecureSessionID = LLUUID.Random();
|
||||||
|
AgentID = LLUUID.Random();
|
||||||
|
|
||||||
|
Hashtable InitialOutfitHash = new Hashtable();
|
||||||
|
InitialOutfitHash["folder_name"] = "Nightclub Female";
|
||||||
|
InitialOutfitHash["gender"] = "female";
|
||||||
|
initialOutfit.Add(InitialOutfitHash);
|
||||||
|
} // SetDefaultValues
|
||||||
|
|
||||||
|
#region Login Failure Methods
|
||||||
|
|
||||||
|
public XmlRpcResponse GenerateFailureResponse(string reason, string message, string login)
|
||||||
|
{
|
||||||
|
// Overwrite any default values;
|
||||||
|
xmlRpcResponse = new XmlRpcResponse();
|
||||||
|
|
||||||
|
// Ensure Login Failed message/reason;
|
||||||
|
ErrorMessage = message;
|
||||||
|
ErrorReason = reason;
|
||||||
|
|
||||||
|
loginError["reason"] = ErrorReason;
|
||||||
|
loginError["message"] = ErrorMessage;
|
||||||
|
loginError["login"] = login;
|
||||||
|
xmlRpcResponse.Value = loginError;
|
||||||
|
return (xmlRpcResponse);
|
||||||
|
} // GenerateResponse
|
||||||
|
|
||||||
|
public LLSD GenerateFailureResponseLLSD(string reason, string message, string login)
|
||||||
|
{
|
||||||
|
LLSDMap map = new LLSDMap();
|
||||||
|
|
||||||
|
// Ensure Login Failed message/reason;
|
||||||
|
ErrorMessage = message;
|
||||||
|
ErrorReason = reason;
|
||||||
|
|
||||||
|
map["reason"] = LLSD.FromString(ErrorReason);
|
||||||
|
map["message"] = LLSD.FromString(ErrorMessage);
|
||||||
|
map["login"] = LLSD.FromString(login);
|
||||||
|
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
public XmlRpcResponse CreateFailedResponse()
|
||||||
|
{
|
||||||
|
return (CreateLoginFailedResponse());
|
||||||
|
} // CreateErrorConnectingToGridResponse()
|
||||||
|
|
||||||
|
public LLSD CreateFailedResponseLLSD()
|
||||||
|
{
|
||||||
|
return CreateLoginFailedResponseLLSD();
|
||||||
|
}
|
||||||
|
|
||||||
|
public XmlRpcResponse CreateLoginFailedResponse()
|
||||||
|
{
|
||||||
|
return
|
||||||
|
(GenerateFailureResponse("key",
|
||||||
|
"Could not authenticate your avatar. Please check your username and password, and check the grid if problems persist.",
|
||||||
|
"false"));
|
||||||
|
} // LoginFailedResponse
|
||||||
|
|
||||||
|
public LLSD CreateLoginFailedResponseLLSD()
|
||||||
|
{
|
||||||
|
return GenerateFailureResponseLLSD(
|
||||||
|
"key",
|
||||||
|
"Could not authenticate your avatar. Please check your username and password, and check the grid if problems persist.",
|
||||||
|
"false");
|
||||||
|
}
|
||||||
|
|
||||||
|
public XmlRpcResponse CreateAlreadyLoggedInResponse()
|
||||||
|
{
|
||||||
|
return
|
||||||
|
(GenerateFailureResponse("presence",
|
||||||
|
"You appear to be already logged in, if this is not the case please wait for your session to timeout, if this takes longer than a few minutes please contact the grid owner",
|
||||||
|
"false"));
|
||||||
|
} // CreateAlreadyLoggedInResponse()
|
||||||
|
|
||||||
|
public LLSD CreateAlreadyLoggedInResponseLLSD()
|
||||||
|
{
|
||||||
|
return GenerateFailureResponseLLSD(
|
||||||
|
"presence",
|
||||||
|
"You appear to be already logged in, if this is not the case please wait for your session to timeout, if this takes longer than a few minutes please contact the grid owner",
|
||||||
|
"false");
|
||||||
|
}
|
||||||
|
|
||||||
|
public XmlRpcResponse CreateDeadRegionResponse()
|
||||||
|
{
|
||||||
|
return
|
||||||
|
(GenerateFailureResponse("key",
|
||||||
|
"The region you are attempting to log into is not responding. Please select another region and try again.",
|
||||||
|
"false"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public LLSD CreateDeadRegionResponseLLSD()
|
||||||
|
{
|
||||||
|
return GenerateFailureResponseLLSD(
|
||||||
|
"key",
|
||||||
|
"The region you are attempting to log into is not responding. Please select another region and try again.",
|
||||||
|
"false");
|
||||||
|
}
|
||||||
|
|
||||||
|
public XmlRpcResponse CreateGridErrorResponse()
|
||||||
|
{
|
||||||
|
return
|
||||||
|
(GenerateFailureResponse("key",
|
||||||
|
"Error connecting to grid. Could not percieve credentials from login XML.",
|
||||||
|
"false"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public LLSD CreateGridErrorResponseLLSD()
|
||||||
|
{
|
||||||
|
return GenerateFailureResponseLLSD(
|
||||||
|
"key",
|
||||||
|
"Error connecting to grid. Could not percieve credentials from login XML.",
|
||||||
|
"false");
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
public XmlRpcResponse ToXmlRpcResponse()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Hashtable responseData = new Hashtable();
|
||||||
|
|
||||||
|
loginFlagsHash = new Hashtable();
|
||||||
|
loginFlagsHash["daylight_savings"] = DST;
|
||||||
|
loginFlagsHash["stipend_since_login"] = StipendSinceLogin;
|
||||||
|
loginFlagsHash["gendered"] = Gendered;
|
||||||
|
loginFlagsHash["ever_logged_in"] = EverLoggedIn;
|
||||||
|
loginFlags.Add(loginFlagsHash);
|
||||||
|
|
||||||
|
responseData["first_name"] = Firstname;
|
||||||
|
responseData["last_name"] = Lastname;
|
||||||
|
responseData["agent_access"] = agentAccess;
|
||||||
|
|
||||||
|
globalTexturesHash = new Hashtable();
|
||||||
|
globalTexturesHash["sun_texture_id"] = SunTexture;
|
||||||
|
globalTexturesHash["cloud_texture_id"] = CloudTexture;
|
||||||
|
globalTexturesHash["moon_texture_id"] = MoonTexture;
|
||||||
|
globalTextures.Add(globalTexturesHash);
|
||||||
|
// this.eventCategories.Add(this.eventCategoriesHash);
|
||||||
|
|
||||||
|
AddToUIConfig("allow_first_life", allowFirstLife);
|
||||||
|
uiConfig.Add(uiConfigHash);
|
||||||
|
|
||||||
|
responseData["sim_port"] = (Int32) SimPort;
|
||||||
|
responseData["sim_ip"] = SimAddress;
|
||||||
|
|
||||||
|
responseData["agent_id"] = AgentID.ToString();
|
||||||
|
responseData["session_id"] = SessionID.ToString();
|
||||||
|
responseData["secure_session_id"] = SecureSessionID.ToString();
|
||||||
|
responseData["circuit_code"] = CircuitCode;
|
||||||
|
responseData["seconds_since_epoch"] = (Int32) (DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalSeconds;
|
||||||
|
responseData["login-flags"] = loginFlags;
|
||||||
|
responseData["global-textures"] = globalTextures;
|
||||||
|
responseData["seed_capability"] = seedCapability;
|
||||||
|
|
||||||
|
responseData["event_categories"] = eventCategories;
|
||||||
|
responseData["event_notifications"] = new ArrayList(); // todo
|
||||||
|
responseData["classified_categories"] = classifiedCategories;
|
||||||
|
responseData["ui-config"] = uiConfig;
|
||||||
|
|
||||||
|
responseData["inventory-skeleton"] = agentInventory;
|
||||||
|
responseData["inventory-skel-lib"] = inventoryLibrary;
|
||||||
|
responseData["inventory-root"] = inventoryRoot;
|
||||||
|
responseData["inventory-lib-root"] = inventoryLibRoot;
|
||||||
|
responseData["gestures"] = new ArrayList(); // todo
|
||||||
|
responseData["inventory-lib-owner"] = inventoryLibraryOwner;
|
||||||
|
responseData["initial-outfit"] = initialOutfit;
|
||||||
|
responseData["start_location"] = startLocation;
|
||||||
|
responseData["seed_capability"] = seedCapability;
|
||||||
|
responseData["home"] = home;
|
||||||
|
responseData["look_at"] = lookAt;
|
||||||
|
responseData["message"] = welcomeMessage;
|
||||||
|
responseData["region_x"] = (Int32) RegionX*256;
|
||||||
|
responseData["region_y"] = (Int32) RegionY*256;
|
||||||
|
|
||||||
|
responseData["version"] = clientVersion; //rex
|
||||||
|
|
||||||
|
//responseData["inventory-lib-root"] = new ArrayList(); // todo
|
||||||
|
|
||||||
|
if (m_buddyList != null)
|
||||||
|
{
|
||||||
|
responseData["buddy-list"] = m_buddyList.ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
responseData["login"] = "true";
|
||||||
|
xmlRpcResponse.Value = responseData;
|
||||||
|
|
||||||
|
return (xmlRpcResponse);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
MainLog.Instance.Warn(
|
||||||
|
"CLIENT",
|
||||||
|
"LoginResponse: Error creating XML-RPC Response: " + e.Message
|
||||||
|
);
|
||||||
|
return (GenerateFailureResponse("Internal Error", "Error generating Login Response", "false"));
|
||||||
|
}
|
||||||
|
} // ToXmlRpcResponse
|
||||||
|
|
||||||
|
public LLSD ToLLSDResponse()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
LLSDMap map = new LLSDMap();
|
||||||
|
|
||||||
|
map["first_name"] = LLSD.FromString(Firstname);
|
||||||
|
map["last_name"] = LLSD.FromString(Lastname);
|
||||||
|
map["agent_access"] = LLSD.FromString(agentAccess);
|
||||||
|
|
||||||
|
map["sim_port"] = LLSD.FromInteger(SimPort);
|
||||||
|
map["sim_ip"] = LLSD.FromString(SimAddress);
|
||||||
|
|
||||||
|
map["agent_id"] = LLSD.FromUUID(AgentID);
|
||||||
|
map["session_id"] = LLSD.FromUUID(SessionID);
|
||||||
|
map["secure_session_id"] = LLSD.FromUUID(SecureSessionID);
|
||||||
|
map["circuit_code"] = LLSD.FromInteger(CircuitCode);
|
||||||
|
map["seconds_since_epoch"] = LLSD.FromInteger((int)(DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalSeconds);
|
||||||
|
|
||||||
|
#region Login Flags
|
||||||
|
|
||||||
|
LLSDMap loginFlagsLLSD = new LLSDMap();
|
||||||
|
loginFlagsLLSD["daylight_savings"] = LLSD.FromString(DST);
|
||||||
|
loginFlagsLLSD["stipend_since_login"] = LLSD.FromString(StipendSinceLogin);
|
||||||
|
loginFlagsLLSD["gendered"] = LLSD.FromString(Gendered);
|
||||||
|
loginFlagsLLSD["ever_logged_in"] = LLSD.FromString(EverLoggedIn);
|
||||||
|
map["login-flags"] = WrapLLSDMap(loginFlagsLLSD);
|
||||||
|
|
||||||
|
#endregion Login Flags
|
||||||
|
|
||||||
|
#region Global Textures
|
||||||
|
|
||||||
|
LLSDMap globalTexturesLLSD = new LLSDMap();
|
||||||
|
globalTexturesLLSD["sun_texture_id"] = LLSD.FromString(SunTexture);
|
||||||
|
globalTexturesLLSD["cloud_texture_id"] = LLSD.FromString(CloudTexture);
|
||||||
|
globalTexturesLLSD["moon_texture_id"] = LLSD.FromString(MoonTexture);
|
||||||
|
|
||||||
|
map["global-textures"] = WrapLLSDMap(globalTexturesLLSD);
|
||||||
|
|
||||||
|
#endregion Global Textures
|
||||||
|
|
||||||
|
map["seed_capability"] = LLSD.FromString(seedCapability);
|
||||||
|
|
||||||
|
// FIXME: Need a function that will convert these ArrayLists in to LLSDArrays,
|
||||||
|
// and convert the data inside them to LLSD objects as well
|
||||||
|
|
||||||
|
//map["event_categories"] = eventCategories;
|
||||||
|
//map["event_notifications"] = new LLSDArray(); // todo
|
||||||
|
//map["classified_categories"] = classifiedCategories;
|
||||||
|
|
||||||
|
#region UI Config
|
||||||
|
|
||||||
|
LLSDMap uiConfigLLSD = new LLSDMap();
|
||||||
|
uiConfigLLSD["allow_first_life"] = LLSD.FromString(allowFirstLife);
|
||||||
|
map["ui-config"] = WrapLLSDMap(uiConfigLLSD);
|
||||||
|
|
||||||
|
#endregion UI Config
|
||||||
|
|
||||||
|
#region Inventory
|
||||||
|
|
||||||
|
//map["inventory-skeleton"] = agentInventory;
|
||||||
|
//map["inventory-skel-lib"] = inventoryLibrary;
|
||||||
|
//map["inventory-root"] = inventoryRoot;
|
||||||
|
//map["inventory-lib-root"] = inventoryLibRoot;
|
||||||
|
//map["inventory-lib-owner"] = inventoryLibraryOwner;
|
||||||
|
|
||||||
|
#endregion Inventory
|
||||||
|
|
||||||
|
map["gestures"] = new LLSDArray(); // todo
|
||||||
|
|
||||||
|
//responseData["initial-outfit"] = initialOutfit;
|
||||||
|
//responseData["start_location"] = startLocation;
|
||||||
|
|
||||||
|
map["seed_capability"] = LLSD.FromString(seedCapability);
|
||||||
|
map["home"] = LLSD.FromString(home);
|
||||||
|
map["look_at"] = LLSD.FromString(lookAt);
|
||||||
|
map["message"] = LLSD.FromString(welcomeMessage);
|
||||||
|
map["region_x"] = LLSD.FromInteger(RegionX * 256);
|
||||||
|
map["region_y"] = LLSD.FromInteger(RegionY * 256);
|
||||||
|
|
||||||
|
map["version"] = LLSD.FromString(clientVersion); //rex
|
||||||
|
|
||||||
|
if (m_buddyList != null)
|
||||||
|
{
|
||||||
|
//map["buddy-list"] = m_buddyList.ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
map["login"] = LLSD.FromString("true");
|
||||||
|
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
MainLog.Instance.Warn(
|
||||||
|
"CLIENT",
|
||||||
|
"LoginResponse: Error creating XML-RPC Response: " + e.Message
|
||||||
|
);
|
||||||
|
return GenerateFailureResponseLLSD("Internal Error", "Error generating Login Response", "false");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private LLSDArray WrapLLSDMap(LLSDMap wrapMe)
|
||||||
|
{
|
||||||
|
LLSDArray array = new LLSDArray();
|
||||||
|
array.Add(wrapMe);
|
||||||
|
return array;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetEventCategories(string category, string value)
|
||||||
|
{
|
||||||
|
// this.eventCategoriesHash[category] = value;
|
||||||
|
//TODO
|
||||||
|
} // SetEventCategories
|
||||||
|
|
||||||
|
public void AddToUIConfig(string itemName, string item)
|
||||||
|
{
|
||||||
|
uiConfigHash[itemName] = item;
|
||||||
|
} // SetUIConfig
|
||||||
|
|
||||||
|
public void AddClassifiedCategory(Int32 ID, string categoryName)
|
||||||
|
{
|
||||||
|
Hashtable hash = new Hashtable();
|
||||||
|
hash["category_name"] = categoryName;
|
||||||
|
hash["category_id"] = ID;
|
||||||
|
classifiedCategories.Add(hash);
|
||||||
|
// this.classifiedCategoriesHash.Clear();
|
||||||
|
} // SetClassifiedCategory
|
||||||
|
|
||||||
|
#region Properties
|
||||||
|
|
||||||
|
public string Login
|
||||||
|
{
|
||||||
|
get { return login; }
|
||||||
|
set { login = value; }
|
||||||
|
} // Login
|
||||||
|
|
||||||
|
public string DST
|
||||||
|
{
|
||||||
|
get { return dst; }
|
||||||
|
set { dst = value; }
|
||||||
|
} // DST
|
||||||
|
|
||||||
|
public string StipendSinceLogin
|
||||||
|
{
|
||||||
|
get { return stipendSinceLogin; }
|
||||||
|
set { stipendSinceLogin = value; }
|
||||||
|
} // StipendSinceLogin
|
||||||
|
|
||||||
|
public string Gendered
|
||||||
|
{
|
||||||
|
get { return gendered; }
|
||||||
|
set { gendered = value; }
|
||||||
|
} // Gendered
|
||||||
|
|
||||||
|
public string EverLoggedIn
|
||||||
|
{
|
||||||
|
get { return everLoggedIn; }
|
||||||
|
set { everLoggedIn = value; }
|
||||||
|
} // EverLoggedIn
|
||||||
|
|
||||||
|
public uint SimPort
|
||||||
|
{
|
||||||
|
get { return simPort; }
|
||||||
|
set { simPort = value; }
|
||||||
|
} // SimPort
|
||||||
|
|
||||||
|
public string SimAddress
|
||||||
|
{
|
||||||
|
get { return simAddress; }
|
||||||
|
set { simAddress = value; }
|
||||||
|
} // SimAddress
|
||||||
|
|
||||||
|
public LLUUID AgentID
|
||||||
|
{
|
||||||
|
get { return agentID; }
|
||||||
|
set { agentID = value; }
|
||||||
|
} // AgentID
|
||||||
|
|
||||||
|
public LLUUID SessionID
|
||||||
|
{
|
||||||
|
get { return sessionID; }
|
||||||
|
set { sessionID = value; }
|
||||||
|
} // SessionID
|
||||||
|
|
||||||
|
public LLUUID SecureSessionID
|
||||||
|
{
|
||||||
|
get { return secureSessionID; }
|
||||||
|
set { secureSessionID = value; }
|
||||||
|
} // SecureSessionID
|
||||||
|
|
||||||
|
public Int32 CircuitCode
|
||||||
|
{
|
||||||
|
get { return circuitCode; }
|
||||||
|
set { circuitCode = value; }
|
||||||
|
} // CircuitCode
|
||||||
|
|
||||||
|
public uint RegionX
|
||||||
|
{
|
||||||
|
get { return regionX; }
|
||||||
|
set { regionX = value; }
|
||||||
|
} // RegionX
|
||||||
|
|
||||||
|
public uint RegionY
|
||||||
|
{
|
||||||
|
get { return regionY; }
|
||||||
|
set { regionY = value; }
|
||||||
|
} // RegionY
|
||||||
|
|
||||||
|
public string SunTexture
|
||||||
|
{
|
||||||
|
get { return sunTexture; }
|
||||||
|
set { sunTexture = value; }
|
||||||
|
} // SunTexture
|
||||||
|
|
||||||
|
public string CloudTexture
|
||||||
|
{
|
||||||
|
get { return cloudTexture; }
|
||||||
|
set { cloudTexture = value; }
|
||||||
|
} // CloudTexture
|
||||||
|
|
||||||
|
public string MoonTexture
|
||||||
|
{
|
||||||
|
get { return moonTexture; }
|
||||||
|
set { moonTexture = value; }
|
||||||
|
} // MoonTexture
|
||||||
|
|
||||||
|
public string Firstname
|
||||||
|
{
|
||||||
|
get { return firstname; }
|
||||||
|
set { firstname = value; }
|
||||||
|
} // Firstname
|
||||||
|
|
||||||
|
public string Lastname
|
||||||
|
{
|
||||||
|
get { return lastname; }
|
||||||
|
set { lastname = value; }
|
||||||
|
} // Lastname
|
||||||
|
|
||||||
|
public string ClientVersion
|
||||||
|
{
|
||||||
|
get { return clientVersion; }
|
||||||
|
set { clientVersion = value; }
|
||||||
|
} //REX ClientVersion
|
||||||
|
|
||||||
|
public string AgentAccess
|
||||||
|
{
|
||||||
|
get { return agentAccess; }
|
||||||
|
set { agentAccess = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public string StartLocation
|
||||||
|
{
|
||||||
|
get { return startLocation; }
|
||||||
|
set { startLocation = value; }
|
||||||
|
} // StartLocation
|
||||||
|
|
||||||
|
public string LookAt
|
||||||
|
{
|
||||||
|
get { return lookAt; }
|
||||||
|
set { lookAt = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public string SeedCapability
|
||||||
|
{
|
||||||
|
get { return seedCapability; }
|
||||||
|
set { seedCapability = value; }
|
||||||
|
} // SeedCapability
|
||||||
|
|
||||||
|
public string ErrorReason
|
||||||
|
{
|
||||||
|
get { return errorReason; }
|
||||||
|
set { errorReason = value; }
|
||||||
|
} // ErrorReason
|
||||||
|
|
||||||
|
public string ErrorMessage
|
||||||
|
{
|
||||||
|
get { return errorMessage; }
|
||||||
|
set { errorMessage = value; }
|
||||||
|
} // ErrorMessage
|
||||||
|
|
||||||
|
public ArrayList InventoryRoot
|
||||||
|
{
|
||||||
|
get { return inventoryRoot; }
|
||||||
|
set { inventoryRoot = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public ArrayList InventorySkeleton
|
||||||
|
{
|
||||||
|
get { return agentInventory; }
|
||||||
|
set { agentInventory = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public ArrayList InventoryLibrary
|
||||||
|
{
|
||||||
|
get { return inventoryLibrary; }
|
||||||
|
set { inventoryLibrary = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public ArrayList InventoryLibraryOwner
|
||||||
|
{
|
||||||
|
get { return inventoryLibraryOwner; }
|
||||||
|
set { inventoryLibraryOwner = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public ArrayList InventoryLibRoot
|
||||||
|
{
|
||||||
|
get { return inventoryLibRoot; }
|
||||||
|
set { inventoryLibRoot = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Home
|
||||||
|
{
|
||||||
|
get { return home; }
|
||||||
|
set { home = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Message
|
||||||
|
{
|
||||||
|
get { return welcomeMessage; }
|
||||||
|
set { welcomeMessage = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public BuddyList BuddList
|
||||||
|
{
|
||||||
|
get { return m_buddyList; }
|
||||||
|
set { m_buddyList = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
public class UserInfo
|
||||||
|
{
|
||||||
|
public string firstname;
|
||||||
|
public string lastname;
|
||||||
|
public ulong homeregionhandle;
|
||||||
|
public LLVector3 homepos;
|
||||||
|
public LLVector3 homelookat;
|
||||||
|
}
|
||||||
|
|
||||||
|
public class BuddyList
|
||||||
|
{
|
||||||
|
public List<BuddyInfo> Buddies = new List<BuddyInfo>();
|
||||||
|
|
||||||
|
public void AddNewBuddy(BuddyInfo buddy)
|
||||||
|
{
|
||||||
|
if (!Buddies.Contains(buddy))
|
||||||
|
{
|
||||||
|
Buddies.Add(buddy);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public ArrayList ToArray()
|
||||||
|
{
|
||||||
|
ArrayList buddyArray = new ArrayList();
|
||||||
|
foreach (BuddyInfo buddy in Buddies)
|
||||||
|
{
|
||||||
|
buddyArray.Add(buddy.ToHashTable());
|
||||||
|
}
|
||||||
|
return buddyArray;
|
||||||
|
}
|
||||||
|
|
||||||
|
public class BuddyInfo
|
||||||
|
{
|
||||||
|
public int BuddyRightsHave = 1;
|
||||||
|
public int BuddyRightsGiven = 1;
|
||||||
|
public LLUUID BuddyID;
|
||||||
|
|
||||||
|
public BuddyInfo(string buddyID)
|
||||||
|
{
|
||||||
|
BuddyID = new LLUUID(buddyID);
|
||||||
|
}
|
||||||
|
|
||||||
|
public BuddyInfo(LLUUID buddyID)
|
||||||
|
{
|
||||||
|
BuddyID = buddyID;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Hashtable ToHashTable()
|
||||||
|
{
|
||||||
|
Hashtable hTable = new Hashtable();
|
||||||
|
hTable["buddy_rights_has"] = BuddyRightsHave;
|
||||||
|
hTable["buddy_rights_given"] = BuddyRightsGiven;
|
||||||
|
hTable["buddy_id"] = BuddyID.ToString();
|
||||||
|
return hTable;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,620 @@
|
||||||
|
/*
|
||||||
|
* 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 OpenSim 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.Threading;
|
||||||
|
using libsecondlife;
|
||||||
|
using libsecondlife.StructuredData;
|
||||||
|
using Nwc.XmlRpc;
|
||||||
|
|
||||||
|
using OpenSim.Framework.Communications.Cache;
|
||||||
|
using OpenSim.Framework.Console;
|
||||||
|
|
||||||
|
namespace OpenSim.Framework.UserManagement
|
||||||
|
{
|
||||||
|
public class LoginService
|
||||||
|
{
|
||||||
|
protected string m_welcomeMessage = "Welcome to OpenSim";
|
||||||
|
protected UserManagerBase m_userManager = null;
|
||||||
|
protected Mutex m_loginMutex = new Mutex(false);
|
||||||
|
protected Boolean m_rexMode;
|
||||||
|
protected RexLoginHandler m_rexLoginHandler;
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Used during login to send the skeleton of the OpenSim Library to the client.
|
||||||
|
/// </summary>
|
||||||
|
protected LibraryRootFolder m_libraryRootFolder;
|
||||||
|
|
||||||
|
public LoginService(
|
||||||
|
UserManagerBase userManager, LibraryRootFolder libraryRootFolder, string welcomeMess, Boolean rexMode)
|
||||||
|
{
|
||||||
|
m_userManager = userManager;
|
||||||
|
m_libraryRootFolder = libraryRootFolder;
|
||||||
|
m_rexMode = rexMode;
|
||||||
|
m_userManager.RexMode = rexMode;
|
||||||
|
if (m_rexMode)
|
||||||
|
m_rexLoginHandler = new RexLoginHandler(this, m_userManager);
|
||||||
|
|
||||||
|
if (welcomeMess != "")
|
||||||
|
{
|
||||||
|
m_welcomeMessage = welcomeMess;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Main user login function
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="request">The XMLRPC request</param>
|
||||||
|
/// <returns>The response to send</returns>
|
||||||
|
public XmlRpcResponse XmlRpcLoginMethod(XmlRpcRequest request)
|
||||||
|
{
|
||||||
|
// Temporary fix
|
||||||
|
m_loginMutex.WaitOne();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (!m_rexMode)
|
||||||
|
{
|
||||||
|
//CFK: CustomizeResponse contains sufficient strings to alleviate the need for this.
|
||||||
|
//CKF: MainLog.Instance.Verbose("LOGIN", "Attempting login now...");
|
||||||
|
XmlRpcResponse response = new XmlRpcResponse();
|
||||||
|
Hashtable requestData = (Hashtable) request.Params[0];
|
||||||
|
|
||||||
|
bool GoodXML = (requestData.Contains("first") && requestData.Contains("last") &&
|
||||||
|
requestData.Contains("passwd"));
|
||||||
|
bool GoodLogin = false;
|
||||||
|
|
||||||
|
UserProfileData userProfile;
|
||||||
|
LoginResponse logResponse = new LoginResponse();
|
||||||
|
|
||||||
|
if (GoodXML)
|
||||||
|
{
|
||||||
|
string firstname = (string) requestData["first"];
|
||||||
|
string lastname = (string) requestData["last"];
|
||||||
|
string passwd = (string) requestData["passwd"];
|
||||||
|
|
||||||
|
userProfile = GetTheUser(firstname, lastname, "");
|
||||||
|
if (userProfile == null)
|
||||||
|
{
|
||||||
|
MainLog.Instance.Verbose(
|
||||||
|
"LOGIN",
|
||||||
|
"Could not find a profile for " + firstname + " " + lastname);
|
||||||
|
|
||||||
|
return logResponse.CreateLoginFailedResponse();
|
||||||
|
}
|
||||||
|
|
||||||
|
GoodLogin = AuthenticateUser(userProfile, passwd);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return logResponse.CreateGridErrorResponse();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!GoodLogin)
|
||||||
|
{
|
||||||
|
return logResponse.CreateLoginFailedResponse();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// If we already have a session...
|
||||||
|
|
||||||
|
if (userProfile.currentAgent != null && userProfile.currentAgent.agentOnline)
|
||||||
|
{
|
||||||
|
userProfile.currentAgent = null;
|
||||||
|
m_userManager.CommitAgent(ref userProfile);
|
||||||
|
|
||||||
|
// Reject the login
|
||||||
|
return logResponse.CreateAlreadyLoggedInResponse();
|
||||||
|
}
|
||||||
|
// Otherwise...
|
||||||
|
// Create a new agent session
|
||||||
|
CreateAgent(userProfile, request);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
LLUUID agentID = userProfile.UUID;
|
||||||
|
|
||||||
|
// Inventory Library Section
|
||||||
|
InventoryData inventData = CreateInventoryData(agentID);
|
||||||
|
ArrayList AgentInventoryArray = inventData.InventoryArray;
|
||||||
|
|
||||||
|
Hashtable InventoryRootHash = new Hashtable();
|
||||||
|
InventoryRootHash["folder_id"] = inventData.RootFolderID.ToString();
|
||||||
|
ArrayList InventoryRoot = new ArrayList();
|
||||||
|
InventoryRoot.Add(InventoryRootHash);
|
||||||
|
userProfile.rootInventoryFolderID = inventData.RootFolderID;
|
||||||
|
|
||||||
|
// Circuit Code
|
||||||
|
uint circode = (uint) (Util.RandomClass.Next());
|
||||||
|
|
||||||
|
//REX: Get client version
|
||||||
|
if (requestData.ContainsKey("version"))
|
||||||
|
{
|
||||||
|
logResponse.ClientVersion = (string)requestData["version"];
|
||||||
|
}
|
||||||
|
|
||||||
|
logResponse.Lastname = userProfile.surname;
|
||||||
|
logResponse.Firstname = userProfile.username;
|
||||||
|
logResponse.AgentID = agentID.ToString();
|
||||||
|
logResponse.SessionID = userProfile.currentAgent.sessionID.ToString();
|
||||||
|
logResponse.SecureSessionID = userProfile.currentAgent.secureSessionID.ToString();
|
||||||
|
logResponse.InventoryRoot = InventoryRoot;
|
||||||
|
logResponse.InventorySkeleton = AgentInventoryArray;
|
||||||
|
logResponse.InventoryLibrary = GetInventoryLibrary();
|
||||||
|
|
||||||
|
Hashtable InventoryLibRootHash = new Hashtable();
|
||||||
|
InventoryLibRootHash["folder_id"] = "00000112-000f-0000-0000-000100bba000";
|
||||||
|
ArrayList InventoryLibRoot = new ArrayList();
|
||||||
|
InventoryLibRoot.Add(InventoryLibRootHash);
|
||||||
|
logResponse.InventoryLibRoot = InventoryLibRoot;
|
||||||
|
|
||||||
|
logResponse.InventoryLibraryOwner = GetLibraryOwner();
|
||||||
|
logResponse.CircuitCode = (Int32) circode;
|
||||||
|
//logResponse.RegionX = 0; //overwritten
|
||||||
|
//logResponse.RegionY = 0; //overwritten
|
||||||
|
logResponse.Home = "!!null temporary value {home}!!"; // Overwritten
|
||||||
|
//logResponse.LookAt = "\n[r" + TheUser.homeLookAt.X.ToString() + ",r" + TheUser.homeLookAt.Y.ToString() + ",r" + TheUser.homeLookAt.Z.ToString() + "]\n";
|
||||||
|
//logResponse.SimAddress = "127.0.0.1"; //overwritten
|
||||||
|
//logResponse.SimPort = 0; //overwritten
|
||||||
|
logResponse.Message = GetMessage();
|
||||||
|
logResponse.BuddList = ConvertFriendListItem(m_userManager.GetUserFriendList(agentID));
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
CustomiseResponse(logResponse, userProfile, null);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
MainLog.Instance.Verbose("LOGIN", e.ToString());
|
||||||
|
return logResponse.CreateDeadRegionResponse();
|
||||||
|
//return logResponse.ToXmlRpcResponse();
|
||||||
|
}
|
||||||
|
CommitAgent(ref userProfile);
|
||||||
|
return logResponse.ToXmlRpcResponse();
|
||||||
|
}
|
||||||
|
|
||||||
|
catch (Exception E)
|
||||||
|
{
|
||||||
|
MainLog.Instance.Verbose("LOGIN", E.ToString());
|
||||||
|
}
|
||||||
|
//}
|
||||||
|
}
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return m_rexLoginHandler.XmlRpcLoginMethod(request);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
m_loginMutex.ReleaseMutex();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public LLSD LLSDLoginMethod(LLSD request)
|
||||||
|
{
|
||||||
|
|
||||||
|
// Temporary fix
|
||||||
|
m_loginMutex.WaitOne();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (!m_rexMode)
|
||||||
|
{
|
||||||
|
bool GoodLogin = false;
|
||||||
|
string clientVersion = "not set"; //rex
|
||||||
|
|
||||||
|
UserProfileData userProfile = null;
|
||||||
|
LoginResponse logResponse = new LoginResponse();
|
||||||
|
|
||||||
|
if (request.Type == LLSDType.Map)
|
||||||
|
{
|
||||||
|
LLSDMap map = (LLSDMap)request;
|
||||||
|
|
||||||
|
if (map.ContainsKey("first") && map.ContainsKey("last") && map.ContainsKey("passwd"))
|
||||||
|
{
|
||||||
|
string firstname = map["first"].AsString();
|
||||||
|
string lastname = map["last"].AsString();
|
||||||
|
string passwd = map["passwd"].AsString();
|
||||||
|
|
||||||
|
//REX: Client version
|
||||||
|
if (map.ContainsKey("version"))
|
||||||
|
{
|
||||||
|
clientVersion = map["version"].AsString();
|
||||||
|
}
|
||||||
|
|
||||||
|
userProfile = GetTheUser(firstname, lastname, "");
|
||||||
|
if (userProfile == null)
|
||||||
|
{
|
||||||
|
MainLog.Instance.Verbose(
|
||||||
|
"LOGIN",
|
||||||
|
"Could not find a profile for " + firstname + " " + lastname);
|
||||||
|
|
||||||
|
return logResponse.CreateLoginFailedResponseLLSD();
|
||||||
|
}
|
||||||
|
|
||||||
|
GoodLogin = AuthenticateUser(userProfile, passwd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!GoodLogin)
|
||||||
|
{
|
||||||
|
return logResponse.CreateLoginFailedResponseLLSD();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// If we already have a session...
|
||||||
|
if (userProfile.currentAgent != null && userProfile.currentAgent.agentOnline)
|
||||||
|
{
|
||||||
|
userProfile.currentAgent = null;
|
||||||
|
m_userManager.CommitAgent(ref userProfile);
|
||||||
|
|
||||||
|
// Reject the login
|
||||||
|
return logResponse.CreateAlreadyLoggedInResponseLLSD();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise...
|
||||||
|
// Create a new agent session
|
||||||
|
CreateAgent(userProfile, request);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
LLUUID agentID = userProfile.UUID;
|
||||||
|
|
||||||
|
// Inventory Library Section
|
||||||
|
InventoryData inventData = CreateInventoryData(agentID);
|
||||||
|
ArrayList AgentInventoryArray = inventData.InventoryArray;
|
||||||
|
|
||||||
|
Hashtable InventoryRootHash = new Hashtable();
|
||||||
|
InventoryRootHash["folder_id"] = inventData.RootFolderID.ToString();
|
||||||
|
ArrayList InventoryRoot = new ArrayList();
|
||||||
|
InventoryRoot.Add(InventoryRootHash);
|
||||||
|
userProfile.rootInventoryFolderID = inventData.RootFolderID;
|
||||||
|
|
||||||
|
// Circuit Code
|
||||||
|
uint circode = (uint)(Util.RandomClass.Next());
|
||||||
|
|
||||||
|
// REX: Set client version
|
||||||
|
logResponse.ClientVersion = clientVersion;
|
||||||
|
|
||||||
|
logResponse.Lastname = userProfile.surname;
|
||||||
|
logResponse.Firstname = userProfile.username;
|
||||||
|
logResponse.AgentID = agentID.ToString();
|
||||||
|
logResponse.SessionID = userProfile.currentAgent.sessionID.ToString();
|
||||||
|
logResponse.SecureSessionID = userProfile.currentAgent.secureSessionID.ToString();
|
||||||
|
logResponse.InventoryRoot = InventoryRoot;
|
||||||
|
logResponse.InventorySkeleton = AgentInventoryArray;
|
||||||
|
logResponse.InventoryLibrary = GetInventoryLibrary();
|
||||||
|
|
||||||
|
Hashtable InventoryLibRootHash = new Hashtable();
|
||||||
|
InventoryLibRootHash["folder_id"] = "00000112-000f-0000-0000-000100bba000";
|
||||||
|
ArrayList InventoryLibRoot = new ArrayList();
|
||||||
|
InventoryLibRoot.Add(InventoryLibRootHash);
|
||||||
|
logResponse.InventoryLibRoot = InventoryLibRoot;
|
||||||
|
|
||||||
|
logResponse.InventoryLibraryOwner = GetLibraryOwner();
|
||||||
|
logResponse.CircuitCode = (Int32)circode;
|
||||||
|
//logResponse.RegionX = 0; //overwritten
|
||||||
|
//logResponse.RegionY = 0; //overwritten
|
||||||
|
logResponse.Home = "!!null temporary value {home}!!"; // Overwritten
|
||||||
|
//logResponse.LookAt = "\n[r" + TheUser.homeLookAt.X.ToString() + ",r" + TheUser.homeLookAt.Y.ToString() + ",r" + TheUser.homeLookAt.Z.ToString() + "]\n";
|
||||||
|
//logResponse.SimAddress = "127.0.0.1"; //overwritten
|
||||||
|
//logResponse.SimPort = 0; //overwritten
|
||||||
|
logResponse.Message = GetMessage();
|
||||||
|
logResponse.BuddList = ConvertFriendListItem(m_userManager.GetUserFriendList(agentID));
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
CustomiseResponse(logResponse, userProfile, null);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
MainLog.Instance.Verbose("LOGIN", ex.ToString());
|
||||||
|
return logResponse.CreateDeadRegionResponseLLSD();
|
||||||
|
}
|
||||||
|
|
||||||
|
CommitAgent(ref userProfile);
|
||||||
|
|
||||||
|
return logResponse.ToLLSDResponse();
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
MainLog.Instance.Verbose("LOGIN", ex.ToString());
|
||||||
|
return logResponse.CreateFailedResponseLLSD();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return m_rexLoginHandler.LLSDLoginMethod(request);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
m_loginMutex.ReleaseMutex();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
/// <summary>
|
||||||
|
/// Remove agent
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="request">The XMLRPC request</param>
|
||||||
|
/// <returns>The response to send</returns>
|
||||||
|
public XmlRpcResponse XmlRpcRemoveAgentMethod(XmlRpcRequest request)
|
||||||
|
{
|
||||||
|
// Temporary fix
|
||||||
|
m_loginMutex.WaitOne();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
MainLog.Instance.Verbose("REMOVE AGENT", "Attempting to remove agent...");
|
||||||
|
XmlRpcResponse response = new XmlRpcResponse();
|
||||||
|
Hashtable requestData = (Hashtable)request.Params[0];
|
||||||
|
|
||||||
|
bool parametersValid = (requestData.Contains("agentID"));
|
||||||
|
|
||||||
|
UserProfileData user;
|
||||||
|
LoginResponse logResponse = new LoginResponse();
|
||||||
|
|
||||||
|
if (parametersValid)
|
||||||
|
{
|
||||||
|
string agentID = (string)requestData["agentID"];
|
||||||
|
user = GetTheUser((libsecondlife.LLUUID)agentID);
|
||||||
|
|
||||||
|
if (user == null)
|
||||||
|
{
|
||||||
|
MainLog.Instance.Verbose("REMOVE AGENT", "Failed. UserProfile not found.");
|
||||||
|
return logResponse.CreateAgentRemoveFailedResponse();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (user != null)
|
||||||
|
{
|
||||||
|
ClearUserAgent(ref user, user.authenticationAddr);
|
||||||
|
MainLog.Instance.Verbose("REMOVE AGENT", "Success. Agent removed from database. UUID = " + user.UUID);
|
||||||
|
return logResponse.GenerateAgentRemoveSuccessResponse();
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MainLog.Instance.Verbose("REMOVE AGENT", "Failed. Parameters invalid.");
|
||||||
|
return logResponse.CreateAgentRemoveFailedResponse();
|
||||||
|
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
m_loginMutex.ReleaseMutex();
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
|
||||||
|
}//*/
|
||||||
|
|
||||||
|
public void ClearUserAgent(ref UserProfileData profile, string authAddr)
|
||||||
|
{
|
||||||
|
m_userManager.clearUserAgent(profile.UUID, authAddr);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Customises the login response and fills in missing values.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="response">The existing response</param>
|
||||||
|
/// <param name="theUser">The user profile</param>
|
||||||
|
public virtual void CustomiseResponse(LoginResponse response, UserProfileData theUser, string ASaddress)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Saves a target agent to the database
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="profile">The users profile</param>
|
||||||
|
/// <returns>Successful?</returns>
|
||||||
|
public void UpdateAgent(UserAgentData agent, string authAddr)
|
||||||
|
{
|
||||||
|
// Saves the agent to database
|
||||||
|
//return true;
|
||||||
|
m_userManager.UpdateUserAgentData(agent.UUID, agent.agentOnline, agent.currentPos, agent.logoutTime, authAddr);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Saves a target agent to the database
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="profile">The users profile</param>
|
||||||
|
/// <returns>Successful?</returns>
|
||||||
|
public bool CommitAgent(ref UserProfileData profile)
|
||||||
|
{
|
||||||
|
return m_userManager.CommitAgent(ref profile);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Checks a user against it's password hash
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="profile">The users profile</param>
|
||||||
|
/// <param name="password">The supplied password</param>
|
||||||
|
/// <returns>Authenticated?</returns>
|
||||||
|
public virtual bool AuthenticateUser(UserProfileData profile, string password)
|
||||||
|
{
|
||||||
|
MainLog.Instance.Verbose(
|
||||||
|
"LOGIN", "Authenticating {0} {1} ({2})", profile.username, profile.surname, profile.UUID);
|
||||||
|
|
||||||
|
password = password.Remove(0, 3); //remove $1$
|
||||||
|
|
||||||
|
string s = Util.Md5Hash(password + ":" + profile.passwordSalt);
|
||||||
|
|
||||||
|
return profile.passwordHash.Equals(s.ToString(), StringComparison.InvariantCultureIgnoreCase);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="profile"></param>
|
||||||
|
/// <param name="request"></param>
|
||||||
|
public void CreateAgent(UserProfileData profile, XmlRpcRequest request)
|
||||||
|
{
|
||||||
|
m_userManager.CreateAgent(profile, request);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void CreateAgent(UserProfileData profile, LLSD request)
|
||||||
|
{
|
||||||
|
m_userManager.CreateAgent(profile, request);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="firstname"></param>
|
||||||
|
/// <param name="lastname"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public virtual UserProfileData GetTheUser(string firstname, string lastname, string authAddr)
|
||||||
|
{
|
||||||
|
return m_userManager.GetUserProfile(firstname, lastname, authAddr);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get user according to uid
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="userUID"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public virtual UserProfileData GetTheUser(LLUUID userUID)
|
||||||
|
{
|
||||||
|
return this.m_userManager.GetUserProfile(userUID, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get user according to account
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="account"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public virtual UserProfileData GetTheUserByAccount(string account)
|
||||||
|
{
|
||||||
|
return this.m_userManager.GetUserProfileByAccount(account);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
public virtual string GetMessage()
|
||||||
|
{
|
||||||
|
return m_welcomeMessage;
|
||||||
|
}
|
||||||
|
|
||||||
|
private LoginResponse.BuddyList ConvertFriendListItem(List<FriendListItem> LFL)
|
||||||
|
{
|
||||||
|
LoginResponse.BuddyList buddylistreturn = new LoginResponse.BuddyList();
|
||||||
|
foreach (FriendListItem fl in LFL)
|
||||||
|
{
|
||||||
|
LoginResponse.BuddyList.BuddyInfo buddyitem = new LoginResponse.BuddyList.BuddyInfo(fl.Friend);
|
||||||
|
buddyitem.BuddyID = fl.Friend;
|
||||||
|
buddyitem.BuddyRightsHave = (int)fl.FriendListOwnerPerms;
|
||||||
|
buddyitem.BuddyRightsGiven = (int) fl.FriendPerms;
|
||||||
|
buddylistreturn.AddNewBuddy(buddyitem);
|
||||||
|
|
||||||
|
}
|
||||||
|
return buddylistreturn;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Converts the inventory library skeleton into the form required by the rpc request.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
protected internal virtual ArrayList GetInventoryLibrary()
|
||||||
|
{
|
||||||
|
Dictionary<LLUUID, InventoryFolderImpl> rootFolders
|
||||||
|
= m_libraryRootFolder.RequestSelfAndDescendentFolders();
|
||||||
|
ArrayList folderHashes = new ArrayList();
|
||||||
|
|
||||||
|
foreach (InventoryFolderBase folder in rootFolders.Values)
|
||||||
|
{
|
||||||
|
Hashtable TempHash = new Hashtable();
|
||||||
|
TempHash["name"] = folder.name;
|
||||||
|
TempHash["parent_id"] = folder.parentID.ToString();
|
||||||
|
TempHash["version"] = (Int32)folder.version;
|
||||||
|
TempHash["type_default"] = (Int32)folder.type;
|
||||||
|
TempHash["folder_id"] = folder.folderID.ToString();
|
||||||
|
folderHashes.Add(TempHash);
|
||||||
|
}
|
||||||
|
|
||||||
|
return folderHashes;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
protected internal virtual ArrayList GetLibraryOwner()
|
||||||
|
{
|
||||||
|
//for now create random inventory library owner
|
||||||
|
Hashtable TempHash = new Hashtable();
|
||||||
|
TempHash["agent_id"] = "11111111-1111-0000-0000-000100bba000";
|
||||||
|
ArrayList inventoryLibOwner = new ArrayList();
|
||||||
|
inventoryLibOwner.Add(TempHash);
|
||||||
|
return inventoryLibOwner;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected internal virtual InventoryData CreateInventoryData(LLUUID userID)
|
||||||
|
{
|
||||||
|
AgentInventory userInventory = new AgentInventory();
|
||||||
|
userInventory.CreateRootFolder(userID, false);
|
||||||
|
|
||||||
|
ArrayList AgentInventoryArray = new ArrayList();
|
||||||
|
Hashtable TempHash;
|
||||||
|
foreach (InventoryFolder InvFolder in userInventory.InventoryFolders.Values)
|
||||||
|
{
|
||||||
|
TempHash = new Hashtable();
|
||||||
|
TempHash["name"] = InvFolder.FolderName;
|
||||||
|
TempHash["parent_id"] = InvFolder.ParentID.ToString();
|
||||||
|
TempHash["version"] = (Int32) InvFolder.Version;
|
||||||
|
TempHash["type_default"] = (Int32) InvFolder.DefaultType;
|
||||||
|
TempHash["folder_id"] = InvFolder.FolderID.ToString();
|
||||||
|
AgentInventoryArray.Add(TempHash);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new InventoryData(AgentInventoryArray, userInventory.InventoryRoot.FolderID);
|
||||||
|
}
|
||||||
|
|
||||||
|
public class InventoryData
|
||||||
|
{
|
||||||
|
public ArrayList InventoryArray = null;
|
||||||
|
public LLUUID RootFolderID = LLUUID.Zero;
|
||||||
|
|
||||||
|
public InventoryData(ArrayList invList, LLUUID rootID)
|
||||||
|
{
|
||||||
|
InventoryArray = invList;
|
||||||
|
RootFolderID = rootID;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,65 @@
|
||||||
|
/*
|
||||||
|
* 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 OpenSim Project nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
||||||
|
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
// General Information about an assembly is controlled through the following
|
||||||
|
// set of attributes. Change these attribute values to modify the information
|
||||||
|
// associated with an assembly.
|
||||||
|
|
||||||
|
[assembly : AssemblyTitle("OpenGrid.Framework.Communications")]
|
||||||
|
[assembly : AssemblyDescription("")]
|
||||||
|
[assembly : AssemblyConfiguration("")]
|
||||||
|
[assembly : AssemblyCompany("")]
|
||||||
|
[assembly : AssemblyProduct("OpenGrid.Framework.Communications")]
|
||||||
|
[assembly : AssemblyCopyright("Copyright © 2007")]
|
||||||
|
[assembly : AssemblyTrademark("")]
|
||||||
|
[assembly : AssemblyCulture("")]
|
||||||
|
|
||||||
|
// Setting ComVisible to false makes the types in this assembly not visible
|
||||||
|
// to COM components. If you need to access a type in this assembly from
|
||||||
|
// COM, set the ComVisible attribute to true on that type.
|
||||||
|
|
||||||
|
[assembly : ComVisible(false)]
|
||||||
|
|
||||||
|
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||||
|
|
||||||
|
[assembly : Guid("13e7c396-78a9-4a5c-baf2-6f980ea75d95")]
|
||||||
|
|
||||||
|
// Version information for an assembly consists of the following four values:
|
||||||
|
//
|
||||||
|
// Major Version
|
||||||
|
// Minor Version
|
||||||
|
// Build Number
|
||||||
|
// Revision
|
||||||
|
//
|
||||||
|
// You can specify all the values or you can default the Revision and Build Numbers
|
||||||
|
// by using the '*' as shown below:
|
||||||
|
|
||||||
|
[assembly : AssemblyVersion("1.0.0.0")]
|
||||||
|
[assembly : AssemblyFileVersion("1.0.0.0")]
|
|
@ -0,0 +1,186 @@
|
||||||
|
/*
|
||||||
|
* 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 OpenSim 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.Threading;
|
||||||
|
|
||||||
|
namespace OpenSim.Framework.Communications
|
||||||
|
{
|
||||||
|
internal class SimpleAsyncResult : IAsyncResult
|
||||||
|
{
|
||||||
|
private readonly AsyncCallback m_callback;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Is process completed?
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>Should really be boolean, but VolatileRead has no boolean method</remarks>
|
||||||
|
private byte m_completed;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Did process complete synchroneously?
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>I have a hard time imagining a scenario where this is the case, again, same issue about
|
||||||
|
/// booleans and VolatileRead as m_completed
|
||||||
|
/// </remarks>
|
||||||
|
private byte m_completedSynchronously;
|
||||||
|
|
||||||
|
private readonly object m_asyncState;
|
||||||
|
private ManualResetEvent m_waitHandle;
|
||||||
|
private Exception m_exception;
|
||||||
|
|
||||||
|
internal SimpleAsyncResult(AsyncCallback cb, object state)
|
||||||
|
{
|
||||||
|
m_callback = cb;
|
||||||
|
m_asyncState = state;
|
||||||
|
m_completed = 0;
|
||||||
|
m_completedSynchronously = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#region IAsyncResult Members
|
||||||
|
|
||||||
|
public object AsyncState
|
||||||
|
{
|
||||||
|
get { return m_asyncState; }
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public WaitHandle AsyncWaitHandle
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (m_waitHandle == null)
|
||||||
|
{
|
||||||
|
bool done = IsCompleted;
|
||||||
|
ManualResetEvent mre = new ManualResetEvent(done);
|
||||||
|
if (Interlocked.CompareExchange(ref m_waitHandle, mre, null) != null)
|
||||||
|
{
|
||||||
|
mre.Close();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!done && IsCompleted)
|
||||||
|
{
|
||||||
|
m_waitHandle.Set();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return m_waitHandle;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public bool CompletedSynchronously
|
||||||
|
{
|
||||||
|
get { return Thread.VolatileRead(ref m_completedSynchronously) == 1; }
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public bool IsCompleted
|
||||||
|
{
|
||||||
|
get { return Thread.VolatileRead(ref m_completed) == 1; }
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region class Methods
|
||||||
|
|
||||||
|
internal void SetAsCompleted(bool completedSynchronously)
|
||||||
|
{
|
||||||
|
m_completed = 1;
|
||||||
|
if (completedSynchronously)
|
||||||
|
m_completedSynchronously = 1;
|
||||||
|
else
|
||||||
|
m_completedSynchronously = 0;
|
||||||
|
|
||||||
|
SignalCompletion();
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void HandleException(Exception e, bool completedSynchronously)
|
||||||
|
{
|
||||||
|
m_completed = 1;
|
||||||
|
if (completedSynchronously)
|
||||||
|
m_completedSynchronously = 1;
|
||||||
|
else
|
||||||
|
m_completedSynchronously = 0;
|
||||||
|
m_exception = e;
|
||||||
|
|
||||||
|
SignalCompletion();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SignalCompletion()
|
||||||
|
{
|
||||||
|
if (m_waitHandle != null) m_waitHandle.Set();
|
||||||
|
|
||||||
|
if (m_callback != null) m_callback(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void EndInvoke()
|
||||||
|
{
|
||||||
|
// This method assumes that only 1 thread calls EndInvoke
|
||||||
|
if (!IsCompleted)
|
||||||
|
{
|
||||||
|
// If the operation isn't done, wait for it
|
||||||
|
AsyncWaitHandle.WaitOne();
|
||||||
|
AsyncWaitHandle.Close();
|
||||||
|
m_waitHandle = null; // Allow early GC
|
||||||
|
}
|
||||||
|
|
||||||
|
// Operation is done: if an exception occured, throw it
|
||||||
|
if (m_exception != null) throw m_exception;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class AsyncResult<T> : SimpleAsyncResult
|
||||||
|
{
|
||||||
|
private T m_result = default(T);
|
||||||
|
|
||||||
|
public AsyncResult(AsyncCallback asyncCallback, Object state) :
|
||||||
|
base(asyncCallback, state)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void SetAsCompleted(T result, bool completedSynchronously)
|
||||||
|
{
|
||||||
|
// Save the asynchronous operation's result
|
||||||
|
m_result = result;
|
||||||
|
|
||||||
|
// Tell the base class that the operation completed
|
||||||
|
// sucessfully (no exception)
|
||||||
|
base.SetAsCompleted(completedSynchronously);
|
||||||
|
}
|
||||||
|
|
||||||
|
public new T EndInvoke()
|
||||||
|
{
|
||||||
|
base.EndInvoke();
|
||||||
|
return m_result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,443 @@
|
||||||
|
/*
|
||||||
|
* 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 OpenSim Project nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
||||||
|
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Net;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Web;
|
||||||
|
using OpenSim.Framework.Console;
|
||||||
|
|
||||||
|
namespace OpenSim.Framework.Communications
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Implementation of a generic REST client
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// This class is a generic implementation of a REST (Representational State Transfer) web service. This
|
||||||
|
/// class is designed to execute both synchroneously and asynchroneously.
|
||||||
|
///
|
||||||
|
/// Internally the implementation works as a two stage asynchroneous web-client.
|
||||||
|
/// When the request is initiated, RestClient will query asynchroneously for for a web-response,
|
||||||
|
/// sleeping until the initial response is returned by the server. Once the initial response is retrieved
|
||||||
|
/// the second stage of asynchroneous requests will be triggered, in an attempt to read of the response
|
||||||
|
/// object into a memorystream as a sequence of asynchroneous reads.
|
||||||
|
///
|
||||||
|
/// The asynchronisity of RestClient is designed to move as much processing into the back-ground, allowing
|
||||||
|
/// other threads to execute, while it waits for a response from the web-service. RestClient it self, can be
|
||||||
|
/// invoked by the caller in either synchroneous mode or asynchroneous mode.
|
||||||
|
/// </remarks>
|
||||||
|
public class RestClient
|
||||||
|
{
|
||||||
|
private string realuri;
|
||||||
|
|
||||||
|
#region member variables
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The base Uri of the web-service e.g. http://www.google.com
|
||||||
|
/// </summary>
|
||||||
|
private string _url;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Path elements of the query
|
||||||
|
/// </summary>
|
||||||
|
private List<string> _pathElements = new List<string>();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Parameter elements of the query, e.g. min=34
|
||||||
|
/// </summary>
|
||||||
|
private Dictionary<string, string> _parameterElements = new Dictionary<string, string>();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Request method. E.g. GET, POST, PUT or DELETE
|
||||||
|
/// </summary>
|
||||||
|
private string _method;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Temporary buffer used to store bytes temporarily as they come in from the server
|
||||||
|
/// </summary>
|
||||||
|
private byte[] _readbuf;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// MemoryStream representing the resultiong resource
|
||||||
|
/// </summary>
|
||||||
|
private Stream _resource;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// WebRequest object, held as a member variable
|
||||||
|
/// </summary>
|
||||||
|
private HttpWebRequest _request;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// WebResponse object, held as a member variable, so we can close it
|
||||||
|
/// </summary>
|
||||||
|
private HttpWebResponse _response;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// This flag will help block the main synchroneous method, in case we run in synchroneous mode
|
||||||
|
/// </summary>
|
||||||
|
public static ManualResetEvent _allDone = new ManualResetEvent(false);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Default time out period
|
||||||
|
/// </summary>
|
||||||
|
private const int DefaultTimeout = 10*1000; // 10 seconds timeout
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Default Buffer size of a block requested from the web-server
|
||||||
|
/// </summary>
|
||||||
|
private const int BufferSize = 4096; // Read blocks of 4 KB.
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// if an exception occours during async processing, we need to save it, so it can be
|
||||||
|
/// rethrown on the primary thread;
|
||||||
|
/// </summary>
|
||||||
|
private Exception _asyncException;
|
||||||
|
|
||||||
|
#endregion member variables
|
||||||
|
|
||||||
|
#region constructors
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Instantiate a new RestClient
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="url">Web-service to query, e.g. http://osgrid.org:8003</param>
|
||||||
|
public RestClient(string url)
|
||||||
|
{
|
||||||
|
_url = url;
|
||||||
|
_readbuf = new byte[BufferSize];
|
||||||
|
_resource = new MemoryStream();
|
||||||
|
_request = null;
|
||||||
|
_response = null;
|
||||||
|
_lock = new object();
|
||||||
|
}
|
||||||
|
|
||||||
|
private object _lock;
|
||||||
|
|
||||||
|
#endregion constructors
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Add a path element to the query, e.g. assets
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="element">path entry</param>
|
||||||
|
public void AddResourcePath(string element)
|
||||||
|
{
|
||||||
|
if (isSlashed(element))
|
||||||
|
_pathElements.Add(element.Substring(0, element.Length - 1));
|
||||||
|
else
|
||||||
|
_pathElements.Add(element);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Add a query parameter to the Url
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="name">Name of the parameter, e.g. min</param>
|
||||||
|
/// <param name="value">Value of the parameter, e.g. 42</param>
|
||||||
|
public void AddQueryParameter(string name, string value)
|
||||||
|
{
|
||||||
|
_parameterElements.Add(HttpUtility.UrlEncode(name), HttpUtility.UrlEncode(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Add a query parameter to the Url
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="name">Name of the parameter, e.g. min</param>
|
||||||
|
public void AddQueryParameter(string name)
|
||||||
|
{
|
||||||
|
_parameterElements.Add(HttpUtility.UrlEncode(name), null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Web-Request method, e.g. GET, PUT, POST, DELETE
|
||||||
|
/// </summary>
|
||||||
|
public string RequestMethod
|
||||||
|
{
|
||||||
|
get { return _method; }
|
||||||
|
set { _method = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// True if string contains a trailing slash '/'
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="s">string to be examined</param>
|
||||||
|
/// <returns>true if slash is present</returns>
|
||||||
|
private bool isSlashed(string s)
|
||||||
|
{
|
||||||
|
return s.Substring(s.Length - 1, 1) == "/";
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// return a slash or blank. A slash will be returned if the string does not contain one
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="s">stromg to be examined</param>
|
||||||
|
/// <returns>slash '/' if not already present</returns>
|
||||||
|
private string slash(string s)
|
||||||
|
{
|
||||||
|
return isSlashed(s) ? "" : "/";
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Build a Uri based on the initial Url, path elements and parameters
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>fully constructed Uri</returns>
|
||||||
|
private Uri buildUri()
|
||||||
|
{
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
sb.Append(_url);
|
||||||
|
|
||||||
|
foreach (string e in _pathElements)
|
||||||
|
{
|
||||||
|
sb.Append("/");
|
||||||
|
sb.Append(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool firstElement = true;
|
||||||
|
foreach (KeyValuePair<string, string> kv in _parameterElements)
|
||||||
|
{
|
||||||
|
if (firstElement)
|
||||||
|
{
|
||||||
|
sb.Append("?");
|
||||||
|
firstElement = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
sb.Append("&");
|
||||||
|
|
||||||
|
sb.Append(kv.Key);
|
||||||
|
if (kv.Value != null && kv.Value.Length != 0)
|
||||||
|
{
|
||||||
|
sb.Append("=");
|
||||||
|
sb.Append(kv.Value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
realuri = sb.ToString();
|
||||||
|
MainLog.Instance.Verbose("REST", "RestURL: {0}", realuri);
|
||||||
|
return new Uri(sb.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Async communications with server
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Async method, invoked when a block of data has been received from the service
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="ar"></param>
|
||||||
|
private void StreamIsReadyDelegate(IAsyncResult ar)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Stream s = (Stream) ar.AsyncState;
|
||||||
|
int read = s.EndRead(ar);
|
||||||
|
|
||||||
|
if (read > 0)
|
||||||
|
{
|
||||||
|
_resource.Write(_readbuf, 0, read);
|
||||||
|
IAsyncResult asynchronousResult =
|
||||||
|
s.BeginRead(_readbuf, 0, BufferSize, new AsyncCallback(StreamIsReadyDelegate), s);
|
||||||
|
|
||||||
|
// TODO! Implement timeout, without killing the server
|
||||||
|
//ThreadPool.RegisterWaitForSingleObject(asynchronousResult.AsyncWaitHandle, new WaitOrTimerCallback(TimeoutCallback), _request, DefaultTimeout, true);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
s.Close();
|
||||||
|
_allDone.Set();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
_allDone.Set();
|
||||||
|
_asyncException = e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Async method, invoked when the initial response if received from the server
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="ar"></param>
|
||||||
|
private void ResponseIsReadyDelegate(IAsyncResult ar)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// grab response
|
||||||
|
WebRequest wr = (WebRequest) ar.AsyncState;
|
||||||
|
_response = (HttpWebResponse) wr.EndGetResponse(ar);
|
||||||
|
|
||||||
|
// get response stream, and setup async reading
|
||||||
|
Stream s = _response.GetResponseStream();
|
||||||
|
IAsyncResult asynchronousResult =
|
||||||
|
s.BeginRead(_readbuf, 0, BufferSize, new AsyncCallback(StreamIsReadyDelegate), s);
|
||||||
|
|
||||||
|
// TODO! Implement timeout, without killing the server
|
||||||
|
// wait until completed, or we timed out
|
||||||
|
// ThreadPool.RegisterWaitForSingleObject(asynchronousResult.AsyncWaitHandle, new WaitOrTimerCallback(TimeoutCallback), _request, DefaultTimeout, true);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
_allDone.Set();
|
||||||
|
_asyncException = e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Abort the request if the timer fires.
|
||||||
|
private static void TimeoutCallback(object state, bool timedOut)
|
||||||
|
{
|
||||||
|
if (timedOut)
|
||||||
|
{
|
||||||
|
HttpWebRequest request = state as HttpWebRequest;
|
||||||
|
if (request != null)
|
||||||
|
{
|
||||||
|
request.Abort();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion Async communications with server
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Perform synchroneous request
|
||||||
|
/// </summary>
|
||||||
|
public Stream Request()
|
||||||
|
{
|
||||||
|
lock (_lock)
|
||||||
|
{
|
||||||
|
_request = (HttpWebRequest) WebRequest.Create(buildUri());
|
||||||
|
_request.KeepAlive = false;
|
||||||
|
_request.ContentType = "application/xml";
|
||||||
|
_request.Timeout = 200000;
|
||||||
|
_asyncException = null;
|
||||||
|
|
||||||
|
// IAsyncResult responseAsyncResult = _request.BeginGetResponse(new AsyncCallback(ResponseIsReadyDelegate), _request);
|
||||||
|
_response = (HttpWebResponse) _request.GetResponse();
|
||||||
|
Stream src = _response.GetResponseStream();
|
||||||
|
int length = src.Read(_readbuf, 0, BufferSize);
|
||||||
|
while (length > 0)
|
||||||
|
{
|
||||||
|
_resource.Write(_readbuf, 0, length);
|
||||||
|
length = src.Read(_readbuf, 0, BufferSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// TODO! Implement timeout, without killing the server
|
||||||
|
// this line implements the timeout, if there is a timeout, the callback fires and the request becomes aborted
|
||||||
|
//ThreadPool.RegisterWaitForSingleObject(responseAsyncResult.AsyncWaitHandle, new WaitOrTimerCallback(TimeoutCallback), _request, DefaultTimeout, true);
|
||||||
|
|
||||||
|
// _allDone.WaitOne();
|
||||||
|
if (_response != null)
|
||||||
|
_response.Close();
|
||||||
|
if (_asyncException != null)
|
||||||
|
throw _asyncException;
|
||||||
|
|
||||||
|
if (_resource != null)
|
||||||
|
{
|
||||||
|
_resource.Flush();
|
||||||
|
_resource.Seek(0, SeekOrigin.Begin);
|
||||||
|
}
|
||||||
|
|
||||||
|
return _resource;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Stream Request(Stream src)
|
||||||
|
{
|
||||||
|
_request = (HttpWebRequest) WebRequest.Create(buildUri());
|
||||||
|
_request.KeepAlive = false;
|
||||||
|
_request.ContentType = "application/xml";
|
||||||
|
_request.Timeout = 900000;
|
||||||
|
_request.Method = RequestMethod;
|
||||||
|
_asyncException = null;
|
||||||
|
_request.ContentLength = src.Length;
|
||||||
|
|
||||||
|
MainLog.Instance.Verbose("REST", "Request Length {0}", _request.ContentLength);
|
||||||
|
MainLog.Instance.Verbose("REST", "Sending Web Request {0}", buildUri());
|
||||||
|
src.Seek(0, SeekOrigin.Begin);
|
||||||
|
MainLog.Instance.Verbose("REST", "Seek is ok");
|
||||||
|
Stream dst = _request.GetRequestStream();
|
||||||
|
MainLog.Instance.Verbose("REST", "GetRequestStream is ok");
|
||||||
|
|
||||||
|
byte[] buf = new byte[1024];
|
||||||
|
int length = src.Read(buf, 0, 1024);
|
||||||
|
MainLog.Instance.Verbose("REST", "First Read is ok");
|
||||||
|
while (length > 0)
|
||||||
|
{
|
||||||
|
dst.Write(buf, 0, length);
|
||||||
|
length = src.Read(buf, 0, 1024);
|
||||||
|
}
|
||||||
|
_response = (HttpWebResponse) _request.GetResponse();
|
||||||
|
|
||||||
|
// IAsyncResult responseAsyncResult = _request.BeginGetResponse(new AsyncCallback(ResponseIsReadyDelegate), _request);
|
||||||
|
|
||||||
|
// TODO! Implement timeout, without killing the server
|
||||||
|
// this line implements the timeout, if there is a timeout, the callback fires and the request becomes aborted
|
||||||
|
//ThreadPool.RegisterWaitForSingleObject(responseAsyncResult.AsyncWaitHandle, new WaitOrTimerCallback(TimeoutCallback), _request, DefaultTimeout, true);
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Async Invocation
|
||||||
|
|
||||||
|
public IAsyncResult BeginRequest(AsyncCallback callback, object state)
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// In case, we are invoked asynchroneously this object will keep track of the state
|
||||||
|
/// </summary>
|
||||||
|
AsyncResult<Stream> ar = new AsyncResult<Stream>(callback, state);
|
||||||
|
ThreadPool.QueueUserWorkItem(RequestHelper, ar);
|
||||||
|
return ar;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Stream EndRequest(IAsyncResult asyncResult)
|
||||||
|
{
|
||||||
|
AsyncResult<Stream> ar = (AsyncResult<Stream>) asyncResult;
|
||||||
|
|
||||||
|
// Wait for operation to complete, then return result or
|
||||||
|
// throw exception
|
||||||
|
return ar.EndInvoke();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void RequestHelper(Object asyncResult)
|
||||||
|
{
|
||||||
|
// We know that it's really an AsyncResult<DateTime> object
|
||||||
|
AsyncResult<Stream> ar = (AsyncResult<Stream>) asyncResult;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// Perform the operation; if sucessful set the result
|
||||||
|
Stream s = Request();
|
||||||
|
ar.SetAsCompleted(s, false);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
// If operation fails, set the exception
|
||||||
|
ar.HandleException(e, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion Async Invocation
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,377 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Threading;
|
||||||
|
using libsecondlife.StructuredData;
|
||||||
|
using libsecondlife;
|
||||||
|
using Nwc.XmlRpc;
|
||||||
|
using OpenSim.Framework.Console;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
namespace OpenSim.Framework.UserManagement
|
||||||
|
{
|
||||||
|
public class RexLoginHandler
|
||||||
|
{
|
||||||
|
private LoginService m_ls;
|
||||||
|
protected UserManagerBase m_userManager = null;
|
||||||
|
|
||||||
|
public RexLoginHandler(LoginService loginservice, UserManagerBase userManager)
|
||||||
|
{
|
||||||
|
m_ls = loginservice;
|
||||||
|
m_userManager = userManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
public LLSD LLSDLoginMethod(LLSD request)
|
||||||
|
{
|
||||||
|
string clientVersion = "not set"; //rex
|
||||||
|
|
||||||
|
LoginResponse logResponse = new LoginResponse();
|
||||||
|
|
||||||
|
string account = "";
|
||||||
|
string sessionhash = "";
|
||||||
|
string AuthenticationAddress = "";
|
||||||
|
|
||||||
|
if (request.Type == LLSDType.Map)
|
||||||
|
{
|
||||||
|
LLSDMap map = (LLSDMap)request;
|
||||||
|
|
||||||
|
if (map.ContainsKey("account") && map.ContainsKey("sessionhash") &&
|
||||||
|
map.ContainsKey("AuthenticationAddress"))
|
||||||
|
{
|
||||||
|
account = map["account"].AsString();
|
||||||
|
sessionhash = map["sessionhash"].AsString();
|
||||||
|
AuthenticationAddress = map["AuthenticationAddress"].AsString();
|
||||||
|
|
||||||
|
if (map.ContainsKey("version"))
|
||||||
|
{
|
||||||
|
clientVersion = map["version"].AsString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return logResponse.CreateLoginFailedResponseLLSD();
|
||||||
|
}
|
||||||
|
return (LLSD)CommonLoginProcess(account, sessionhash, AuthenticationAddress, clientVersion, true);
|
||||||
|
}
|
||||||
|
return logResponse.CreateLoginFailedResponseLLSD();
|
||||||
|
}
|
||||||
|
|
||||||
|
public XmlRpcResponse XmlRpcLoginMethod(XmlRpcRequest request)
|
||||||
|
{
|
||||||
|
MainLog.Instance.Verbose("LOGIN", "Attempting login to rexmode sim now...");
|
||||||
|
LoginResponse logResponse = new LoginResponse();
|
||||||
|
|
||||||
|
Hashtable requestData = (Hashtable)request.Params[0];
|
||||||
|
|
||||||
|
bool GoodXML = (//requestData.Contains("first") && requestData.Contains("last") &&
|
||||||
|
requestData.Contains("account") && requestData.Contains("sessionhash") &&
|
||||||
|
requestData.Contains("AuthenticationAddress"));
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#region GoodXML // authentication and getting UserProfileData
|
||||||
|
if (GoodXML)
|
||||||
|
{
|
||||||
|
string account = (string)requestData["account"];
|
||||||
|
string sessionhash = (string)requestData["sessionhash"];
|
||||||
|
string AuthenticationAddress = (string)requestData["AuthenticationAddress"];
|
||||||
|
string clientVersion = "not set";
|
||||||
|
if (requestData.ContainsKey("version"))
|
||||||
|
{
|
||||||
|
clientVersion = (string)requestData["version"];
|
||||||
|
}
|
||||||
|
|
||||||
|
return (XmlRpcResponse) CommonLoginProcess(account, sessionhash, AuthenticationAddress,
|
||||||
|
clientVersion, false);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return logResponse.CreateGridErrorResponse();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private object CommonLoginProcess(string account, string sessionhash, string AuthenticationAddress,
|
||||||
|
string clientVersion, bool useLLSD)
|
||||||
|
{
|
||||||
|
string asAddress;
|
||||||
|
UserProfileData userProfile;
|
||||||
|
bool GoodLogin = false;
|
||||||
|
XmlRpcResponse response = new XmlRpcResponse();
|
||||||
|
|
||||||
|
LoginResponse logResponse = new LoginResponse();
|
||||||
|
|
||||||
|
// in rex mode first thing to do is authenticate
|
||||||
|
GoodLogin = AuthenticateUser(account, ref sessionhash, AuthenticationAddress);
|
||||||
|
|
||||||
|
if (!GoodLogin)
|
||||||
|
return logResponse.CreateLoginFailedResponse();
|
||||||
|
|
||||||
|
userProfile = GetTheUser(account, sessionhash, AuthenticationAddress, out asAddress);
|
||||||
|
|
||||||
|
|
||||||
|
if (userProfile == null)
|
||||||
|
{
|
||||||
|
if (!useLLSD)
|
||||||
|
return logResponse.CreateLoginFailedResponse();
|
||||||
|
else
|
||||||
|
return logResponse.CreateAlreadyLoggedInResponseLLSD();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set at least here if not filled elsewhere later...
|
||||||
|
userProfile.authenticationAddr = AuthenticationAddress;
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region GoodLogin // Agent storing issues
|
||||||
|
if (!GoodLogin)
|
||||||
|
{
|
||||||
|
return logResponse.CreateLoginFailedResponse();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// If we already have a session...
|
||||||
|
//if (userProfile.currentAgent != null && userProfile.currentAgent.agentOnline)
|
||||||
|
//{
|
||||||
|
// userProfile.currentAgent = null;
|
||||||
|
|
||||||
|
//m_userManager.CommitAgent(ref userProfile);// not needed
|
||||||
|
// Reject the login
|
||||||
|
// return logResponse.CreateAlreadyLoggedInResponse();
|
||||||
|
//}
|
||||||
|
// Otherwise...
|
||||||
|
// TODO: Actually this is needed at least for now as otherwise crashes to agent being null
|
||||||
|
//m_ls.CreateAgent(userProfile, request); // not needed
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region AllTheRest
|
||||||
|
// All the rest in this method goes like in LoginServices method
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
LLUUID agentID = userProfile.UUID;
|
||||||
|
|
||||||
|
// Inventory Library Section
|
||||||
|
|
||||||
|
OpenSim.Framework.UserManagement.LoginService.InventoryData inventData = m_ls.CreateInventoryData(agentID);
|
||||||
|
ArrayList AgentInventoryArray = inventData.InventoryArray;
|
||||||
|
|
||||||
|
Hashtable InventoryRootHash = new Hashtable();
|
||||||
|
InventoryRootHash["folder_id"] = inventData.RootFolderID.ToString();
|
||||||
|
ArrayList InventoryRoot = new ArrayList();
|
||||||
|
InventoryRoot.Add(InventoryRootHash);
|
||||||
|
userProfile.rootInventoryFolderID = inventData.RootFolderID;
|
||||||
|
|
||||||
|
// Circuit Code
|
||||||
|
uint circode = (uint)(Util.RandomClass.Next());
|
||||||
|
|
||||||
|
logResponse.Lastname = userProfile.surname;
|
||||||
|
logResponse.Firstname = userProfile.username;
|
||||||
|
logResponse.AgentID = agentID.ToString();
|
||||||
|
// TODO: Authentication server does not send these, so use random generated defaults! (at least for now)
|
||||||
|
logResponse.SessionID = userProfile.currentAgent.sessionID.ToString();
|
||||||
|
logResponse.SecureSessionID = userProfile.currentAgent.secureSessionID.ToString();
|
||||||
|
logResponse.InventoryRoot = InventoryRoot;
|
||||||
|
logResponse.InventorySkeleton = AgentInventoryArray;
|
||||||
|
logResponse.InventoryLibrary = m_ls.GetInventoryLibrary();
|
||||||
|
logResponse.ClientVersion = clientVersion;
|
||||||
|
|
||||||
|
Hashtable InventoryLibRootHash = new Hashtable();
|
||||||
|
InventoryLibRootHash["folder_id"] = "00000112-000f-0000-0000-000100bba000";
|
||||||
|
ArrayList InventoryLibRoot = new ArrayList();
|
||||||
|
InventoryLibRoot.Add(InventoryLibRootHash);
|
||||||
|
logResponse.InventoryLibRoot = InventoryLibRoot;
|
||||||
|
|
||||||
|
logResponse.InventoryLibraryOwner = m_ls.GetLibraryOwner();
|
||||||
|
logResponse.CircuitCode = (Int32)circode;
|
||||||
|
//logResponse.RegionX = 0; //overwritten
|
||||||
|
//logResponse.RegionY = 0; //overwritten
|
||||||
|
logResponse.Home = "!!null temporary value {home}!!"; // Overwritten
|
||||||
|
//logResponse.LookAt = "\n[r" + TheUser.homeLookAt.X.ToString() + ",r" + TheUser.homeLookAt.Y.ToString() + ",r" + TheUser.homeLookAt.Z.ToString() + "]\n";
|
||||||
|
//logResponse.SimAddress = "127.0.0.1"; //overwritten
|
||||||
|
//logResponse.SimPort = 0; //overwritten
|
||||||
|
logResponse.Message = m_ls.GetMessage();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
m_ls.CustomiseResponse(logResponse, userProfile, asAddress);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
MainLog.Instance.Verbose("LOGIN", e.ToString());
|
||||||
|
if (!useLLSD)
|
||||||
|
return logResponse.CreateDeadRegionResponse();
|
||||||
|
else
|
||||||
|
return logResponse.CreateDeadRegionResponseLLSD();
|
||||||
|
//return logResponse.ToXmlRpcResponse();
|
||||||
|
}
|
||||||
|
//m_ls.CommitAgent(ref userProfile);
|
||||||
|
if (!useLLSD)
|
||||||
|
return logResponse.ToXmlRpcResponse();
|
||||||
|
else
|
||||||
|
return logResponse.ToLLSDResponse();
|
||||||
|
|
||||||
|
}
|
||||||
|
catch (Exception E)
|
||||||
|
{
|
||||||
|
MainLog.Instance.Verbose("LOGIN", E.ToString());
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
if (!useLLSD)
|
||||||
|
return response;
|
||||||
|
else
|
||||||
|
return logResponse.CreateFailedResponseLLSD();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Does authentication to Authentication server
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="account"></param>
|
||||||
|
/// <param name="loginSessionHash"></param>
|
||||||
|
/// <returns>new sessionhash ?</returns>
|
||||||
|
public bool AuthenticateUser(string account, ref string loginSessionHash, string authenticationAddr)
|
||||||
|
{
|
||||||
|
Hashtable requestParams = new Hashtable();
|
||||||
|
requestParams.Add("account", account);
|
||||||
|
requestParams.Add("sessionhash", loginSessionHash);
|
||||||
|
XmlRpcResponse res = doRequest("SimAuthenticationAccount", requestParams, authenticationAddr);
|
||||||
|
|
||||||
|
if ((string)((Hashtable)res.Value)["login"] == "success")
|
||||||
|
{
|
||||||
|
loginSessionHash = (string)((Hashtable)res.Value)["sessionHash"];
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual UserProfileData GetTheUser(string account, string sessionhash, string authenticationAddr,
|
||||||
|
out string asAddress)
|
||||||
|
{
|
||||||
|
Hashtable requestParams = new Hashtable();
|
||||||
|
requestParams.Add("avatar_account", account);
|
||||||
|
requestParams.Add("sessionhash", sessionhash);
|
||||||
|
XmlRpcResponse res = doRequest("get_user_by_account", requestParams, authenticationAddr);
|
||||||
|
|
||||||
|
// should do better check
|
||||||
|
if ((string)((Hashtable)res.Value)["uuid"] != null)
|
||||||
|
{
|
||||||
|
if ((string)((Hashtable)res.Value)["as_address"] != null)
|
||||||
|
asAddress = (string)((Hashtable)res.Value)["as_address"];
|
||||||
|
else
|
||||||
|
asAddress = "";
|
||||||
|
|
||||||
|
return HashtableToUserProfileData((Hashtable)res.Value);
|
||||||
|
}
|
||||||
|
asAddress = "";
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
protected XmlRpcResponse doRequest(string method,
|
||||||
|
Hashtable requestParams,
|
||||||
|
string authenticationAddr)
|
||||||
|
{
|
||||||
|
ArrayList SendParams = new ArrayList();
|
||||||
|
SendParams.Add(requestParams);
|
||||||
|
XmlRpcRequest req = new XmlRpcRequest(method, SendParams);
|
||||||
|
if (!authenticationAddr.StartsWith("http://"))
|
||||||
|
authenticationAddr = "http://" + authenticationAddr;
|
||||||
|
return req.Send(authenticationAddr, 300000);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static public UserProfileData HashtableToUserProfileData(Hashtable responseData)
|
||||||
|
{
|
||||||
|
UserProfileData profile = new UserProfileData();
|
||||||
|
// Account information
|
||||||
|
profile.username = (string)responseData["firstname"];
|
||||||
|
profile.surname = (string)responseData["lastname"];
|
||||||
|
|
||||||
|
profile.UUID = LLUUID.Parse((string)responseData["uuid"]);
|
||||||
|
// Server Information
|
||||||
|
profile.userInventoryURI = (string)responseData["server_inventory"];
|
||||||
|
profile.userAssetURI = (string)responseData["server_asset"];
|
||||||
|
// Profile Information
|
||||||
|
profile.profileAboutText = (string)responseData["profile_about"];
|
||||||
|
profile.profileFirstText = (string)responseData["profile_firstlife_about"];
|
||||||
|
profile.profileFirstImage = LLUUID.Parse((string)responseData["profile_firstlife_image"]);
|
||||||
|
|
||||||
|
profile.profileCanDoMask = uint.Parse((string)responseData["profile_can_do"]);
|
||||||
|
profile.profileWantDoMask = uint.Parse((string)responseData["profile_want_do"]);
|
||||||
|
|
||||||
|
profile.profileImage = LLUUID.Parse((string)responseData["profile_image"]);
|
||||||
|
|
||||||
|
profile.created = int.Parse((string)responseData["profile_created"]);
|
||||||
|
profile.lastLogin = int.Parse((string)responseData["profile_lastlogin"]);
|
||||||
|
// Home region information
|
||||||
|
profile.homeLocation = new LLVector3(float.Parse((string)responseData["home_coordinates_x"]),
|
||||||
|
float.Parse((string)responseData["home_coordinates_y"]),
|
||||||
|
float.Parse((string)responseData["home_coordinates_z"]));
|
||||||
|
|
||||||
|
profile.homeRegion = ulong.Parse((string)responseData["home_region"]);
|
||||||
|
|
||||||
|
profile.homeLookAt = new LLVector3(float.Parse((string)responseData["home_look_x"]),
|
||||||
|
float.Parse((string)responseData["home_look_y"]),
|
||||||
|
float.Parse((string)responseData["home_look_z"]));
|
||||||
|
|
||||||
|
Hashtable UADtable = (Hashtable)responseData["currentAgent"];
|
||||||
|
if (UADtable != null)
|
||||||
|
{
|
||||||
|
profile.currentAgent = new UserAgentData();
|
||||||
|
HashtableToAgentData(ref UADtable, ref profile.currentAgent);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
System.Console.WriteLine("No currentAgent in response!");
|
||||||
|
}
|
||||||
|
|
||||||
|
return profile;
|
||||||
|
}
|
||||||
|
|
||||||
|
static public void HashtableToAgentData(ref Hashtable h, ref UserAgentData uad)
|
||||||
|
{
|
||||||
|
|
||||||
|
uad.UUID = LLUUID.Parse((string)h["UUID"]);
|
||||||
|
|
||||||
|
uad.agentIP = (string)h["agentIP"];
|
||||||
|
|
||||||
|
uad.agentPort = uint.Parse((string)h["agentPort"]);
|
||||||
|
|
||||||
|
uad.agentOnline = Boolean.Parse((string)h["agentOnline"]);
|
||||||
|
|
||||||
|
uad.sessionID = LLUUID.Parse((string)h["sessionID"]);
|
||||||
|
|
||||||
|
uad.secureSessionID = LLUUID.Parse((string)h["secureSessionID"]);
|
||||||
|
|
||||||
|
uad.regionID = LLUUID.Parse((string)h["regionID"]);
|
||||||
|
|
||||||
|
uad.loginTime = int.Parse((string)h["loginTime"]);
|
||||||
|
|
||||||
|
uad.logoutTime = int.Parse((string)h["logoutTime"]);
|
||||||
|
|
||||||
|
uad.currentRegion = LLUUID.Parse((string)h["currentRegion"]);
|
||||||
|
|
||||||
|
uad.currentHandle = ulong.Parse((string)h["currentHandle"]);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
string pos1 = (string)h["currentPos"];//<123,3132,3123>
|
||||||
|
string pos2 = pos1.Substring(1, pos1.Length - 2); // remove < & >
|
||||||
|
string[] vals = pos2.Split(',');
|
||||||
|
uad.currentPos = new LLVector3(float.Parse(vals[0]), float.Parse(vals[1]), float.Parse(vals[2]));
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
uad.currentPos = new LLVector3();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,701 @@
|
||||||
|
/*
|
||||||
|
* 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 OpenSim Project nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
||||||
|
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Security.Cryptography;
|
||||||
|
using libsecondlife;
|
||||||
|
using libsecondlife.StructuredData;
|
||||||
|
using Nwc.XmlRpc;
|
||||||
|
using OpenSim.Framework.Console;
|
||||||
|
|
||||||
|
namespace OpenSim.Framework.UserManagement
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Base class for user management (create, read, etc)
|
||||||
|
/// </summary>
|
||||||
|
public abstract class UserManagerBase : IUserService
|
||||||
|
{
|
||||||
|
public UserConfig _config;
|
||||||
|
private Dictionary<string, IUserData> _plugins = new Dictionary<string, IUserData>();
|
||||||
|
public bool RexMode = false; // _config is not initiated in local mode
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Adds a new user server plugin - user servers will be requested in the order they were loaded.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="FileName">The filename to the user server plugin DLL</param>
|
||||||
|
public void AddPlugin(string FileName)
|
||||||
|
{
|
||||||
|
if (!String.IsNullOrEmpty(FileName))
|
||||||
|
{
|
||||||
|
MainLog.Instance.Verbose("USERSTORAGE", "Attempting to load " + FileName);
|
||||||
|
Assembly pluginAssembly = Assembly.LoadFrom(FileName);
|
||||||
|
|
||||||
|
MainLog.Instance.Verbose("USERSTORAGE", "Found " + pluginAssembly.GetTypes().Length + " interfaces.");
|
||||||
|
foreach (Type pluginType in pluginAssembly.GetTypes())
|
||||||
|
{
|
||||||
|
if (!pluginType.IsAbstract)
|
||||||
|
{
|
||||||
|
Type typeInterface = pluginType.GetInterface("IUserData", true);
|
||||||
|
|
||||||
|
if (typeInterface != null)
|
||||||
|
{
|
||||||
|
IUserData plug =
|
||||||
|
(IUserData) Activator.CreateInstance(pluginAssembly.GetType(pluginType.ToString()));
|
||||||
|
AddPlugin(plug);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddPlugin(IUserData plug)
|
||||||
|
{
|
||||||
|
plug.Initialise();
|
||||||
|
_plugins.Add(plug.getName(), plug);
|
||||||
|
MainLog.Instance.Verbose("USERSTORAGE", "Added IUserData Interface");
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Get UserProfile
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Loads a user profile from a database by UUID
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="uuid">The target UUID</param>
|
||||||
|
/// <returns>A user profile. Returns null if no user profile is found.</returns>
|
||||||
|
public UserProfileData GetUserProfile(LLUUID uuid, string authAddr)
|
||||||
|
{
|
||||||
|
if (!RexMode)
|
||||||
|
{
|
||||||
|
foreach (KeyValuePair<string, IUserData> plugin in _plugins)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
UserProfileData profile = plugin.Value.GetUserByUUID(uuid);
|
||||||
|
if (null != profile)
|
||||||
|
{
|
||||||
|
profile.currentAgent = getUserAgent(profile.UUID);
|
||||||
|
return profile;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
MainLog.Instance.Verbose("USERSTORAGE", "Unable to find user via " + plugin.Key + "(" + e.ToString() + ")");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
UserProfileData userpd = null;
|
||||||
|
System.Collections.Hashtable param = new System.Collections.Hashtable();
|
||||||
|
param["avatar_uuid"] = uuid.ToString();
|
||||||
|
param["AuthenticationAddress"] = authAddr;
|
||||||
|
System.Collections.Hashtable resp = MakeCommonRequest("get_user_by_uuid", param, authAddr, 3000);
|
||||||
|
userpd = RexLoginHandler.HashtableToUserProfileData(resp);
|
||||||
|
return userpd;
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
System.Console.WriteLine("Error when trying to fetch profile data by uuid from remote authentication server: " +
|
||||||
|
e.Message);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public System.Collections.Hashtable MakeCommonRequest(string method, System.Collections.Hashtable param, string addr, int timeout)//rex
|
||||||
|
{
|
||||||
|
System.Collections.IList parameters = new System.Collections.ArrayList();
|
||||||
|
parameters.Add(param);
|
||||||
|
XmlRpcRequest req = new XmlRpcRequest(method, parameters);
|
||||||
|
if (!addr.StartsWith("http://"))
|
||||||
|
addr = "http://" + addr;
|
||||||
|
XmlRpcResponse resp = req.Send(addr, timeout);
|
||||||
|
return (System.Collections.Hashtable)resp.Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Loads a user profile by name
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="name">The target name</param>
|
||||||
|
/// <returns>A user profile</returns>
|
||||||
|
public UserProfileData GetUserProfileByAccount(string account)
|
||||||
|
{
|
||||||
|
foreach (KeyValuePair<string, IUserData> plugin in _plugins)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
UserProfileData profile = plugin.Value.GetUserByAccount(account);
|
||||||
|
profile.currentAgent = getUserAgent(profile.UUID);
|
||||||
|
return profile;
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
MainLog.Instance.Verbose("USERSTORAGE", "Unable to find user by account via " + plugin.Key + "(" + e.ToString() + ")");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public List<AvatarPickerAvatar> GenerateAgentPickerRequestResponse(LLUUID queryID, string query)
|
||||||
|
{
|
||||||
|
List<AvatarPickerAvatar> pickerlist = new List<AvatarPickerAvatar>();
|
||||||
|
foreach (KeyValuePair<string, IUserData> plugin in _plugins)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
pickerlist = plugin.Value.GeneratePickerResults(queryID, query);
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
MainLog.Instance.Verbose("USERSTORAGE",
|
||||||
|
"Unable to generate AgentPickerData via " + plugin.Key + "(" + query + ")");
|
||||||
|
return new List<AvatarPickerAvatar>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return pickerlist;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Loads a user profile by name
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="fname">First name</param>
|
||||||
|
/// <param name="lname">Last name</param>
|
||||||
|
/// <returns>A user profile. Returns null if no profile is found</returns>
|
||||||
|
public UserProfileData GetUserProfile(string fname, string lname, string authAddr)
|
||||||
|
{
|
||||||
|
if (!RexMode)
|
||||||
|
{
|
||||||
|
foreach (KeyValuePair<string, IUserData> plugin in _plugins)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
UserProfileData profile = plugin.Value.GetUserByName(fname, lname);
|
||||||
|
|
||||||
|
if (profile != null)
|
||||||
|
{
|
||||||
|
profile.currentAgent = getUserAgent(profile.UUID);
|
||||||
|
return profile;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
MainLog.Instance.Verbose("USERSTORAGE", "Unable to find user via " + plugin.Key + "(" + e.ToString() + ")");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
UserProfileData userpd = null;
|
||||||
|
System.Collections.Hashtable param = new System.Collections.Hashtable();
|
||||||
|
param["avatar_name"] = fname + " "+lname;
|
||||||
|
param["AuthenticationAddress"] = authAddr;
|
||||||
|
System.Collections.Hashtable resp = MakeCommonRequest("get_user_by_name", param, authAddr, 3000);
|
||||||
|
if (resp.Contains("error_type"))
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
userpd = RexLoginHandler.HashtableToUserProfileData(resp);
|
||||||
|
return userpd;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
System.Console.WriteLine("Error when trying to fetch profile data by firstname, lastname from remote authentication server: " +
|
||||||
|
e.Message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Set's user profile from object
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="fname">First name</param>
|
||||||
|
/// <param name="lname">Last name</param>
|
||||||
|
/// <returns>A user profile</returns>
|
||||||
|
public bool setUserProfile(UserProfileData data)
|
||||||
|
{
|
||||||
|
foreach (KeyValuePair<string, IUserData> plugin in _plugins)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
plugin.Value.UpdateUserProfile(data);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
MainLog.Instance.Verbose("USERSTORAGE",
|
||||||
|
"Unable to set user via " + plugin.Key + "(" + e.ToString() + ")");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Get UserAgent
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Loads a user agent by uuid (not called directly)
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="uuid">The agent's UUID</param>
|
||||||
|
/// <returns>Agent profiles</returns>
|
||||||
|
public UserAgentData getUserAgent(LLUUID uuid)
|
||||||
|
{
|
||||||
|
foreach (KeyValuePair<string, IUserData> plugin in _plugins)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return plugin.Value.GetAgentByUUID(uuid);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
MainLog.Instance.Verbose("USERSTORAGE",
|
||||||
|
"Unable to find user via " + plugin.Key + "(" + e.ToString() + ")");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Loads a user's friend list
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="name">the UUID of the friend list owner</param>
|
||||||
|
/// <returns>A List of FriendListItems that contains info about the user's friends</returns>
|
||||||
|
public List<FriendListItem> GetUserFriendList(LLUUID ownerID)
|
||||||
|
{
|
||||||
|
|
||||||
|
foreach (KeyValuePair<string, IUserData> plugin in _plugins)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return plugin.Value.GetUserFriendList(ownerID);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
MainLog.Instance.Verbose("USERSTORAGE",
|
||||||
|
"Unable to GetUserFriendList via " + plugin.Key + "(" + e.ToString() + ")");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddNewUserFriend(LLUUID friendlistowner, LLUUID friend, uint perms)
|
||||||
|
{
|
||||||
|
foreach (KeyValuePair<string, IUserData> plugin in _plugins)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
plugin.Value.AddNewUserFriend(friendlistowner,friend,perms);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
MainLog.Instance.Verbose("USERSTORAGE",
|
||||||
|
"Unable to AddNewUserFriend via " + plugin.Key + "(" + e.ToString() + ")");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void RemoveUserFriend(LLUUID friendlistowner, LLUUID friend)
|
||||||
|
{
|
||||||
|
foreach (KeyValuePair<string, IUserData> plugin in _plugins)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
plugin.Value.RemoveUserFriend(friendlistowner, friend);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
MainLog.Instance.Verbose("USERSTORAGE",
|
||||||
|
"Unable to RemoveUserFriend via " + plugin.Key + "(" + e.ToString() + ")");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void UpdateUserFriendPerms(LLUUID friendlistowner, LLUUID friend, uint perms)
|
||||||
|
{
|
||||||
|
foreach (KeyValuePair<string, IUserData> plugin in _plugins)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
plugin.Value.UpdateUserFriendPerms(friendlistowner, friend, perms);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
MainLog.Instance.Verbose("USERSTORAGE",
|
||||||
|
"Unable to UpdateUserFriendPerms via " + plugin.Key + "(" + e.ToString() + ")");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Loads a user agent by name (not called directly)
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="name">The agent's name</param>
|
||||||
|
/// <returns>A user agent</returns>
|
||||||
|
public UserAgentData getUserAgent(string name)
|
||||||
|
{
|
||||||
|
foreach (KeyValuePair<string, IUserData> plugin in _plugins)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return plugin.Value.GetAgentByName(name);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
MainLog.Instance.Verbose("USERSTORAGE",
|
||||||
|
"Unable to find user via " + plugin.Key + "(" + e.ToString() + ")");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: document
|
||||||
|
public void clearUserAgent(LLUUID agentID, string authAddr)
|
||||||
|
{
|
||||||
|
UserProfileData profile = GetUserProfile(agentID, authAddr);
|
||||||
|
if (profile != null)
|
||||||
|
{
|
||||||
|
profile.currentAgent = null;
|
||||||
|
if (!RexMode)
|
||||||
|
{
|
||||||
|
setUserProfile(profile);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
System.Collections.Hashtable param = new System.Collections.Hashtable();
|
||||||
|
param["agentID"] = profile.UUID.ToString();
|
||||||
|
System.Collections.Hashtable resp = MakeCommonRequest("remove_user_agent", param, authAddr, 3000);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
System.Console.WriteLine("Error when trying to fetch agent data by uuid from remote authentication server: " +
|
||||||
|
e.Message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
MainLog.Instance.Verbose("USERSTORAGE", "Unable to clear user agent with agentID : " + agentID);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Loads a user agent by name (not called directly)
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="fname">The agent's firstname</param>
|
||||||
|
/// <param name="lname">The agent's lastname</param>
|
||||||
|
/// <returns>A user agent</returns>
|
||||||
|
public UserAgentData getUserAgent(string fname, string lname)
|
||||||
|
{
|
||||||
|
foreach (KeyValuePair<string, IUserData> plugin in _plugins)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return plugin.Value.GetAgentByName(fname, lname);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
MainLog.Instance.Verbose("USERSTORAGE",
|
||||||
|
"Unable to find user via " + plugin.Key + "(" + e.ToString() + ")");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region CreateAgent
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates and initialises a new user agent - make sure to use CommitAgent when done to submit to the DB
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="profile">The users profile</param>
|
||||||
|
/// <param name="request">The users loginrequest</param>
|
||||||
|
public void CreateAgent(UserProfileData profile, XmlRpcRequest request)
|
||||||
|
{
|
||||||
|
//Hashtable requestData = (Hashtable) request.Params[0];
|
||||||
|
|
||||||
|
UserAgentData agent = new UserAgentData();
|
||||||
|
|
||||||
|
// User connection
|
||||||
|
agent.agentOnline = true;
|
||||||
|
|
||||||
|
// Generate sessions
|
||||||
|
RNGCryptoServiceProvider rand = new RNGCryptoServiceProvider();
|
||||||
|
byte[] randDataS = new byte[16];
|
||||||
|
byte[] randDataSS = new byte[16];
|
||||||
|
rand.GetBytes(randDataS);
|
||||||
|
rand.GetBytes(randDataSS);
|
||||||
|
|
||||||
|
agent.secureSessionID = new LLUUID(randDataSS, 0);
|
||||||
|
agent.sessionID = new LLUUID(randDataS, 0);
|
||||||
|
|
||||||
|
// Profile UUID
|
||||||
|
agent.UUID = profile.UUID;
|
||||||
|
|
||||||
|
// Current position (from Home)
|
||||||
|
agent.currentHandle = profile.homeRegion;
|
||||||
|
agent.currentPos = profile.homeLocation;
|
||||||
|
|
||||||
|
// If user specified additional start, use that
|
||||||
|
// if (requestData.ContainsKey("start"))
|
||||||
|
// {
|
||||||
|
// string startLoc = ((string) requestData["start"]).Trim();
|
||||||
|
// if (!(startLoc == "last" || startLoc == "home"))
|
||||||
|
// {
|
||||||
|
// // Format: uri:Ahern&162&213&34
|
||||||
|
// try
|
||||||
|
// {
|
||||||
|
// string[] parts = startLoc.Remove(0, 4).Split('&');
|
||||||
|
// //string region = parts[0];
|
||||||
|
//
|
||||||
|
// ////////////////////////////////////////////////////
|
||||||
|
// //SimProfile SimInfo = new SimProfile();
|
||||||
|
// //SimInfo = SimInfo.LoadFromGrid(theUser.currentAgent.currentHandle, _config.GridServerURL, _config.GridSendKey, _config.GridRecvKey);
|
||||||
|
// }
|
||||||
|
// catch (Exception)
|
||||||
|
// {
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// What time did the user login?
|
||||||
|
agent.loginTime = Util.UnixTimeSinceEpoch();
|
||||||
|
agent.logoutTime = 0;
|
||||||
|
|
||||||
|
// Current location
|
||||||
|
agent.regionID = LLUUID.Zero; // Fill in later
|
||||||
|
agent.currentRegion = LLUUID.Zero; // Fill in later
|
||||||
|
|
||||||
|
profile.currentAgent = agent;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void CreateAgent(UserProfileData profile, LLSD request)
|
||||||
|
{
|
||||||
|
UserAgentData agent = new UserAgentData();
|
||||||
|
|
||||||
|
// User connection
|
||||||
|
agent.agentOnline = true;
|
||||||
|
|
||||||
|
// Generate sessions
|
||||||
|
RNGCryptoServiceProvider rand = new RNGCryptoServiceProvider();
|
||||||
|
byte[] randDataS = new byte[16];
|
||||||
|
byte[] randDataSS = new byte[16];
|
||||||
|
rand.GetBytes(randDataS);
|
||||||
|
rand.GetBytes(randDataSS);
|
||||||
|
|
||||||
|
agent.secureSessionID = new LLUUID(randDataSS, 0);
|
||||||
|
agent.sessionID = new LLUUID(randDataS, 0);
|
||||||
|
|
||||||
|
// Profile UUID
|
||||||
|
agent.UUID = profile.UUID;
|
||||||
|
|
||||||
|
// Current position (from Home)
|
||||||
|
agent.currentHandle = profile.homeRegion;
|
||||||
|
agent.currentPos = profile.homeLocation;
|
||||||
|
|
||||||
|
// What time did the user login?
|
||||||
|
agent.loginTime = Util.UnixTimeSinceEpoch();
|
||||||
|
agent.logoutTime = 0;
|
||||||
|
|
||||||
|
// Current location
|
||||||
|
agent.regionID = LLUUID.Zero; // Fill in later
|
||||||
|
agent.currentRegion = LLUUID.Zero; // Fill in later
|
||||||
|
|
||||||
|
profile.currentAgent = agent;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Saves a target agent to the database
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="profile">The users profile</param>
|
||||||
|
/// <returns>Successful?</returns>
|
||||||
|
public bool CommitAgent(ref UserProfileData profile)
|
||||||
|
{
|
||||||
|
// TODO: how is this function different from setUserProfile?
|
||||||
|
return setUserProfile(profile);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="user"></param>
|
||||||
|
public LLUUID AddUserProfile(string firstName, string lastName, string pass, uint regX, uint regY)
|
||||||
|
{
|
||||||
|
UserProfileData user = new UserProfileData();
|
||||||
|
user.homeLocation = new LLVector3(128, 128, 100);
|
||||||
|
user.UUID = LLUUID.Random();
|
||||||
|
user.username = firstName;
|
||||||
|
user.surname = lastName;
|
||||||
|
user.passwordHash = pass;
|
||||||
|
user.passwordSalt = "";
|
||||||
|
user.created = Util.UnixTimeSinceEpoch();
|
||||||
|
user.homeLookAt = new LLVector3(100, 100, 100);
|
||||||
|
user.homeRegionX = regX;
|
||||||
|
user.homeRegionY = regY;
|
||||||
|
|
||||||
|
|
||||||
|
foreach (KeyValuePair<string, IUserData> plugin in _plugins)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
plugin.Value.AddNewUserProfile(user);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
MainLog.Instance.Verbose("USERSTORAGE",
|
||||||
|
"Unable to add user via " + plugin.Key + "(" + e.ToString() + ")");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return user.UUID;
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract UserProfileData SetupMasterUser(string firstName, string lastName);
|
||||||
|
public abstract UserProfileData SetupMasterUser(string firstName, string lastName, string password);
|
||||||
|
public abstract UserProfileData SetupMasterUser(LLUUID uuid);
|
||||||
|
|
||||||
|
|
||||||
|
public bool AuthenticateUser(LLUUID agentId, string sessionhash, out String avatarstorage)
|
||||||
|
{
|
||||||
|
avatarstorage = "";
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Loads a user profile by name
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="name">The target name</param>
|
||||||
|
/// <returns>A user profile</returns>
|
||||||
|
public UserProfileData GetUserProfile(string name, string authAddr)
|
||||||
|
{
|
||||||
|
foreach (KeyValuePair<string, IUserData> plugin in _plugins)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
UserProfileData profile = plugin.Value.GetUserByName(name, authAddr);
|
||||||
|
profile.currentAgent = getUserAgent(profile.UUID);
|
||||||
|
return profile;
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
MainLog.Instance.Verbose("USERSTORAGE", "Unable to find user via " + plugin.Key + "(" + e.ToString() + ")");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void UpdateUserAgentData(LLUUID agentId, bool agentOnline, LLVector3 currentPos, int logoutTime, string authAddr)
|
||||||
|
{
|
||||||
|
// Saves the agent to database
|
||||||
|
//return true;
|
||||||
|
if (!RexMode)
|
||||||
|
{
|
||||||
|
foreach (KeyValuePair<string, IUserData> plugin in _plugins)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
UserAgentData agent = plugin.Value.GetAgentByUUID(agentId);
|
||||||
|
if (agent != null)
|
||||||
|
{
|
||||||
|
agent.agentOnline = agentOnline;
|
||||||
|
agent.logoutTime = logoutTime;
|
||||||
|
agent.currentPos = currentPos;
|
||||||
|
agent.currentPos = new LLVector3(
|
||||||
|
Convert.ToSingle(currentPos.X),
|
||||||
|
Convert.ToSingle(currentPos.Y),
|
||||||
|
Convert.ToSingle(currentPos.Z));
|
||||||
|
plugin.Value.AddNewUserAgent(agent);
|
||||||
|
MainLog.Instance.Verbose("USERSTORAGE", "Agent updated UUID = " + agent.UUID.ToString());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
MainLog.Instance.Verbose("USERSTORAGE", "Agent update, agent not found with UUID = " + agentId);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
MainLog.Instance.Verbose("USERSTORAGE", "Unable to add or update agent via " + plugin.Key + "(" + e.ToString() + ")");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
System.Collections.Hashtable param = new System.Collections.Hashtable();
|
||||||
|
param["agentID"] = agentId.ToString();
|
||||||
|
param["agentOnline"] = agentOnline.ToString();
|
||||||
|
param["logoutTime"] = logoutTime.ToString();
|
||||||
|
param["agent_currentPosX"] = Convert.ToSingle(currentPos.X).ToString();
|
||||||
|
param["agent_currentPosY"] = Convert.ToSingle(currentPos.Y).ToString();
|
||||||
|
param["agent_currentPosZ"] = Convert.ToSingle(currentPos.Z).ToString();
|
||||||
|
param["AuthenticationAddress"] = authAddr;
|
||||||
|
System.Collections.Hashtable resp = MakeCommonRequest("update_user_agent", param, authAddr, 3000);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
System.Console.WriteLine("Error when trying to update user agent data to remote authentication server: " +
|
||||||
|
e.Message);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,115 @@
|
||||||
|
/*
|
||||||
|
* 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 OpenSim 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.IO;
|
||||||
|
using System.Net;
|
||||||
|
using System.Text;
|
||||||
|
using OpenSim.Framework.Console;
|
||||||
|
|
||||||
|
namespace OpenSim.Framework.Configuration.HTTP
|
||||||
|
{
|
||||||
|
public class HTTPConfiguration : IGenericConfig
|
||||||
|
{
|
||||||
|
private RemoteConfigSettings remoteConfigSettings;
|
||||||
|
|
||||||
|
private XmlConfiguration xmlConfig;
|
||||||
|
|
||||||
|
private string configFileName = "";
|
||||||
|
|
||||||
|
public HTTPConfiguration()
|
||||||
|
{
|
||||||
|
remoteConfigSettings = new RemoteConfigSettings("remoteconfig.xml");
|
||||||
|
xmlConfig = new XmlConfiguration();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetFileName(string fileName)
|
||||||
|
{
|
||||||
|
configFileName = fileName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void LoadData()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
|
||||||
|
byte[] buf = new byte[8192];
|
||||||
|
HttpWebRequest request =
|
||||||
|
(HttpWebRequest) WebRequest.Create(remoteConfigSettings.baseConfigURL + configFileName);
|
||||||
|
HttpWebResponse response = (HttpWebResponse) request.GetResponse();
|
||||||
|
|
||||||
|
Stream resStream = response.GetResponseStream();
|
||||||
|
|
||||||
|
string tempString = null;
|
||||||
|
int count = 0;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
count = resStream.Read(buf, 0, buf.Length);
|
||||||
|
if (count != 0)
|
||||||
|
{
|
||||||
|
tempString = Encoding.ASCII.GetString(buf, 0, count);
|
||||||
|
sb.Append(tempString);
|
||||||
|
}
|
||||||
|
} while (count > 0);
|
||||||
|
LoadDataFromString(sb.ToString());
|
||||||
|
}
|
||||||
|
catch (WebException)
|
||||||
|
{
|
||||||
|
MainLog.Instance.Warn("Unable to connect to remote configuration file (" +
|
||||||
|
remoteConfigSettings.baseConfigURL + configFileName +
|
||||||
|
"). Creating local file instead.");
|
||||||
|
xmlConfig.SetFileName(configFileName);
|
||||||
|
xmlConfig.LoadData();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void LoadDataFromString(string data)
|
||||||
|
{
|
||||||
|
xmlConfig.LoadDataFromString(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
public string GetAttribute(string attributeName)
|
||||||
|
{
|
||||||
|
return xmlConfig.GetAttribute(attributeName);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool SetAttribute(string attributeName, string attributeValue)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Commit()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Close()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,62 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) Contributors, http://opensimulator.org/
|
||||||
|
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of the OpenSim 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.Configuration.HTTP
|
||||||
|
{
|
||||||
|
public class RemoteConfigSettings
|
||||||
|
{
|
||||||
|
private ConfigurationMember configMember;
|
||||||
|
|
||||||
|
public string baseConfigURL = "";
|
||||||
|
|
||||||
|
public RemoteConfigSettings(string filename)
|
||||||
|
{
|
||||||
|
configMember =
|
||||||
|
new ConfigurationMember(filename, "REMOTE CONFIG SETTINGS", loadConfigurationOptions,
|
||||||
|
handleIncomingConfiguration,true);
|
||||||
|
configMember.forceConfigurationPluginLibrary("OpenSim.Framework.Configuration.XML.dll");
|
||||||
|
configMember.performConfigurationRetrieve();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void loadConfigurationOptions()
|
||||||
|
{
|
||||||
|
configMember.addConfigurationOption("base_config_url",
|
||||||
|
ConfigurationOption.ConfigurationTypes.TYPE_STRING_NOT_EMPTY,
|
||||||
|
"URL Containing Configuration Files", "http://localhost/", false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool handleIncomingConfiguration(string configuration_key, object configuration_result)
|
||||||
|
{
|
||||||
|
if (configuration_key == "base_config_url")
|
||||||
|
{
|
||||||
|
baseConfigURL = (string) configuration_result;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,139 @@
|
||||||
|
/*
|
||||||
|
* 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 OpenSim Project nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
||||||
|
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Xml;
|
||||||
|
|
||||||
|
namespace OpenSim.Framework.Configuration
|
||||||
|
{
|
||||||
|
public class XmlConfiguration : IGenericConfig
|
||||||
|
{
|
||||||
|
private XmlDocument doc;
|
||||||
|
private XmlNode rootNode;
|
||||||
|
private XmlNode configNode;
|
||||||
|
private string fileName;
|
||||||
|
private bool createdFile = false;
|
||||||
|
|
||||||
|
public void SetFileName(string file)
|
||||||
|
{
|
||||||
|
fileName = file;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void LoadDataToClass()
|
||||||
|
{
|
||||||
|
rootNode = doc.FirstChild;
|
||||||
|
if (rootNode.Name != "Root")
|
||||||
|
throw new Exception("Error: Invalid .xml File. Missing <Root>");
|
||||||
|
|
||||||
|
configNode = rootNode.FirstChild;
|
||||||
|
if (configNode.Name != "Config")
|
||||||
|
throw new Exception("Error: Invalid .xml File. <Root> first child should be <Config>");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void LoadData()
|
||||||
|
{
|
||||||
|
lock (this)
|
||||||
|
{
|
||||||
|
doc = new XmlDocument();
|
||||||
|
if (File.Exists(fileName))
|
||||||
|
{
|
||||||
|
XmlTextReader reader = new XmlTextReader(fileName);
|
||||||
|
reader.WhitespaceHandling = WhitespaceHandling.None;
|
||||||
|
doc.Load(reader);
|
||||||
|
reader.Close();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
createdFile = true;
|
||||||
|
rootNode = doc.CreateNode(XmlNodeType.Element, "Root", "");
|
||||||
|
doc.AppendChild(rootNode);
|
||||||
|
configNode = doc.CreateNode(XmlNodeType.Element, "Config", "");
|
||||||
|
rootNode.AppendChild(configNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
LoadDataToClass();
|
||||||
|
|
||||||
|
if (createdFile)
|
||||||
|
{
|
||||||
|
Commit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void LoadDataFromString(string data)
|
||||||
|
{
|
||||||
|
doc = new XmlDocument();
|
||||||
|
doc.LoadXml(data);
|
||||||
|
|
||||||
|
LoadDataToClass();
|
||||||
|
}
|
||||||
|
|
||||||
|
public string GetAttribute(string attributeName)
|
||||||
|
{
|
||||||
|
string result = null;
|
||||||
|
if (configNode.Attributes[attributeName] != null)
|
||||||
|
{
|
||||||
|
result = ((XmlAttribute) configNode.Attributes.GetNamedItem(attributeName)).Value;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool SetAttribute(string attributeName, string attributeValue)
|
||||||
|
{
|
||||||
|
if (configNode.Attributes[attributeName] != null)
|
||||||
|
{
|
||||||
|
((XmlAttribute) configNode.Attributes.GetNamedItem(attributeName)).Value = attributeValue;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
XmlAttribute attri;
|
||||||
|
attri = doc.CreateAttribute(attributeName);
|
||||||
|
attri.Value = attributeValue;
|
||||||
|
configNode.Attributes.Append(attri);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Commit()
|
||||||
|
{
|
||||||
|
if (!Directory.Exists(Util.configDir()))
|
||||||
|
{
|
||||||
|
Directory.CreateDirectory(Util.configDir());
|
||||||
|
}
|
||||||
|
doc.Save(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Close()
|
||||||
|
{
|
||||||
|
configNode = null;
|
||||||
|
rootNode = null;
|
||||||
|
doc = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,505 @@
|
||||||
|
/*
|
||||||
|
* 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 OpenSim 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.Globalization;
|
||||||
|
using System.Net;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Xml;
|
||||||
|
using libsecondlife;
|
||||||
|
using OpenSim.Framework.Console;
|
||||||
|
|
||||||
|
namespace OpenSim.Framework
|
||||||
|
{
|
||||||
|
public class ConfigurationMember
|
||||||
|
{
|
||||||
|
public delegate bool ConfigurationOptionResult(string configuration_key, object configuration_result);
|
||||||
|
|
||||||
|
public delegate void ConfigurationOptionsLoad();
|
||||||
|
|
||||||
|
private List<ConfigurationOption> configurationOptions = new List<ConfigurationOption>();
|
||||||
|
private string configurationFilename = "";
|
||||||
|
private string configurationDescription = "";
|
||||||
|
private XmlNode configurationFromXMLNode = null;
|
||||||
|
private ConfigurationOptionsLoad loadFunction;
|
||||||
|
private ConfigurationOptionResult resultFunction;
|
||||||
|
|
||||||
|
private IGenericConfig configurationPlugin = null;
|
||||||
|
private bool useConsoleToPromptOnError = true;
|
||||||
|
/// <summary>
|
||||||
|
/// This is the default configuration DLL loaded
|
||||||
|
/// </summary>
|
||||||
|
private string configurationPluginFilename = "OpenSim.Framework.Configuration.XML.dll";
|
||||||
|
|
||||||
|
public ConfigurationMember(string configuration_filename, string configuration_description,
|
||||||
|
ConfigurationOptionsLoad load_function, ConfigurationOptionResult result_function, bool use_console_to_prompt_on_error)
|
||||||
|
{
|
||||||
|
configurationFilename = configuration_filename;
|
||||||
|
configurationDescription = configuration_description;
|
||||||
|
loadFunction = load_function;
|
||||||
|
resultFunction = result_function;
|
||||||
|
useConsoleToPromptOnError = use_console_to_prompt_on_error;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ConfigurationMember(XmlNode configuration_xml, string configuration_description,
|
||||||
|
ConfigurationOptionsLoad load_function, ConfigurationOptionResult result_function, bool use_console_to_prompt_on_error)
|
||||||
|
{
|
||||||
|
configurationFilename = "";
|
||||||
|
configurationFromXMLNode = configuration_xml;
|
||||||
|
configurationDescription = configuration_description;
|
||||||
|
loadFunction = load_function;
|
||||||
|
resultFunction = result_function;
|
||||||
|
useConsoleToPromptOnError = use_console_to_prompt_on_error;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setConfigurationFilename(string filename)
|
||||||
|
{
|
||||||
|
configurationFilename = filename;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setConfigurationDescription(string desc)
|
||||||
|
{
|
||||||
|
configurationDescription = desc;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setConfigurationResultFunction(ConfigurationOptionResult result)
|
||||||
|
{
|
||||||
|
resultFunction = result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void forceConfigurationPluginLibrary(string dll_filename)
|
||||||
|
{
|
||||||
|
configurationPluginFilename = dll_filename;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkAndAddConfigOption(ConfigurationOption option)
|
||||||
|
{
|
||||||
|
if ((option.configurationKey != "" && option.configurationQuestion != "") ||
|
||||||
|
(option.configurationKey != "" && option.configurationUseDefaultNoPrompt))
|
||||||
|
{
|
||||||
|
if (!configurationOptions.Contains(option))
|
||||||
|
{
|
||||||
|
configurationOptions.Add(option);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
MainLog.Instance.Notice(
|
||||||
|
"Required fields for adding a configuration option is invalid. Will not add this option (" +
|
||||||
|
option.configurationKey + ")");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addConfigurationOption(string configuration_key,
|
||||||
|
ConfigurationOption.ConfigurationTypes configuration_type,
|
||||||
|
string configuration_question, string configuration_default,
|
||||||
|
bool use_default_no_prompt)
|
||||||
|
{
|
||||||
|
ConfigurationOption configOption = new ConfigurationOption();
|
||||||
|
configOption.configurationKey = configuration_key;
|
||||||
|
configOption.configurationQuestion = configuration_question;
|
||||||
|
configOption.configurationDefault = configuration_default;
|
||||||
|
configOption.configurationType = configuration_type;
|
||||||
|
configOption.configurationUseDefaultNoPrompt = use_default_no_prompt;
|
||||||
|
configOption.shouldIBeAsked = null; //Assumes true, I can ask whenever
|
||||||
|
checkAndAddConfigOption(configOption);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addConfigurationOption(string configuration_key,
|
||||||
|
ConfigurationOption.ConfigurationTypes configuration_type,
|
||||||
|
string configuration_question, string configuration_default,
|
||||||
|
bool use_default_no_prompt,
|
||||||
|
ConfigurationOption.ConfigurationOptionShouldBeAsked shouldIBeAskedDelegate)
|
||||||
|
{
|
||||||
|
ConfigurationOption configOption = new ConfigurationOption();
|
||||||
|
configOption.configurationKey = configuration_key;
|
||||||
|
configOption.configurationQuestion = configuration_question;
|
||||||
|
configOption.configurationDefault = configuration_default;
|
||||||
|
configOption.configurationType = configuration_type;
|
||||||
|
configOption.configurationUseDefaultNoPrompt = use_default_no_prompt;
|
||||||
|
configOption.shouldIBeAsked = shouldIBeAskedDelegate;
|
||||||
|
checkAndAddConfigOption(configOption);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// TEMP - REMOVE
|
||||||
|
private int cE = 0;
|
||||||
|
public void performConfigurationRetrieve()
|
||||||
|
{
|
||||||
|
if (cE > 1)
|
||||||
|
MainLog.Instance.Error("READING CONFIGURATION COUT: " + cE.ToString());
|
||||||
|
|
||||||
|
|
||||||
|
configurationPlugin = LoadConfigDll(configurationPluginFilename);
|
||||||
|
configurationOptions.Clear();
|
||||||
|
if (loadFunction == null)
|
||||||
|
{
|
||||||
|
MainLog.Instance.Error("Load Function for '" + configurationDescription +
|
||||||
|
"' is null. Refusing to run configuration.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (resultFunction == null)
|
||||||
|
{
|
||||||
|
MainLog.Instance.Error("Result Function for '" + configurationDescription +
|
||||||
|
"' is null. Refusing to run configuration.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
MainLog.Instance.Verbose("CONFIG", "Calling Configuration Load Function...");
|
||||||
|
loadFunction();
|
||||||
|
|
||||||
|
if (configurationOptions.Count <= 0)
|
||||||
|
{
|
||||||
|
MainLog.Instance.Error("CONFIG",
|
||||||
|
"No configuration options were specified for '" + configurationOptions +
|
||||||
|
"'. Refusing to continue configuration.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool useFile = true;
|
||||||
|
if (configurationPlugin == null)
|
||||||
|
{
|
||||||
|
MainLog.Instance.Error("CONFIG", "Configuration Plugin NOT LOADED!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (configurationFilename.Trim() != "")
|
||||||
|
{
|
||||||
|
configurationPlugin.SetFileName(configurationFilename);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
configurationPlugin.LoadData();
|
||||||
|
useFile = true;
|
||||||
|
}
|
||||||
|
catch (XmlException e)
|
||||||
|
{
|
||||||
|
MainLog.Instance.Error("Error loading " + configurationFilename + ": " + e.ToString());
|
||||||
|
useFile = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (configurationFromXMLNode != null)
|
||||||
|
{
|
||||||
|
MainLog.Instance.Notice("Loading from XML Node, will not save to the file");
|
||||||
|
configurationPlugin.LoadDataFromString(configurationFromXMLNode.OuterXml);
|
||||||
|
}
|
||||||
|
|
||||||
|
MainLog.Instance.Notice("XML Configuration Filename is not valid; will not save to the file.");
|
||||||
|
useFile = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (ConfigurationOption configOption in configurationOptions)
|
||||||
|
{
|
||||||
|
bool convertSuccess = false;
|
||||||
|
object return_result = null;
|
||||||
|
string errorMessage = "";
|
||||||
|
bool ignoreNextFromConfig = false;
|
||||||
|
while (convertSuccess == false)
|
||||||
|
{
|
||||||
|
string console_result = "";
|
||||||
|
string attribute = null;
|
||||||
|
if (useFile || configurationFromXMLNode != null)
|
||||||
|
{
|
||||||
|
if (!ignoreNextFromConfig)
|
||||||
|
{
|
||||||
|
attribute = configurationPlugin.GetAttribute(configOption.configurationKey);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ignoreNextFromConfig = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (attribute == null)
|
||||||
|
{
|
||||||
|
if (configOption.configurationUseDefaultNoPrompt || useConsoleToPromptOnError == false)
|
||||||
|
{
|
||||||
|
console_result = configOption.configurationDefault;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if ((configOption.shouldIBeAsked != null &&
|
||||||
|
configOption.shouldIBeAsked(configOption.configurationKey)) ||
|
||||||
|
configOption.shouldIBeAsked == null)
|
||||||
|
{
|
||||||
|
if (configurationDescription.Trim() != "")
|
||||||
|
{
|
||||||
|
console_result =
|
||||||
|
MainLog.Instance.CmdPrompt(
|
||||||
|
configurationDescription + ": " + configOption.configurationQuestion,
|
||||||
|
configOption.configurationDefault);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
console_result =
|
||||||
|
MainLog.Instance.CmdPrompt(configOption.configurationQuestion,
|
||||||
|
configOption.configurationDefault);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//Dont Ask! Just use default
|
||||||
|
console_result = configOption.configurationDefault;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
console_result = attribute;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (configOption.configurationType)
|
||||||
|
{
|
||||||
|
case ConfigurationOption.ConfigurationTypes.TYPE_STRING:
|
||||||
|
return_result = console_result;
|
||||||
|
convertSuccess = true;
|
||||||
|
break;
|
||||||
|
case ConfigurationOption.ConfigurationTypes.TYPE_STRING_NOT_EMPTY:
|
||||||
|
if (console_result.Length > 0)
|
||||||
|
{
|
||||||
|
return_result = console_result;
|
||||||
|
convertSuccess = true;
|
||||||
|
}
|
||||||
|
errorMessage = "a string that is not empty";
|
||||||
|
break;
|
||||||
|
case ConfigurationOption.ConfigurationTypes.TYPE_BOOLEAN:
|
||||||
|
bool boolResult;
|
||||||
|
if (Boolean.TryParse(console_result, out boolResult))
|
||||||
|
{
|
||||||
|
convertSuccess = true;
|
||||||
|
return_result = boolResult;
|
||||||
|
}
|
||||||
|
errorMessage = "'true' or 'false' (Boolean)";
|
||||||
|
break;
|
||||||
|
case ConfigurationOption.ConfigurationTypes.TYPE_BYTE:
|
||||||
|
byte byteResult;
|
||||||
|
if (Byte.TryParse(console_result, out byteResult))
|
||||||
|
{
|
||||||
|
convertSuccess = true;
|
||||||
|
return_result = byteResult;
|
||||||
|
}
|
||||||
|
errorMessage = "a byte (Byte)";
|
||||||
|
break;
|
||||||
|
case ConfigurationOption.ConfigurationTypes.TYPE_CHARACTER:
|
||||||
|
char charResult;
|
||||||
|
if (Char.TryParse(console_result, out charResult))
|
||||||
|
{
|
||||||
|
convertSuccess = true;
|
||||||
|
return_result = charResult;
|
||||||
|
}
|
||||||
|
errorMessage = "a character (Char)";
|
||||||
|
break;
|
||||||
|
case ConfigurationOption.ConfigurationTypes.TYPE_INT16:
|
||||||
|
short shortResult;
|
||||||
|
if (Int16.TryParse(console_result, out shortResult))
|
||||||
|
{
|
||||||
|
convertSuccess = true;
|
||||||
|
return_result = shortResult;
|
||||||
|
}
|
||||||
|
errorMessage = "a signed 32 bit integer (short)";
|
||||||
|
break;
|
||||||
|
case ConfigurationOption.ConfigurationTypes.TYPE_INT32:
|
||||||
|
int intResult;
|
||||||
|
if (Int32.TryParse(console_result, out intResult))
|
||||||
|
{
|
||||||
|
convertSuccess = true;
|
||||||
|
return_result = intResult;
|
||||||
|
}
|
||||||
|
errorMessage = "a signed 32 bit integer (int)";
|
||||||
|
break;
|
||||||
|
case ConfigurationOption.ConfigurationTypes.TYPE_INT64:
|
||||||
|
long longResult;
|
||||||
|
if (Int64.TryParse(console_result, out longResult))
|
||||||
|
{
|
||||||
|
convertSuccess = true;
|
||||||
|
return_result = longResult;
|
||||||
|
}
|
||||||
|
errorMessage = "a signed 32 bit integer (long)";
|
||||||
|
break;
|
||||||
|
case ConfigurationOption.ConfigurationTypes.TYPE_IP_ADDRESS:
|
||||||
|
IPAddress ipAddressResult;
|
||||||
|
if (IPAddress.TryParse(console_result, out ipAddressResult))
|
||||||
|
{
|
||||||
|
convertSuccess = true;
|
||||||
|
return_result = ipAddressResult;
|
||||||
|
}
|
||||||
|
errorMessage = "an IP Address (IPAddress)";
|
||||||
|
break;
|
||||||
|
case ConfigurationOption.ConfigurationTypes.TYPE_LLUUID:
|
||||||
|
LLUUID uuidResult;
|
||||||
|
if (LLUUID.TryParse(console_result, out uuidResult))
|
||||||
|
{
|
||||||
|
convertSuccess = true;
|
||||||
|
return_result = uuidResult;
|
||||||
|
}
|
||||||
|
errorMessage = "a UUID (LLUUID)";
|
||||||
|
break;
|
||||||
|
case ConfigurationOption.ConfigurationTypes.TYPE_LLVECTOR3:
|
||||||
|
LLVector3 vectorResult;
|
||||||
|
if (LLVector3.TryParse(console_result, out vectorResult))
|
||||||
|
{
|
||||||
|
convertSuccess = true;
|
||||||
|
return_result = vectorResult;
|
||||||
|
}
|
||||||
|
errorMessage = "a vector (LLVector3)";
|
||||||
|
break;
|
||||||
|
case ConfigurationOption.ConfigurationTypes.TYPE_UINT16:
|
||||||
|
ushort ushortResult;
|
||||||
|
if (UInt16.TryParse(console_result, out ushortResult))
|
||||||
|
{
|
||||||
|
convertSuccess = true;
|
||||||
|
return_result = ushortResult;
|
||||||
|
}
|
||||||
|
errorMessage = "an unsigned 16 bit integer (ushort)";
|
||||||
|
break;
|
||||||
|
case ConfigurationOption.ConfigurationTypes.TYPE_UINT32:
|
||||||
|
uint uintResult;
|
||||||
|
if (UInt32.TryParse(console_result, out uintResult))
|
||||||
|
{
|
||||||
|
convertSuccess = true;
|
||||||
|
return_result = uintResult;
|
||||||
|
}
|
||||||
|
errorMessage = "an unsigned 32 bit integer (uint)";
|
||||||
|
break;
|
||||||
|
case ConfigurationOption.ConfigurationTypes.TYPE_UINT64:
|
||||||
|
ulong ulongResult;
|
||||||
|
if (UInt64.TryParse(console_result, out ulongResult))
|
||||||
|
{
|
||||||
|
convertSuccess = true;
|
||||||
|
return_result = ulongResult;
|
||||||
|
}
|
||||||
|
errorMessage = "an unsigned 64 bit integer (ulong)";
|
||||||
|
break;
|
||||||
|
case ConfigurationOption.ConfigurationTypes.TYPE_FLOAT:
|
||||||
|
float floatResult;
|
||||||
|
if (
|
||||||
|
float.TryParse(console_result, NumberStyles.AllowDecimalPoint, Culture.NumberFormatInfo,
|
||||||
|
out floatResult))
|
||||||
|
{
|
||||||
|
convertSuccess = true;
|
||||||
|
return_result = floatResult;
|
||||||
|
}
|
||||||
|
errorMessage = "a single-precision floating point number (float)";
|
||||||
|
break;
|
||||||
|
case ConfigurationOption.ConfigurationTypes.TYPE_DOUBLE:
|
||||||
|
double doubleResult;
|
||||||
|
if (
|
||||||
|
Double.TryParse(console_result, NumberStyles.AllowDecimalPoint, Culture.NumberFormatInfo,
|
||||||
|
out doubleResult))
|
||||||
|
{
|
||||||
|
convertSuccess = true;
|
||||||
|
return_result = doubleResult;
|
||||||
|
}
|
||||||
|
errorMessage = "an double-precision floating point number (double)";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (convertSuccess)
|
||||||
|
{
|
||||||
|
if (useFile)
|
||||||
|
{
|
||||||
|
configurationPlugin.SetAttribute(configOption.configurationKey, console_result);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!resultFunction(configOption.configurationKey, return_result))
|
||||||
|
{
|
||||||
|
MainLog.Instance.Notice(
|
||||||
|
"The handler for the last configuration option denied that input, please try again.");
|
||||||
|
convertSuccess = false;
|
||||||
|
ignoreNextFromConfig = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (configOption.configurationUseDefaultNoPrompt)
|
||||||
|
{
|
||||||
|
MainLog.Instance.Error("CONFIG",
|
||||||
|
string.Format(
|
||||||
|
"[{3}]:[{1}] is not valid default for parameter [{0}].\nThe configuration result must be parsable to {2}.\n",
|
||||||
|
configOption.configurationKey, console_result, errorMessage,
|
||||||
|
configurationFilename));
|
||||||
|
convertSuccess = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
MainLog.Instance.Warn("CONFIG",
|
||||||
|
string.Format(
|
||||||
|
"[{3}]:[{1}] is not a valid value [{0}].\nThe configuration result must be parsable to {2}.\n",
|
||||||
|
configOption.configurationKey, console_result, errorMessage,
|
||||||
|
configurationFilename));
|
||||||
|
ignoreNextFromConfig = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (useFile)
|
||||||
|
{
|
||||||
|
configurationPlugin.Commit();
|
||||||
|
configurationPlugin.Close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private IGenericConfig LoadConfigDll(string dllName)
|
||||||
|
{
|
||||||
|
Assembly pluginAssembly = Assembly.LoadFrom(dllName);
|
||||||
|
IGenericConfig plug = null;
|
||||||
|
|
||||||
|
foreach (Type pluginType in pluginAssembly.GetTypes())
|
||||||
|
{
|
||||||
|
if (pluginType.IsPublic)
|
||||||
|
{
|
||||||
|
if (!pluginType.IsAbstract)
|
||||||
|
{
|
||||||
|
Type typeInterface = pluginType.GetInterface("IGenericConfig", true);
|
||||||
|
|
||||||
|
if (typeInterface != null)
|
||||||
|
{
|
||||||
|
plug =
|
||||||
|
(IGenericConfig) Activator.CreateInstance(pluginAssembly.GetType(pluginType.ToString()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pluginAssembly = null;
|
||||||
|
return plug;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void forceSetConfigurationOption(string configuration_key, string configuration_value)
|
||||||
|
{
|
||||||
|
configurationPlugin.LoadData();
|
||||||
|
configurationPlugin.SetAttribute(configuration_key, configuration_value);
|
||||||
|
configurationPlugin.Commit();
|
||||||
|
configurationPlugin.Close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,63 @@
|
||||||
|
/*
|
||||||
|
* 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 OpenSim 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
|
||||||
|
{
|
||||||
|
public class ConfigurationOption
|
||||||
|
{
|
||||||
|
public delegate bool ConfigurationOptionShouldBeAsked(string configuration_key);
|
||||||
|
|
||||||
|
public enum ConfigurationTypes
|
||||||
|
{
|
||||||
|
TYPE_STRING,
|
||||||
|
TYPE_STRING_NOT_EMPTY,
|
||||||
|
TYPE_UINT16,
|
||||||
|
TYPE_UINT32,
|
||||||
|
TYPE_UINT64,
|
||||||
|
TYPE_INT16,
|
||||||
|
TYPE_INT32,
|
||||||
|
TYPE_INT64,
|
||||||
|
TYPE_IP_ADDRESS,
|
||||||
|
TYPE_CHARACTER,
|
||||||
|
TYPE_BOOLEAN,
|
||||||
|
TYPE_BYTE,
|
||||||
|
TYPE_LLUUID,
|
||||||
|
TYPE_LLVECTOR3,
|
||||||
|
TYPE_FLOAT,
|
||||||
|
TYPE_DOUBLE
|
||||||
|
} ;
|
||||||
|
|
||||||
|
public string configurationKey = "";
|
||||||
|
public string configurationQuestion = "";
|
||||||
|
public string configurationDefault = "";
|
||||||
|
|
||||||
|
public ConfigurationTypes configurationType = ConfigurationTypes.TYPE_STRING;
|
||||||
|
public bool configurationUseDefaultNoPrompt = false;
|
||||||
|
public ConfigurationOptionShouldBeAsked shouldIBeAsked; //Should I be asked now? Based on previous answers
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,58 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) Contributors, http://opensimulator.org/
|
||||||
|
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of the OpenSim Project nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
||||||
|
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
// Information about this assembly is defined by the following
|
||||||
|
// attributes.
|
||||||
|
//
|
||||||
|
// change them to the information which is associated with the assembly
|
||||||
|
// you compile.
|
||||||
|
|
||||||
|
[assembly : AssemblyTitle("ServerConsole")]
|
||||||
|
[assembly : AssemblyDescription("")]
|
||||||
|
[assembly : AssemblyConfiguration("")]
|
||||||
|
[assembly : AssemblyCompany("")]
|
||||||
|
[assembly : AssemblyProduct("ServerConsole")]
|
||||||
|
[assembly : AssemblyCopyright("")]
|
||||||
|
[assembly : AssemblyTrademark("")]
|
||||||
|
[assembly : AssemblyCulture("")]
|
||||||
|
|
||||||
|
// This sets the default COM visibility of types in the assembly to invisible.
|
||||||
|
// If you need to expose a type to COM, use [ComVisible(true)] on that type.
|
||||||
|
|
||||||
|
[assembly : ComVisible(false)]
|
||||||
|
|
||||||
|
// The assembly version has following format :
|
||||||
|
//
|
||||||
|
// Major.Minor.Build.Revision
|
||||||
|
//
|
||||||
|
// You can specify all values by your own or you can build default build and revision
|
||||||
|
// numbers with the '*' character (the default):
|
||||||
|
|
||||||
|
[assembly : AssemblyVersion("1.0.*")]
|
|
@ -0,0 +1,35 @@
|
||||||
|
/*
|
||||||
|
* 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 OpenSim 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.Console
|
||||||
|
{
|
||||||
|
public interface conscmd_callback
|
||||||
|
{
|
||||||
|
void RunCmd(string cmd, string[] cmdparams);
|
||||||
|
void Show(string ShowWhat);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,482 @@
|
||||||
|
/*
|
||||||
|
* 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 OpenSim 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.Diagnostics;
|
||||||
|
using System.IO;
|
||||||
|
using System.Net;
|
||||||
|
|
||||||
|
namespace OpenSim.Framework.Console
|
||||||
|
{
|
||||||
|
public enum LogPriority : int
|
||||||
|
{
|
||||||
|
CRITICAL,
|
||||||
|
HIGH,
|
||||||
|
MEDIUM,
|
||||||
|
NORMAL,
|
||||||
|
LOW,
|
||||||
|
VERBOSE,
|
||||||
|
EXTRAVERBOSE
|
||||||
|
}
|
||||||
|
|
||||||
|
public class LogBase
|
||||||
|
{
|
||||||
|
private object m_syncRoot = new object();
|
||||||
|
|
||||||
|
private StreamWriter Log;
|
||||||
|
public conscmd_callback cmdparser;
|
||||||
|
public string componentname;
|
||||||
|
private bool m_verbose;
|
||||||
|
|
||||||
|
public LogBase(string LogFile, string componentname, conscmd_callback cmdparser, bool verbose)
|
||||||
|
{
|
||||||
|
this.componentname = componentname;
|
||||||
|
this.cmdparser = cmdparser;
|
||||||
|
m_verbose = verbose;
|
||||||
|
System.Console.WriteLine("Creating new local console");
|
||||||
|
|
||||||
|
if (String.IsNullOrEmpty(LogFile))
|
||||||
|
{
|
||||||
|
LogFile = componentname + ".log";
|
||||||
|
}
|
||||||
|
|
||||||
|
System.Console.WriteLine("Logs will be saved to current directory in " + LogFile);
|
||||||
|
|
||||||
|
Log = File.AppendText(LogFile);
|
||||||
|
Log.WriteLine("========================================================================");
|
||||||
|
Log.WriteLine(componentname + " Started at " + DateTime.Now.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Close()
|
||||||
|
{
|
||||||
|
Log.WriteLine("Shutdown at " + DateTime.Now.ToString());
|
||||||
|
Log.Close();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// derive an ansi color from a string, ignoring the darker colors.
|
||||||
|
/// This is used to help automatically bin component tags with colors
|
||||||
|
/// in various print functions.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="input">arbitrary string for input</param>
|
||||||
|
/// <returns>an ansii color</returns>
|
||||||
|
private ConsoleColor DeriveColor(string input)
|
||||||
|
{
|
||||||
|
int colIdx = (input.ToUpper().GetHashCode()%6) + 9;
|
||||||
|
return (ConsoleColor) colIdx;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sends a warning to the current log output
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="format">The message to send</param>
|
||||||
|
/// <param name="args">WriteLine-style message arguments</param>
|
||||||
|
public void Warn(string format, params object[] args)
|
||||||
|
{
|
||||||
|
WriteNewLine(ConsoleColor.Yellow, format, args);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sends a warning to the current log output
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="sender">The module that sent this message</param>
|
||||||
|
/// <param name="format">The message to send</param>
|
||||||
|
/// <param name="args">WriteLine-style message arguments</param>
|
||||||
|
public void Warn(string sender, string format, params object[] args)
|
||||||
|
{
|
||||||
|
WritePrefixLine(DeriveColor(sender), sender);
|
||||||
|
WriteNewLine(ConsoleColor.Yellow, format, args);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sends a notice to the current log output
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="format">The message to send</param>
|
||||||
|
/// <param name="args">WriteLine-style message arguments</param>
|
||||||
|
public void Notice(string format, params object[] args)
|
||||||
|
{
|
||||||
|
WriteNewLine(ConsoleColor.White, format, args);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sends a notice to the current log output
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="sender">The module that sent this message</param>
|
||||||
|
/// <param name="format">The message to send</param>
|
||||||
|
/// <param name="args">WriteLine-style message arguments</param>
|
||||||
|
public void Notice(string sender, string format, params object[] args)
|
||||||
|
{
|
||||||
|
WritePrefixLine(DeriveColor(sender), sender);
|
||||||
|
WriteNewLine(ConsoleColor.White, format, args);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sends an error to the current log output
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="format">The message to send</param>
|
||||||
|
/// <param name="args">WriteLine-style message arguments</param>
|
||||||
|
public void Error(string format, params object[] args)
|
||||||
|
{
|
||||||
|
WriteNewLine(ConsoleColor.Red, format, args);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sends an error to the current log output
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="sender">The module that sent this message</param>
|
||||||
|
/// <param name="format">The message to send</param>
|
||||||
|
/// <param name="args">WriteLine-style message arguments</param>
|
||||||
|
public void Error(string sender, string format, params object[] args)
|
||||||
|
{
|
||||||
|
WritePrefixLine(DeriveColor(sender), sender);
|
||||||
|
Error(format, args);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sends an informational message to the current log output
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="sender">The module that sent this message</param>
|
||||||
|
/// <param name="format">The message to send</param>
|
||||||
|
/// <param name="args">WriteLine-style message arguments</param>
|
||||||
|
public void Verbose(string sender, string format, params object[] args)
|
||||||
|
{
|
||||||
|
if (m_verbose)
|
||||||
|
{
|
||||||
|
WritePrefixLine(DeriveColor(sender), sender);
|
||||||
|
WriteNewLine(ConsoleColor.Gray, format, args);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sends a status message to the current log output
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="format">The message to send</param>
|
||||||
|
/// <param name="args">WriteLine-style message arguments</param>
|
||||||
|
public void Status(string format, params object[] args)
|
||||||
|
{
|
||||||
|
WriteNewLine(ConsoleColor.Blue, format, args);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sends a status message to the current log output
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="sender">The module that sent this message</param>
|
||||||
|
/// <param name="format">The message to send</param>
|
||||||
|
/// <param name="args">WriteLine-style message arguments</param>
|
||||||
|
public void Status(string sender, string format, params object[] args)
|
||||||
|
{
|
||||||
|
WritePrefixLine(DeriveColor(sender), sender);
|
||||||
|
WriteNewLine(ConsoleColor.Blue, format, args);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
[Conditional("DEBUG")]
|
||||||
|
public void Debug(string format, params object[] args)
|
||||||
|
{
|
||||||
|
WriteNewLine(ConsoleColor.Gray, format, args);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
[Conditional("DEBUG")]
|
||||||
|
public void Debug(string sender, string format, params object[] args)
|
||||||
|
{
|
||||||
|
WritePrefixLine(DeriveColor(sender), sender);
|
||||||
|
WriteNewLine(ConsoleColor.Gray, format, args);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void WriteNewLine(ConsoleColor color, string format, params object[] args)
|
||||||
|
{
|
||||||
|
lock (m_syncRoot)
|
||||||
|
{
|
||||||
|
string now = DateTime.Now.ToString("[MM-dd hh:mm:ss] ");
|
||||||
|
Log.Write(now);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Log.WriteLine(format, args);
|
||||||
|
Log.Flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
catch (FormatException)
|
||||||
|
{
|
||||||
|
System.Console.WriteLine(args);
|
||||||
|
}
|
||||||
|
System.Console.Write(now);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (color != ConsoleColor.White)
|
||||||
|
System.Console.ForegroundColor = color;
|
||||||
|
|
||||||
|
System.Console.WriteLine(format, args);
|
||||||
|
System.Console.ResetColor();
|
||||||
|
}
|
||||||
|
catch (ArgumentNullException)
|
||||||
|
{
|
||||||
|
// Some older systems dont support coloured text.
|
||||||
|
System.Console.WriteLine(format, args);
|
||||||
|
}
|
||||||
|
catch (FormatException)
|
||||||
|
{
|
||||||
|
// Some older systems dont support coloured text.
|
||||||
|
System.Console.WriteLine(args);
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void WritePrefixLine(ConsoleColor color, string sender)
|
||||||
|
{
|
||||||
|
lock (m_syncRoot)
|
||||||
|
{
|
||||||
|
sender = sender.ToUpper();
|
||||||
|
Log.WriteLine("[" + sender + "] ");
|
||||||
|
Log.Flush();
|
||||||
|
|
||||||
|
System.Console.Write("[");
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
System.Console.ForegroundColor = color;
|
||||||
|
System.Console.Write(sender);
|
||||||
|
System.Console.ResetColor();
|
||||||
|
}
|
||||||
|
catch (ArgumentNullException)
|
||||||
|
{
|
||||||
|
// Some older systems dont support coloured text.
|
||||||
|
System.Console.WriteLine(sender);
|
||||||
|
}
|
||||||
|
|
||||||
|
System.Console.Write("] \t");
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public string ReadLine()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
string TempStr = System.Console.ReadLine();
|
||||||
|
Log.WriteLine(TempStr);
|
||||||
|
return TempStr;
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
MainLog.Instance.Error("Console", "System.Console.ReadLine exception " + e.ToString());
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int Read()
|
||||||
|
{
|
||||||
|
int TempInt = System.Console.Read();
|
||||||
|
Log.Write((char) TempInt);
|
||||||
|
return TempInt;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IPAddress CmdPromptIPAddress(string prompt, string defaultvalue)
|
||||||
|
{
|
||||||
|
IPAddress address;
|
||||||
|
string addressStr;
|
||||||
|
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
addressStr = MainLog.Instance.CmdPrompt(prompt, defaultvalue);
|
||||||
|
if (IPAddress.TryParse(addressStr, out address))
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
MainLog.Instance.Error("Illegal address. Please re-enter.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return address;
|
||||||
|
}
|
||||||
|
|
||||||
|
public uint CmdPromptIPPort(string prompt, string defaultvalue)
|
||||||
|
{
|
||||||
|
uint port;
|
||||||
|
string portStr;
|
||||||
|
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
portStr = MainLog.Instance.CmdPrompt(prompt, defaultvalue);
|
||||||
|
if (uint.TryParse(portStr, out port))
|
||||||
|
{
|
||||||
|
if (port >= IPEndPoint.MinPort && port <= IPEndPoint.MaxPort)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MainLog.Instance.Error("Illegal address. Please re-enter.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return port;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Displays a prompt and waits for the user to enter a string, then returns that string
|
||||||
|
// Done with no echo and suitable for passwords
|
||||||
|
public string PasswdPrompt(string prompt)
|
||||||
|
{
|
||||||
|
// FIXME: Needs to be better abstracted
|
||||||
|
Log.WriteLine(prompt);
|
||||||
|
Notice(prompt);
|
||||||
|
ConsoleColor oldfg = System.Console.ForegroundColor;
|
||||||
|
System.Console.ForegroundColor = System.Console.BackgroundColor;
|
||||||
|
string temp = System.Console.ReadLine();
|
||||||
|
System.Console.ForegroundColor = oldfg;
|
||||||
|
return temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Displays a command prompt and waits for the user to enter a string, then returns that string
|
||||||
|
public string CmdPrompt(string prompt)
|
||||||
|
{
|
||||||
|
Notice(String.Format("{0}: ", prompt));
|
||||||
|
return ReadLine();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Displays a command prompt and returns a default value if the user simply presses enter
|
||||||
|
public string CmdPrompt(string prompt, string defaultresponse)
|
||||||
|
{
|
||||||
|
string temp = CmdPrompt(String.Format("{0} [{1}]", prompt, defaultresponse));
|
||||||
|
if (temp == "")
|
||||||
|
{
|
||||||
|
return defaultresponse;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return temp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Displays a command prompt and returns a default value, user may only enter 1 of 2 options
|
||||||
|
public string CmdPrompt(string prompt, string defaultresponse, string OptionA, string OptionB)
|
||||||
|
{
|
||||||
|
bool itisdone = false;
|
||||||
|
string temp = CmdPrompt(prompt, defaultresponse);
|
||||||
|
while (itisdone == false)
|
||||||
|
{
|
||||||
|
if ((temp == OptionA) || (temp == OptionB))
|
||||||
|
{
|
||||||
|
itisdone = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Notice("Valid options are " + OptionA + " or " + OptionB);
|
||||||
|
temp = CmdPrompt(prompt, defaultresponse);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Runs a command with a number of parameters
|
||||||
|
public Object RunCmd(string Cmd, string[] cmdparams)
|
||||||
|
{
|
||||||
|
cmdparser.RunCmd(Cmd, cmdparams);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Shows data about something
|
||||||
|
public void ShowCommands(string ShowWhat)
|
||||||
|
{
|
||||||
|
cmdparser.Show(ShowWhat);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void MainLogPrompt()
|
||||||
|
{
|
||||||
|
string tempstr = CmdPrompt(componentname + "# ");
|
||||||
|
MainLogRunCommand(tempstr);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void MainLogRunCommand(string command)
|
||||||
|
{
|
||||||
|
string[] tempstrarray;
|
||||||
|
tempstrarray = command.Split(' ');
|
||||||
|
string cmd = tempstrarray[0];
|
||||||
|
Array.Reverse(tempstrarray);
|
||||||
|
Array.Resize<string>(ref tempstrarray, tempstrarray.Length - 1);
|
||||||
|
Array.Reverse(tempstrarray);
|
||||||
|
string[] cmdparams = (string[]) tempstrarray;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
RunCmd(cmd, cmdparams);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
MainLog.Instance.Error("Console", "Command failed with exception " + e.ToString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public string LineInfo
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
string result = String.Empty;
|
||||||
|
|
||||||
|
string stacktrace = Environment.StackTrace;
|
||||||
|
List<string> lines = new List<string>(stacktrace.Split(new string[] {"at "}, StringSplitOptions.None));
|
||||||
|
|
||||||
|
if (lines.Count > 4)
|
||||||
|
{
|
||||||
|
lines.RemoveRange(0, 4);
|
||||||
|
|
||||||
|
string tmpLine = lines[0];
|
||||||
|
|
||||||
|
int inIndex = tmpLine.IndexOf(" in ");
|
||||||
|
|
||||||
|
if (inIndex > -1)
|
||||||
|
{
|
||||||
|
result = tmpLine.Substring(0, inIndex);
|
||||||
|
|
||||||
|
int lineIndex = tmpLine.IndexOf(":line ");
|
||||||
|
|
||||||
|
if (lineIndex > -1)
|
||||||
|
{
|
||||||
|
lineIndex += 6;
|
||||||
|
result += ", line " + tmpLine.Substring(lineIndex, (tmpLine.Length - lineIndex) - 5);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,40 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) Contributors, http://opensimulator.org/
|
||||||
|
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of the OpenSim 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.Console
|
||||||
|
{
|
||||||
|
public class MainLog
|
||||||
|
{
|
||||||
|
private static LogBase instance;
|
||||||
|
|
||||||
|
public static LogBase Instance
|
||||||
|
{
|
||||||
|
get { return instance; }
|
||||||
|
set { instance = value; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,54 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) Contributors, http://opensimulator.org/
|
||||||
|
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of the OpenSim 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.Globalization;
|
||||||
|
using System.Threading;
|
||||||
|
|
||||||
|
namespace OpenSim.Framework
|
||||||
|
{
|
||||||
|
public class Culture
|
||||||
|
{
|
||||||
|
private static readonly CultureInfo m_cultureInfo = new CultureInfo("en-US", true);
|
||||||
|
|
||||||
|
public static NumberFormatInfo NumberFormatInfo
|
||||||
|
{
|
||||||
|
get { return m_cultureInfo.NumberFormat; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IFormatProvider FormatProvider
|
||||||
|
{
|
||||||
|
get { return m_cultureInfo; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void SetCurrentCulture()
|
||||||
|
{
|
||||||
|
Thread.CurrentThread.CurrentCulture = m_cultureInfo;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,177 @@
|
||||||
|
/*
|
||||||
|
* 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 OpenSim 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 libsecondlife;
|
||||||
|
|
||||||
|
namespace OpenSim.Framework.Data.DB4o
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// A grid server storage mechanism employing the DB4o database system
|
||||||
|
/// </summary>
|
||||||
|
internal class DB4oGridData : IGridData
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The database manager object
|
||||||
|
/// </summary>
|
||||||
|
private DB4oGridManager manager;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Called when the plugin is first loaded (as constructors are not called)
|
||||||
|
/// </summary>
|
||||||
|
public void Initialise()
|
||||||
|
{
|
||||||
|
manager = new DB4oGridManager("gridserver.yap");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns a list of regions within the specified ranges
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="a">minimum X coordinate</param>
|
||||||
|
/// <param name="b">minimum Y coordinate</param>
|
||||||
|
/// <param name="c">maximum X coordinate</param>
|
||||||
|
/// <param name="d">maximum Y coordinate</param>
|
||||||
|
/// <returns>An array of region profiles</returns>
|
||||||
|
public RegionProfileData[] GetProfilesInRange(uint a, uint b, uint c, uint d)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns a region located at the specified regionHandle (warning multiple regions may occupy the one spot, first found is returned)
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="handle">The handle to search for</param>
|
||||||
|
/// <returns>A region profile</returns>
|
||||||
|
public RegionProfileData GetProfileByHandle(ulong handle)
|
||||||
|
{
|
||||||
|
lock (manager.simProfiles)
|
||||||
|
{
|
||||||
|
foreach (LLUUID UUID in manager.simProfiles.Keys)
|
||||||
|
{
|
||||||
|
if (manager.simProfiles[UUID].regionHandle == handle)
|
||||||
|
{
|
||||||
|
return manager.simProfiles[UUID];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new Exception("Unable to find profile with handle (" + handle.ToString() + ")");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns a specific region
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="uuid">The region ID code</param>
|
||||||
|
/// <returns>A region profile</returns>
|
||||||
|
public RegionProfileData GetProfileByLLUUID(LLUUID uuid)
|
||||||
|
{
|
||||||
|
lock (manager.simProfiles)
|
||||||
|
{
|
||||||
|
if (manager.simProfiles.ContainsKey(uuid))
|
||||||
|
return manager.simProfiles[uuid];
|
||||||
|
}
|
||||||
|
throw new Exception("Unable to find profile with UUID (" + uuid.ToString() +
|
||||||
|
"). Total Registered Regions: " + manager.simProfiles.Count);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Adds a new specified region to the database
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="profile">The profile to add</param>
|
||||||
|
/// <returns>A dataresponse enum indicating success</returns>
|
||||||
|
public DataResponse AddProfile(RegionProfileData profile)
|
||||||
|
{
|
||||||
|
lock (manager.simProfiles)
|
||||||
|
{
|
||||||
|
if (manager.AddRow(profile))
|
||||||
|
{
|
||||||
|
return DataResponse.RESPONSE_OK;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return DataResponse.RESPONSE_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Authenticates a new region using the shared secrets. NOT SECURE.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="uuid">The UUID the region is authenticating with</param>
|
||||||
|
/// <param name="handle">The location the region is logging into (unused in Db4o)</param>
|
||||||
|
/// <param name="key">The shared secret</param>
|
||||||
|
/// <returns>Authenticated?</returns>
|
||||||
|
public bool AuthenticateSim(LLUUID uuid, ulong handle, string key)
|
||||||
|
{
|
||||||
|
if (manager.simProfiles[uuid].regionRecvKey == key)
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Shuts down the database
|
||||||
|
/// </summary>
|
||||||
|
public void Close()
|
||||||
|
{
|
||||||
|
manager = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// // Returns a list of avatar and UUIDs that match the query
|
||||||
|
/// </summary>
|
||||||
|
public List<AvatarPickerAvatar> GeneratePickerResults(LLUUID queryID, string query)
|
||||||
|
{
|
||||||
|
//Do nothing yet
|
||||||
|
List<AvatarPickerAvatar> returnlist = new List<AvatarPickerAvatar>();
|
||||||
|
return returnlist;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the providers name
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>The name of the storage system</returns>
|
||||||
|
public string getName()
|
||||||
|
{
|
||||||
|
return "DB4o Grid Provider";
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the providers version
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>The version of the storage system</returns>
|
||||||
|
public string getVersion()
|
||||||
|
{
|
||||||
|
return "0.1";
|
||||||
|
}
|
||||||
|
|
||||||
|
public ReservationData GetReservationAtPoint(uint x, uint y)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,170 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) Contributors, http://opensimulator.org/
|
||||||
|
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of the OpenSim 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 Db4objects.Db4o;
|
||||||
|
using libsecondlife;
|
||||||
|
|
||||||
|
namespace OpenSim.Framework.Data.DB4o
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// A Database manager for Db4o
|
||||||
|
/// </summary>
|
||||||
|
internal class DB4oGridManager
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// A list of the current regions connected (in-memory cache)
|
||||||
|
/// </summary>
|
||||||
|
public Dictionary<LLUUID, RegionProfileData> simProfiles = new Dictionary<LLUUID, RegionProfileData>();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Database File Name
|
||||||
|
/// </summary>
|
||||||
|
private string dbfl;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a new grid storage manager
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="db4odb">Filename to the database file</param>
|
||||||
|
public DB4oGridManager(string db4odb)
|
||||||
|
{
|
||||||
|
dbfl = db4odb;
|
||||||
|
IObjectContainer database;
|
||||||
|
database = Db4oFactory.OpenFile(dbfl);
|
||||||
|
IObjectSet result = database.Get(typeof (RegionProfileData));
|
||||||
|
// Loads the file into the in-memory cache
|
||||||
|
foreach (RegionProfileData row in result)
|
||||||
|
{
|
||||||
|
simProfiles.Add(row.UUID, row);
|
||||||
|
}
|
||||||
|
database.Close();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Adds a new profile to the database (Warning: Probably slow.)
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="row">The profile to add</param>
|
||||||
|
/// <returns>Successful?</returns>
|
||||||
|
public bool AddRow(RegionProfileData row)
|
||||||
|
{
|
||||||
|
if (simProfiles.ContainsKey(row.UUID))
|
||||||
|
{
|
||||||
|
simProfiles[row.UUID] = row;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
simProfiles.Add(row.UUID, row);
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
IObjectContainer database;
|
||||||
|
database = Db4oFactory.OpenFile(dbfl);
|
||||||
|
database.Set(row);
|
||||||
|
database.Close();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A manager for the DB4o database (user profiles)
|
||||||
|
/// </summary>
|
||||||
|
internal class DB4oUserManager
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// A list of the user profiles (in memory cache)
|
||||||
|
/// </summary>
|
||||||
|
public Dictionary<LLUUID, UserProfileData> userProfiles = new Dictionary<LLUUID, UserProfileData>();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Database filename
|
||||||
|
/// </summary>
|
||||||
|
private string dbfl;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initialises a new DB manager
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="db4odb">The filename to the database</param>
|
||||||
|
public DB4oUserManager(string db4odb)
|
||||||
|
{
|
||||||
|
dbfl = db4odb;
|
||||||
|
IObjectContainer database;
|
||||||
|
database = Db4oFactory.OpenFile(dbfl);
|
||||||
|
// Load to cache
|
||||||
|
IObjectSet result = database.Get(typeof (UserProfileData));
|
||||||
|
foreach (UserProfileData row in result)
|
||||||
|
{
|
||||||
|
if (userProfiles.ContainsKey(row.UUID))
|
||||||
|
userProfiles[row.UUID] = row;
|
||||||
|
else
|
||||||
|
userProfiles.Add(row.UUID, row);
|
||||||
|
}
|
||||||
|
database.Close();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Adds or updates a record to the user database. Do this when changes are needed
|
||||||
|
/// in the user profile that need to be persistant.
|
||||||
|
///
|
||||||
|
/// TODO: the logic here is not ACID, the local cache will be
|
||||||
|
/// updated even if the persistant data is not. This may lead
|
||||||
|
/// to unexpected results.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="record">The profile to update</param>
|
||||||
|
/// <returns>true on success, false on fail to persist to db</returns>
|
||||||
|
public bool UpdateRecord(UserProfileData record)
|
||||||
|
{
|
||||||
|
if (userProfiles.ContainsKey(record.UUID))
|
||||||
|
{
|
||||||
|
userProfiles[record.UUID] = record;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
userProfiles.Add(record.UUID, record);
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
IObjectContainer database;
|
||||||
|
database = Db4oFactory.OpenFile(dbfl);
|
||||||
|
database.Set(record);
|
||||||
|
database.Close();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,277 @@
|
||||||
|
/*
|
||||||
|
* 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 OpenSim Project nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
||||||
|
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using libsecondlife;
|
||||||
|
|
||||||
|
namespace OpenSim.Framework.Data.DB4o
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// A User storage interface for the DB4o database system
|
||||||
|
/// </summary>
|
||||||
|
public class DB4oUserData : IUserData
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The database manager
|
||||||
|
/// </summary>
|
||||||
|
private DB4oUserManager manager;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Artificial constructor called upon plugin load
|
||||||
|
/// </summary>
|
||||||
|
public void Initialise()
|
||||||
|
{
|
||||||
|
manager = new DB4oUserManager(Path.Combine(Util.dataDir(), "userprofiles.yap"));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Loads a specified user profile from a UUID
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="uuid">The users UUID</param>
|
||||||
|
/// <returns>A user profile</returns>
|
||||||
|
public UserProfileData GetUserByUUID(LLUUID uuid)
|
||||||
|
{
|
||||||
|
if (manager.userProfiles.ContainsKey(uuid))
|
||||||
|
return manager.userProfiles[uuid];
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Loads a specified user profile from a account
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="uuid">The users account</param>
|
||||||
|
/// <returns>A user profile</returns>
|
||||||
|
public UserProfileData GetUserByAccount(string account)
|
||||||
|
{
|
||||||
|
if (manager.userProfiles.ContainsKey(account))
|
||||||
|
return manager.userProfiles[account];
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns a user by searching for its name
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="name">The users account name</param>
|
||||||
|
/// <returns>A matching users profile</returns>
|
||||||
|
public UserProfileData GetUserByName(string name)
|
||||||
|
{
|
||||||
|
return GetUserByName(name.Split(' ')[0], name.Split(' ')[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns a user by searching for its name
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="fname">The first part of the users account name</param>
|
||||||
|
/// <param name="lname">The second part of the users account name</param>
|
||||||
|
/// <returns>A matching users profile</returns>
|
||||||
|
public UserProfileData GetUserByName(string fname, string lname)
|
||||||
|
{
|
||||||
|
foreach (UserProfileData profile in manager.userProfiles.Values)
|
||||||
|
{
|
||||||
|
if (profile.username == fname && profile.surname == lname)
|
||||||
|
return profile;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns a user by UUID direct
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="uuid">The users account ID</param>
|
||||||
|
/// <returns>A matching users profile</returns>
|
||||||
|
public UserAgentData GetAgentByUUID(LLUUID uuid)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return GetUserByUUID(uuid).currentAgent;
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns a session by account name
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="name">The account name</param>
|
||||||
|
/// <returns>The users session agent</returns>
|
||||||
|
public UserAgentData GetAgentByName(string name)
|
||||||
|
{
|
||||||
|
return GetAgentByName(name.Split(' ')[0], name.Split(' ')[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns a session by account name
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="fname">The first part of the users account name</param>
|
||||||
|
/// <param name="lname">The second part of the users account name</param>
|
||||||
|
/// <returns>A user agent</returns>
|
||||||
|
public UserAgentData GetAgentByName(string fname, string lname)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return GetUserByName(fname, lname).currentAgent;
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#region User Friends List Data
|
||||||
|
|
||||||
|
public void AddNewUserFriend(LLUUID friendlistowner, LLUUID friend, uint perms)
|
||||||
|
{
|
||||||
|
//MainLog.Instance.Verbose("FRIEND", "Stub AddNewUserFriend called");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RemoveUserFriend(LLUUID friendlistowner, LLUUID friend)
|
||||||
|
{
|
||||||
|
//MainLog.Instance.Verbose("FRIEND", "Stub RemoveUserFriend called");
|
||||||
|
}
|
||||||
|
public void UpdateUserFriendPerms(LLUUID friendlistowner, LLUUID friend, uint perms)
|
||||||
|
{
|
||||||
|
//MainLog.Instance.Verbose("FRIEND", "Stub UpdateUserFriendPerms called");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public List<FriendListItem> GetUserFriendList(LLUUID friendlistowner)
|
||||||
|
{
|
||||||
|
//MainLog.Instance.Verbose("FRIEND", "Stub GetUserFriendList called");
|
||||||
|
return new List<FriendListItem>();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
public void UpdateUserCurrentRegion(LLUUID avatarid, LLUUID regionuuid)
|
||||||
|
{
|
||||||
|
//MainLog.Instance.Verbose("USER", "Stub UpdateUserCUrrentRegion called");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void LogOffUser(LLUUID avatarid)
|
||||||
|
{
|
||||||
|
//MainLog.Instance.Verbose("USER", "Stub LogOffUser called");
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Framework.AvatarPickerAvatar> GeneratePickerResults(LLUUID queryID, string query)
|
||||||
|
{
|
||||||
|
//Do nothing yet
|
||||||
|
List<Framework.AvatarPickerAvatar> returnlist = new List<Framework.AvatarPickerAvatar>();
|
||||||
|
return returnlist;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a new user profile
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="user">The profile to add to the database</param>
|
||||||
|
public void AddNewUserProfile(UserProfileData user)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
manager.UpdateRecord(user);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Console.WriteLine(e.ToString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a new user profile
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="user">The profile to add to the database</param>
|
||||||
|
/// <returns>True on success, false on error</returns>
|
||||||
|
public bool UpdateUserProfile(UserProfileData user)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return manager.UpdateRecord(user);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Console.WriteLine(e.ToString());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a new user agent
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="agent">The agent to add to the database</param>
|
||||||
|
public void AddNewUserAgent(UserAgentData agent)
|
||||||
|
{
|
||||||
|
// Do nothing. yet.
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Transfers money between two user accounts
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="from">Starting account</param>
|
||||||
|
/// <param name="to">End account</param>
|
||||||
|
/// <param name="amount">The amount to move</param>
|
||||||
|
/// <returns>Success?</returns>
|
||||||
|
public bool MoneyTransferRequest(LLUUID from, LLUUID to, uint amount)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Transfers inventory between two accounts
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>Move to inventory server</remarks>
|
||||||
|
/// <param name="from">Senders account</param>
|
||||||
|
/// <param name="to">Receivers account</param>
|
||||||
|
/// <param name="item">Inventory item</param>
|
||||||
|
/// <returns>Success?</returns>
|
||||||
|
public bool InventoryTransferRequest(LLUUID from, LLUUID to, LLUUID item)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the name of the storage provider
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>Storage provider name</returns>
|
||||||
|
public string getName()
|
||||||
|
{
|
||||||
|
return "DB4o Userdata";
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the version of the storage provider
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>Storage provider version</returns>
|
||||||
|
public string GetVersion()
|
||||||
|
{
|
||||||
|
return "0.1";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,38 @@
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
// General Information about an assembly is controlled through the following
|
||||||
|
// set of attributes. Change these attribute values to modify the information
|
||||||
|
// associated with an assembly.
|
||||||
|
|
||||||
|
[assembly : AssemblyTitle("OpenSim.Framework.Data.DB4o")]
|
||||||
|
[assembly : AssemblyDescription("")]
|
||||||
|
[assembly : AssemblyConfiguration("")]
|
||||||
|
[assembly : AssemblyCompany("")]
|
||||||
|
[assembly : AssemblyProduct("OpenSim.Framework.Data.DB4o")]
|
||||||
|
[assembly : AssemblyCopyright("Copyright © 2007")]
|
||||||
|
[assembly : AssemblyTrademark("")]
|
||||||
|
[assembly : AssemblyCulture("")]
|
||||||
|
|
||||||
|
// Setting ComVisible to false makes the types in this assembly not visible
|
||||||
|
// to COM components. If you need to access a type in this assembly from
|
||||||
|
// COM, set the ComVisible attribute to true on that type.
|
||||||
|
|
||||||
|
[assembly : ComVisible(false)]
|
||||||
|
|
||||||
|
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||||
|
|
||||||
|
[assembly : Guid("57991e15-79da-41b7-aa06-2e6b49165a63")]
|
||||||
|
|
||||||
|
// Version information for an assembly consists of the following four values:
|
||||||
|
//
|
||||||
|
// Major Version
|
||||||
|
// Minor Version
|
||||||
|
// Build Number
|
||||||
|
// Revision
|
||||||
|
//
|
||||||
|
// You can specify all the values or you can default the Revision and Build Numbers
|
||||||
|
// by using the '*' as shown below:
|
||||||
|
|
||||||
|
[assembly : AssemblyVersion("1.0.0.0")]
|
||||||
|
[assembly : AssemblyFileVersion("1.0.0.0")]
|
|
@ -0,0 +1,240 @@
|
||||||
|
/*
|
||||||
|
* 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 OpenSim 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.Data;
|
||||||
|
using System.Data.SqlClient;
|
||||||
|
using libsecondlife;
|
||||||
|
using OpenSim.Framework.Console;
|
||||||
|
|
||||||
|
namespace OpenSim.Framework.Data.MSSQL
|
||||||
|
{
|
||||||
|
internal class MSSQLAssetData : IAssetProvider
|
||||||
|
{
|
||||||
|
private MSSQLManager database;
|
||||||
|
|
||||||
|
#region IAssetProvider Members
|
||||||
|
|
||||||
|
private void UpgradeAssetsTable(string tableName)
|
||||||
|
{
|
||||||
|
// null as the version, indicates that the table didn't exist
|
||||||
|
if (tableName == null)
|
||||||
|
{
|
||||||
|
MainLog.Instance.Notice("ASSETS", "Creating new database tables");
|
||||||
|
database.ExecuteResourceSql("CreateAssetsTable.sql");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Ensure that the assets related tables exists and are at the latest version
|
||||||
|
/// </summary>
|
||||||
|
private void TestTables()
|
||||||
|
{
|
||||||
|
Dictionary<string, string> tableList = new Dictionary<string, string>();
|
||||||
|
|
||||||
|
tableList["assets"] = null;
|
||||||
|
database.GetTableVersion(tableList);
|
||||||
|
|
||||||
|
UpgradeAssetsTable(tableList["assets"]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public AssetBase FetchAsset(LLUUID assetID)
|
||||||
|
{
|
||||||
|
AssetBase asset = null;
|
||||||
|
|
||||||
|
Dictionary<string, string> param = new Dictionary<string, string>();
|
||||||
|
param["id"] = assetID.ToString();
|
||||||
|
|
||||||
|
IDbCommand result = database.Query("SELECT * FROM assets WHERE id = @id", param);
|
||||||
|
IDataReader reader = result.ExecuteReader();
|
||||||
|
|
||||||
|
asset = database.getAssetRow(reader);
|
||||||
|
reader.Close();
|
||||||
|
result.Dispose();
|
||||||
|
|
||||||
|
return asset;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void CreateAsset(AssetBase asset)
|
||||||
|
{
|
||||||
|
if (ExistsAsset((LLUUID) asset.FullID))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
SqlCommand cmd =
|
||||||
|
new SqlCommand(
|
||||||
|
"INSERT INTO assets ([id], [name], [mediaUrl], [description], [assetType], [invType], [local], [temporary], [data])" +
|
||||||
|
" VALUES " +
|
||||||
|
"(@id, @name, @mediaUrl, @description, @assetType, @invType, @local, @temporary, @data)",
|
||||||
|
database.getConnection());
|
||||||
|
|
||||||
|
using (cmd)
|
||||||
|
{
|
||||||
|
//SqlParameter p = cmd.Parameters.Add("id", SqlDbType.NVarChar);
|
||||||
|
//p.Value = asset.FullID.ToString();
|
||||||
|
cmd.Parameters.AddWithValue("id", asset.FullID.ToString());
|
||||||
|
cmd.Parameters.AddWithValue("name", asset.Name);
|
||||||
|
cmd.Parameters.AddWithValue("mediaUrl", asset.MediaURL);
|
||||||
|
cmd.Parameters.AddWithValue("description", asset.Description);
|
||||||
|
SqlParameter e = cmd.Parameters.Add("assetType", SqlDbType.TinyInt);
|
||||||
|
e.Value = asset.Type;
|
||||||
|
SqlParameter f = cmd.Parameters.Add("invType", SqlDbType.TinyInt);
|
||||||
|
f.Value = asset.InvType;
|
||||||
|
SqlParameter g = cmd.Parameters.Add("local", SqlDbType.TinyInt);
|
||||||
|
g.Value = asset.Local;
|
||||||
|
SqlParameter h = cmd.Parameters.Add("temporary", SqlDbType.TinyInt);
|
||||||
|
h.Value = asset.Temporary;
|
||||||
|
SqlParameter i = cmd.Parameters.Add("data", SqlDbType.Image);
|
||||||
|
i.Value = asset.Data;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
cmd.ExecuteNonQuery();
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void UpdateAsset(AssetBase asset)
|
||||||
|
{
|
||||||
|
SqlCommand command = new SqlCommand("UPDATE assets set id = @id, " +
|
||||||
|
"name = @name, " +
|
||||||
|
"mediaUrl = @mediaUrl, "+
|
||||||
|
"description = @description," +
|
||||||
|
"assetType = @assetType," +
|
||||||
|
"invType = @invType," +
|
||||||
|
"local = @local," +
|
||||||
|
"temporary = @temporary," +
|
||||||
|
"data = @data where " +
|
||||||
|
"id = @keyId;", database.getConnection());
|
||||||
|
SqlParameter param1 = new SqlParameter("@id", asset.FullID.ToString());
|
||||||
|
SqlParameter param2 = new SqlParameter("@name", asset.Name);
|
||||||
|
SqlParameter param3 = new SqlParameter("@mediaUrl", asset.MediaURL);
|
||||||
|
SqlParameter param4 = new SqlParameter("@description", asset.Description);
|
||||||
|
SqlParameter param5 = new SqlParameter("@assetType", Convert.ToBoolean(asset.Type));
|
||||||
|
SqlParameter param6 = new SqlParameter("@invType", Convert.ToBoolean(asset.InvType));
|
||||||
|
SqlParameter param7 = new SqlParameter("@local", asset.Local);
|
||||||
|
SqlParameter param8 = new SqlParameter("@temporary", asset.Temporary);
|
||||||
|
SqlParameter param9 = new SqlParameter("@data", asset.Data);
|
||||||
|
SqlParameter param10 = new SqlParameter("@keyId", asset.FullID.ToString());
|
||||||
|
command.Parameters.Add(param1);
|
||||||
|
command.Parameters.Add(param2);
|
||||||
|
command.Parameters.Add(param3);
|
||||||
|
command.Parameters.Add(param4);
|
||||||
|
command.Parameters.Add(param5);
|
||||||
|
command.Parameters.Add(param6);
|
||||||
|
command.Parameters.Add(param7);
|
||||||
|
command.Parameters.Add(param8);
|
||||||
|
command.Parameters.Add(param9);
|
||||||
|
command.Parameters.Add(param10);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
command.ExecuteNonQuery();
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
MainLog.Instance.Error(e.ToString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool ExistsAsset(LLUUID uuid)
|
||||||
|
{
|
||||||
|
if (FetchAsset(uuid) != null)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// rex, new function, fixme not implemented
|
||||||
|
public List<AssetBase> GetAssetList(int vAssetType)
|
||||||
|
{
|
||||||
|
List<AssetBase> retvals = new List<AssetBase>();
|
||||||
|
return retvals;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// All writes are immediately commited to the database, so this is a no-op
|
||||||
|
/// </summary>
|
||||||
|
public void CommitAssets()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// rex new function for "replace assets" functionality
|
||||||
|
// TODO: actual implementation by someone, should return LLUUID of an asset
|
||||||
|
// with matching type & name, or zero if not in DB
|
||||||
|
public LLUUID ExistsAsset(sbyte type, string name)
|
||||||
|
{
|
||||||
|
return LLUUID.Zero;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region IPlugin Members
|
||||||
|
|
||||||
|
public void Initialise()
|
||||||
|
{
|
||||||
|
IniFile GridDataMySqlFile = new IniFile("mssql_connection.ini");
|
||||||
|
string settingDataSource = GridDataMySqlFile.ParseFileReadValue("data_source");
|
||||||
|
string settingInitialCatalog = GridDataMySqlFile.ParseFileReadValue("initial_catalog");
|
||||||
|
string settingPersistSecurityInfo = GridDataMySqlFile.ParseFileReadValue("persist_security_info");
|
||||||
|
string settingUserId = GridDataMySqlFile.ParseFileReadValue("user_id");
|
||||||
|
string settingPassword = GridDataMySqlFile.ParseFileReadValue("password");
|
||||||
|
|
||||||
|
database =
|
||||||
|
new MSSQLManager(settingDataSource, settingInitialCatalog, settingPersistSecurityInfo, settingUserId,
|
||||||
|
settingPassword);
|
||||||
|
|
||||||
|
TestTables();
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Version
|
||||||
|
{
|
||||||
|
// get { return database.getVersion(); }
|
||||||
|
get { return database.getVersion(); }
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Name
|
||||||
|
{
|
||||||
|
get { return "MSSQL Asset storage engine"; }
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,309 @@
|
||||||
|
/*
|
||||||
|
* 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 OpenSim 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.Data;
|
||||||
|
using System.Security.Cryptography;
|
||||||
|
using System.Text;
|
||||||
|
using libsecondlife;
|
||||||
|
using OpenSim.Framework.Console;
|
||||||
|
|
||||||
|
namespace OpenSim.Framework.Data.MSSQL
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// A grid data interface for Microsoft SQL Server
|
||||||
|
/// </summary>
|
||||||
|
public class SqlGridData : IGridData
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Database manager
|
||||||
|
/// </summary>
|
||||||
|
private MSSQLManager database;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initialises the Grid Interface
|
||||||
|
/// </summary>
|
||||||
|
public void Initialise()
|
||||||
|
{
|
||||||
|
IniFile GridDataMySqlFile = new IniFile("mssql_connection.ini");
|
||||||
|
string settingDataSource = GridDataMySqlFile.ParseFileReadValue("data_source");
|
||||||
|
string settingInitialCatalog = GridDataMySqlFile.ParseFileReadValue("initial_catalog");
|
||||||
|
string settingPersistSecurityInfo = GridDataMySqlFile.ParseFileReadValue("persist_security_info");
|
||||||
|
string settingUserId = GridDataMySqlFile.ParseFileReadValue("user_id");
|
||||||
|
string settingPassword = GridDataMySqlFile.ParseFileReadValue("password");
|
||||||
|
|
||||||
|
database =
|
||||||
|
new MSSQLManager(settingDataSource, settingInitialCatalog, settingPersistSecurityInfo, settingUserId,
|
||||||
|
settingPassword);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Shuts down the grid interface
|
||||||
|
/// </summary>
|
||||||
|
public void Close()
|
||||||
|
{
|
||||||
|
database.Close();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the storage system name
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>A string containing the storage system name</returns>
|
||||||
|
public string getName()
|
||||||
|
{
|
||||||
|
return "Sql OpenGridData";
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the storage system version
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>A string containing the storage system version</returns>
|
||||||
|
public string getVersion()
|
||||||
|
{
|
||||||
|
return "0.1";
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns a list of regions within the specified ranges
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="a">minimum X coordinate</param>
|
||||||
|
/// <param name="b">minimum Y coordinate</param>
|
||||||
|
/// <param name="c">maximum X coordinate</param>
|
||||||
|
/// <param name="d">maximum Y coordinate</param>
|
||||||
|
/// <returns>An array of region profiles</returns>
|
||||||
|
public RegionProfileData[] GetProfilesInRange(uint a, uint b, uint c, uint d)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns a sim profile from it's location
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="handle">Region location handle</param>
|
||||||
|
/// <returns>Sim profile</returns>
|
||||||
|
public RegionProfileData GetProfileByHandle(ulong handle)
|
||||||
|
{
|
||||||
|
IDataReader reader = null;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Dictionary<string, string> param = new Dictionary<string, string>();
|
||||||
|
param["handle"] = handle.ToString();
|
||||||
|
IDbCommand result = database.Query("SELECT * FROM regions WHERE regionHandle = @handle", param);
|
||||||
|
reader = result.ExecuteReader();
|
||||||
|
|
||||||
|
RegionProfileData row = database.getRegionRow(reader);
|
||||||
|
reader.Close();
|
||||||
|
result.Dispose();
|
||||||
|
|
||||||
|
return row;
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
if (reader != null)
|
||||||
|
{
|
||||||
|
reader.Close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// // Returns a list of avatar and UUIDs that match the query
|
||||||
|
/// </summary>
|
||||||
|
public List<AvatarPickerAvatar> GeneratePickerResults(LLUUID queryID, string query)
|
||||||
|
{
|
||||||
|
List<AvatarPickerAvatar> returnlist = new List<AvatarPickerAvatar>();
|
||||||
|
string[] querysplit;
|
||||||
|
querysplit = query.Split(' ');
|
||||||
|
if (querysplit.Length == 2)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
lock (database)
|
||||||
|
{
|
||||||
|
Dictionary<string, string> param = new Dictionary<string, string>();
|
||||||
|
param["first"] = querysplit[0];
|
||||||
|
param["second"] = querysplit[1];
|
||||||
|
|
||||||
|
IDbCommand result =
|
||||||
|
database.Query(
|
||||||
|
"SELECT UUID,username,surname FROM users WHERE username = @first AND lastname = @second",
|
||||||
|
param);
|
||||||
|
IDataReader reader = result.ExecuteReader();
|
||||||
|
|
||||||
|
|
||||||
|
while (reader.Read())
|
||||||
|
{
|
||||||
|
AvatarPickerAvatar user = new AvatarPickerAvatar();
|
||||||
|
user.AvatarID = new LLUUID((string) reader["UUID"]);
|
||||||
|
user.firstName = (string) reader["username"];
|
||||||
|
user.lastName = (string) reader["surname"];
|
||||||
|
returnlist.Add(user);
|
||||||
|
}
|
||||||
|
reader.Close();
|
||||||
|
result.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
database.Reconnect();
|
||||||
|
MainLog.Instance.Error(e.ToString());
|
||||||
|
return returnlist;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (querysplit.Length == 1)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
lock (database)
|
||||||
|
{
|
||||||
|
Dictionary<string, string> param = new Dictionary<string, string>();
|
||||||
|
param["first"] = querysplit[0];
|
||||||
|
param["second"] = querysplit[1];
|
||||||
|
|
||||||
|
IDbCommand result =
|
||||||
|
database.Query(
|
||||||
|
"SELECT UUID,username,surname FROM users WHERE username = @first OR lastname = @second",
|
||||||
|
param);
|
||||||
|
IDataReader reader = result.ExecuteReader();
|
||||||
|
|
||||||
|
|
||||||
|
while (reader.Read())
|
||||||
|
{
|
||||||
|
AvatarPickerAvatar user = new AvatarPickerAvatar();
|
||||||
|
user.AvatarID = new LLUUID((string) reader["UUID"]);
|
||||||
|
user.firstName = (string) reader["username"];
|
||||||
|
user.lastName = (string) reader["surname"];
|
||||||
|
returnlist.Add(user);
|
||||||
|
}
|
||||||
|
reader.Close();
|
||||||
|
result.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
database.Reconnect();
|
||||||
|
MainLog.Instance.Error(e.ToString());
|
||||||
|
return returnlist;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return returnlist;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns a sim profile from it's UUID
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="uuid">The region UUID</param>
|
||||||
|
/// <returns>The sim profile</returns>
|
||||||
|
public RegionProfileData GetProfileByLLUUID(LLUUID uuid)
|
||||||
|
{
|
||||||
|
Dictionary<string, string> param = new Dictionary<string, string>();
|
||||||
|
param["uuid"] = uuid.ToString();
|
||||||
|
IDbCommand result = database.Query("SELECT * FROM regions WHERE uuid = @uuid", param);
|
||||||
|
IDataReader reader = result.ExecuteReader();
|
||||||
|
|
||||||
|
RegionProfileData row = database.getRegionRow(reader);
|
||||||
|
reader.Close();
|
||||||
|
result.Dispose();
|
||||||
|
|
||||||
|
return row;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Adds a new specified region to the database
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="profile">The profile to add</param>
|
||||||
|
/// <returns>A dataresponse enum indicating success</returns>
|
||||||
|
public DataResponse AddProfile(RegionProfileData profile)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (GetProfileByLLUUID(profile.UUID) != null)
|
||||||
|
{
|
||||||
|
return DataResponse.RESPONSE_OK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
System.Console.WriteLine("No regions found. Create new one.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (database.insertRegionRow(profile))
|
||||||
|
{
|
||||||
|
return DataResponse.RESPONSE_OK;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return DataResponse.RESPONSE_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// DEPRECIATED. Attempts to authenticate a region by comparing a shared secret.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="uuid">The UUID of the challenger</param>
|
||||||
|
/// <param name="handle">The attempted regionHandle of the challenger</param>
|
||||||
|
/// <param name="authkey">The secret</param>
|
||||||
|
/// <returns>Whether the secret and regionhandle match the database entry for UUID</returns>
|
||||||
|
public bool AuthenticateSim(LLUUID uuid, ulong handle, string authkey)
|
||||||
|
{
|
||||||
|
bool throwHissyFit = false; // Should be true by 1.0
|
||||||
|
|
||||||
|
if (throwHissyFit)
|
||||||
|
throw new Exception("CRYPTOWEAK AUTHENTICATE: Refusing to authenticate due to replay potential.");
|
||||||
|
|
||||||
|
RegionProfileData data = GetProfileByLLUUID(uuid);
|
||||||
|
|
||||||
|
return (handle == data.regionHandle && authkey == data.regionSecret);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// NOT YET FUNCTIONAL. Provides a cryptographic authentication of a region
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>This requires a security audit.</remarks>
|
||||||
|
/// <param name="uuid"></param>
|
||||||
|
/// <param name="handle"></param>
|
||||||
|
/// <param name="authhash"></param>
|
||||||
|
/// <param name="challenge"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public bool AuthenticateSim(LLUUID uuid, ulong handle, string authhash, string challenge)
|
||||||
|
{
|
||||||
|
SHA512Managed HashProvider = new SHA512Managed();
|
||||||
|
ASCIIEncoding TextProvider = new ASCIIEncoding();
|
||||||
|
|
||||||
|
byte[] stream = TextProvider.GetBytes(uuid.ToString() + ":" + handle.ToString() + ":" + challenge);
|
||||||
|
byte[] hash = HashProvider.ComputeHash(stream);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ReservationData GetReservationAtPoint(uint x, uint y)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,726 @@
|
||||||
|
/*
|
||||||
|
* 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 OpenSim 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.Data;
|
||||||
|
using System.Data.SqlClient;
|
||||||
|
using libsecondlife;
|
||||||
|
using OpenSim.Framework.Console;
|
||||||
|
|
||||||
|
namespace OpenSim.Framework.Data.MSSQL
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// A MySQL interface for the inventory server
|
||||||
|
/// </summary>
|
||||||
|
public class MSSQLInventoryData : IInventoryData
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The database manager
|
||||||
|
/// </summary>
|
||||||
|
private MSSQLManager database;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Loads and initialises this database plugin
|
||||||
|
/// </summary>
|
||||||
|
public void Initialise()
|
||||||
|
{
|
||||||
|
IniFile GridDataMySqlFile = new IniFile("mssql_connection.ini");
|
||||||
|
string settingDataSource = GridDataMySqlFile.ParseFileReadValue("data_source");
|
||||||
|
string settingInitialCatalog = GridDataMySqlFile.ParseFileReadValue("initial_catalog");
|
||||||
|
string settingPersistSecurityInfo = GridDataMySqlFile.ParseFileReadValue("persist_security_info");
|
||||||
|
string settingUserId = GridDataMySqlFile.ParseFileReadValue("user_id");
|
||||||
|
string settingPassword = GridDataMySqlFile.ParseFileReadValue("password");
|
||||||
|
|
||||||
|
database =
|
||||||
|
new MSSQLManager(settingDataSource, settingInitialCatalog, settingPersistSecurityInfo, settingUserId,
|
||||||
|
settingPassword);
|
||||||
|
TestTables();
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Test and initialization code
|
||||||
|
|
||||||
|
private void UpgradeFoldersTable(string tableName)
|
||||||
|
{
|
||||||
|
// null as the version, indicates that the table didn't exist
|
||||||
|
if (tableName == null)
|
||||||
|
{
|
||||||
|
database.ExecuteResourceSql("CreateFoldersTable.sql");
|
||||||
|
//database.ExecuteResourceSql("UpgradeFoldersTableToVersion2.sql");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UpgradeItemsTable(string tableName)
|
||||||
|
{
|
||||||
|
// null as the version, indicates that the table didn't exist
|
||||||
|
if (tableName == null)
|
||||||
|
{
|
||||||
|
database.ExecuteResourceSql("CreateItemsTable.sql");
|
||||||
|
//database.ExecuteResourceSql("UpgradeItemsTableToVersion2.sql");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void TestTables()
|
||||||
|
{
|
||||||
|
Dictionary<string, string> tableList = new Dictionary<string, string>();
|
||||||
|
|
||||||
|
tableList["inventoryfolders"] = null;
|
||||||
|
tableList["inventoryitems"] = null;
|
||||||
|
|
||||||
|
database.GetTableVersion(tableList);
|
||||||
|
|
||||||
|
UpgradeFoldersTable(tableList["inventoryfolders"]);
|
||||||
|
UpgradeItemsTable(tableList["inventoryitems"]);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The name of this DB provider
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>Name of DB provider</returns>
|
||||||
|
public string getName()
|
||||||
|
{
|
||||||
|
return "MSSQL Inventory Data Interface";
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Closes this DB provider
|
||||||
|
/// </summary>
|
||||||
|
public void Close()
|
||||||
|
{
|
||||||
|
// Do nothing.
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the version of this DB provider
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>A string containing the DB provider</returns>
|
||||||
|
public string getVersion()
|
||||||
|
{
|
||||||
|
return database.getVersion();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns a list of items in a specified folder
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="folderID">The folder to search</param>
|
||||||
|
/// <returns>A list containing inventory items</returns>
|
||||||
|
public List<InventoryItemBase> getInventoryInFolder(LLUUID folderID)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
lock (database)
|
||||||
|
{
|
||||||
|
List<InventoryItemBase> items = new List<InventoryItemBase>();
|
||||||
|
|
||||||
|
Dictionary<string, string> param = new Dictionary<string, string>();
|
||||||
|
param["parentFolderID"] = folderID.ToString();
|
||||||
|
|
||||||
|
IDbCommand result =
|
||||||
|
database.Query("SELECT * FROM inventoryitems WHERE parentFolderID = @parentFolderID", param);
|
||||||
|
IDataReader reader = result.ExecuteReader();
|
||||||
|
|
||||||
|
while (reader.Read())
|
||||||
|
items.Add(readInventoryItem(reader));
|
||||||
|
|
||||||
|
reader.Close();
|
||||||
|
result.Dispose();
|
||||||
|
|
||||||
|
return items;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
database.Reconnect();
|
||||||
|
MainLog.Instance.Error(e.ToString());
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns a list of the root folders within a users inventory
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="user">The user whos inventory is to be searched</param>
|
||||||
|
/// <returns>A list of folder objects</returns>
|
||||||
|
public List<InventoryFolderBase> getUserRootFolders(LLUUID user)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
lock (database)
|
||||||
|
{
|
||||||
|
Dictionary<string, string> param = new Dictionary<string, string>();
|
||||||
|
param["uuid"] = user.ToString();
|
||||||
|
param["zero"] = LLUUID.Zero.ToString();
|
||||||
|
|
||||||
|
IDbCommand result =
|
||||||
|
database.Query(
|
||||||
|
"SELECT * FROM inventoryfolders WHERE parentFolderID = @zero AND agentID = @uuid", param);
|
||||||
|
IDataReader reader = result.ExecuteReader();
|
||||||
|
|
||||||
|
List<InventoryFolderBase> items = new List<InventoryFolderBase>();
|
||||||
|
while (reader.Read())
|
||||||
|
items.Add(readInventoryFolder(reader));
|
||||||
|
|
||||||
|
|
||||||
|
reader.Close();
|
||||||
|
result.Dispose();
|
||||||
|
|
||||||
|
return items;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
database.Reconnect();
|
||||||
|
MainLog.Instance.Error(e.ToString());
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// see InventoryItemBase.getUserRootFolder
|
||||||
|
public InventoryFolderBase getUserRootFolder(LLUUID user)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
lock (database)
|
||||||
|
{
|
||||||
|
Dictionary<string, string> param = new Dictionary<string, string>();
|
||||||
|
param["uuid"] = user.ToString();
|
||||||
|
param["zero"] = LLUUID.Zero.ToString();
|
||||||
|
|
||||||
|
IDbCommand result =
|
||||||
|
database.Query(
|
||||||
|
"SELECT * FROM inventoryfolders WHERE parentFolderID = @zero AND agentID = @uuid", param);
|
||||||
|
IDataReader reader = result.ExecuteReader();
|
||||||
|
|
||||||
|
List<InventoryFolderBase> items = new List<InventoryFolderBase>();
|
||||||
|
while (reader.Read())
|
||||||
|
items.Add(readInventoryFolder(reader));
|
||||||
|
|
||||||
|
InventoryFolderBase rootFolder = null;
|
||||||
|
|
||||||
|
// There should only ever be one root folder for a user. However, if there's more
|
||||||
|
// than one we'll simply use the first one rather than failing. It would be even
|
||||||
|
// nicer to print some message to this effect, but this feels like it's too low a
|
||||||
|
// to put such a message out, and it's too minor right now to spare the time to
|
||||||
|
// suitably refactor.
|
||||||
|
if (items.Count > 0)
|
||||||
|
{
|
||||||
|
rootFolder = items[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
reader.Close();
|
||||||
|
result.Dispose();
|
||||||
|
|
||||||
|
return rootFolder;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
database.Reconnect();
|
||||||
|
MainLog.Instance.Error(e.ToString());
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns a list of folders in a users inventory contained within the specified folder
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="parentID">The folder to search</param>
|
||||||
|
/// <returns>A list of inventory folders</returns>
|
||||||
|
public List<InventoryFolderBase> getInventoryFolders(LLUUID parentID)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
lock (database)
|
||||||
|
{
|
||||||
|
Dictionary<string, string> param = new Dictionary<string, string>();
|
||||||
|
param["parentFolderID"] = parentID.ToString();
|
||||||
|
|
||||||
|
|
||||||
|
IDbCommand result =
|
||||||
|
database.Query("SELECT * FROM inventoryfolders WHERE parentFolderID = @parentFolderID", param);
|
||||||
|
IDataReader reader = result.ExecuteReader();
|
||||||
|
|
||||||
|
List<InventoryFolderBase> items = new List<InventoryFolderBase>();
|
||||||
|
|
||||||
|
while (reader.Read())
|
||||||
|
items.Add(readInventoryFolder(reader));
|
||||||
|
|
||||||
|
reader.Close();
|
||||||
|
result.Dispose();
|
||||||
|
|
||||||
|
return items;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
database.Reconnect();
|
||||||
|
MainLog.Instance.Error(e.ToString());
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Reads a one item from an SQL result
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="reader">The SQL Result</param>
|
||||||
|
/// <returns>the item read</returns>
|
||||||
|
private InventoryItemBase readInventoryItem(IDataReader reader)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
InventoryItemBase item = new InventoryItemBase();
|
||||||
|
|
||||||
|
item.inventoryID = new LLUUID((string) reader["inventoryID"]);
|
||||||
|
item.assetID = new LLUUID((string) reader["assetID"]);
|
||||||
|
item.assetType = (int) reader["assetType"];
|
||||||
|
item.parentFolderID = new LLUUID((string) reader["parentFolderID"]);
|
||||||
|
item.avatarID = new LLUUID((string) reader["avatarID"]);
|
||||||
|
item.inventoryName = (string) reader["inventoryName"];
|
||||||
|
item.inventoryDescription = (string) reader["inventoryDescription"];
|
||||||
|
item.inventoryNextPermissions = Convert.ToUInt32(reader["inventoryNextPermissions"]);
|
||||||
|
item.inventoryCurrentPermissions = Convert.ToUInt32(reader["inventoryCurrentPermissions"]);
|
||||||
|
item.invType = (int) reader["invType"];
|
||||||
|
item.creatorsID = new LLUUID((string) reader["creatorID"]);
|
||||||
|
item.inventoryBasePermissions = Convert.ToUInt32(reader["inventoryBasePermissions"]);
|
||||||
|
item.inventoryEveryOnePermissions = Convert.ToUInt32(reader["inventoryEveryOnePermissions"]);
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
catch (SqlException e)
|
||||||
|
{
|
||||||
|
MainLog.Instance.Error(e.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns a specified inventory item
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="item">The item to return</param>
|
||||||
|
/// <returns>An inventory item</returns>
|
||||||
|
public InventoryItemBase getInventoryItem(LLUUID itemID)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
lock (database)
|
||||||
|
{
|
||||||
|
Dictionary<string, string> param = new Dictionary<string, string>();
|
||||||
|
param["inventoryID"] = itemID.ToString();
|
||||||
|
|
||||||
|
IDbCommand result =
|
||||||
|
database.Query("SELECT * FROM inventoryitems WHERE inventoryID = @inventoryID", param);
|
||||||
|
IDataReader reader = result.ExecuteReader();
|
||||||
|
|
||||||
|
InventoryItemBase item = null;
|
||||||
|
if (reader.Read())
|
||||||
|
item = readInventoryItem(reader);
|
||||||
|
|
||||||
|
reader.Close();
|
||||||
|
result.Dispose();
|
||||||
|
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
database.Reconnect();
|
||||||
|
MainLog.Instance.Error(e.ToString());
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Reads a list of inventory folders returned by a query.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="reader">A MySQL Data Reader</param>
|
||||||
|
/// <returns>A List containing inventory folders</returns>
|
||||||
|
protected InventoryFolderBase readInventoryFolder(IDataReader reader)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
InventoryFolderBase folder = new InventoryFolderBase();
|
||||||
|
folder.agentID = new LLUUID((string) reader["agentID"]);
|
||||||
|
folder.parentID = new LLUUID((string) reader["parentFolderID"]);
|
||||||
|
folder.folderID = new LLUUID((string) reader["folderID"]);
|
||||||
|
folder.name = (string) reader["folderName"];
|
||||||
|
folder.type = (short) reader["type"];
|
||||||
|
folder.version = (ushort) ((int) reader["version"]);
|
||||||
|
return folder;
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
MainLog.Instance.Error(e.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns a specified inventory folder
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="folder">The folder to return</param>
|
||||||
|
/// <returns>A folder class</returns>
|
||||||
|
public InventoryFolderBase getInventoryFolder(LLUUID folderID)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
lock (database)
|
||||||
|
{
|
||||||
|
Dictionary<string, string> param = new Dictionary<string, string>();
|
||||||
|
param["uuid"] = folderID.ToString();
|
||||||
|
|
||||||
|
IDbCommand result = database.Query("SELECT * FROM inventoryfolders WHERE folderID = @uuid", param);
|
||||||
|
IDataReader reader = result.ExecuteReader();
|
||||||
|
|
||||||
|
reader.Read();
|
||||||
|
InventoryFolderBase folder = readInventoryFolder(reader);
|
||||||
|
reader.Close();
|
||||||
|
result.Dispose();
|
||||||
|
|
||||||
|
return folder;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
database.Reconnect();
|
||||||
|
MainLog.Instance.Error(e.ToString());
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Adds a specified item to the database
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="item">The inventory item</param>
|
||||||
|
public void addInventoryItem(InventoryItemBase item)
|
||||||
|
{
|
||||||
|
string sql = "INSERT INTO inventoryitems";
|
||||||
|
sql +=
|
||||||
|
"([inventoryID], [assetID], [assetType], [parentFolderID], [avatarID], [inventoryName], [inventoryDescription], [inventoryNextPermissions], [inventoryCurrentPermissions], [invType], [creatorID], [inventoryBasePermissions], [inventoryEveryOnePermissions]) VALUES ";
|
||||||
|
sql +=
|
||||||
|
"(@inventoryID, @assetID, @assetType, @parentFolderID, @avatarID, @inventoryName, @inventoryDescription, @inventoryNextPermissions, @inventoryCurrentPermissions, @invType, @creatorID, @inventoryBasePermissions, @inventoryEveryOnePermissions);";
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Dictionary<string, string> param = new Dictionary<string, string>();
|
||||||
|
param["inventoryID"] = item.inventoryID.ToString();
|
||||||
|
param["assetID"] = item.assetID.ToString();
|
||||||
|
param["assetType"] = item.assetType.ToString();
|
||||||
|
param["parentFolderID"] = item.parentFolderID.ToString();
|
||||||
|
param["avatarID"] = item.avatarID.ToString();
|
||||||
|
param["inventoryName"] = item.inventoryName;
|
||||||
|
param["inventoryDescription"] = item.inventoryDescription;
|
||||||
|
param["inventoryNextPermissions"] = item.inventoryNextPermissions.ToString();
|
||||||
|
param["inventoryCurrentPermissions"] = item.inventoryCurrentPermissions.ToString();
|
||||||
|
param["invType"] = Convert.ToString(item.invType);
|
||||||
|
param["creatorID"] = item.creatorsID.ToString();
|
||||||
|
param["inventoryBasePermissions"] = Convert.ToString(item.inventoryBasePermissions);
|
||||||
|
param["inventoryEveryOnePermissions"] = Convert.ToString(item.inventoryEveryOnePermissions);
|
||||||
|
|
||||||
|
IDbCommand result = database.Query(sql, param);
|
||||||
|
result.ExecuteNonQuery();
|
||||||
|
result.Dispose();
|
||||||
|
}
|
||||||
|
catch (SqlException e)
|
||||||
|
{
|
||||||
|
MainLog.Instance.Error(e.ToString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Updates the specified inventory item
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="item">Inventory item to update</param>
|
||||||
|
public void updateInventoryItem(InventoryItemBase item)
|
||||||
|
{
|
||||||
|
SqlCommand command = new SqlCommand("UPDATE inventoryitems set inventoryID = @inventoryID, " +
|
||||||
|
"assetID = @assetID, " +
|
||||||
|
"assetType = @assetType" +
|
||||||
|
"parentFolderID = @parentFolderID" +
|
||||||
|
"avatarID = @avatarID" +
|
||||||
|
"inventoryName = @inventoryName" +
|
||||||
|
"inventoryDescription = @inventoryDescription" +
|
||||||
|
"inventoryNextPermissions = @inventoryNextPermissions" +
|
||||||
|
"inventoryCurrentPermissions = @inventoryCurrentPermissions" +
|
||||||
|
"invType = @invType" +
|
||||||
|
"creatorID = @creatorID" +
|
||||||
|
"inventoryBasePermissions = @inventoryBasePermissions" +
|
||||||
|
"inventoryEveryOnePermissions = @inventoryEveryOnePermissions) where " +
|
||||||
|
"inventoryID = @keyInventoryID;", database.getConnection());
|
||||||
|
SqlParameter param1 = new SqlParameter("@inventoryID", item.inventoryID.ToString());
|
||||||
|
SqlParameter param2 = new SqlParameter("@assetID", item.assetID);
|
||||||
|
SqlParameter param3 = new SqlParameter("@assetType", item.assetType);
|
||||||
|
SqlParameter param4 = new SqlParameter("@parentFolderID", item.parentFolderID);
|
||||||
|
SqlParameter param5 = new SqlParameter("@avatarID", item.avatarID);
|
||||||
|
SqlParameter param6 = new SqlParameter("@inventoryName", item.inventoryName);
|
||||||
|
SqlParameter param7 = new SqlParameter("@inventoryDescription", item.inventoryDescription);
|
||||||
|
SqlParameter param8 = new SqlParameter("@inventoryNextPermissions", item.inventoryNextPermissions);
|
||||||
|
SqlParameter param9 = new SqlParameter("@inventoryCurrentPermissions", item.inventoryCurrentPermissions);
|
||||||
|
SqlParameter param10 = new SqlParameter("@invType", item.invType);
|
||||||
|
SqlParameter param11 = new SqlParameter("@creatorID", item.creatorsID);
|
||||||
|
SqlParameter param12 = new SqlParameter("@inventoryBasePermissions", item.inventoryBasePermissions);
|
||||||
|
SqlParameter param13 = new SqlParameter("@inventoryEveryOnePermissions", item.inventoryEveryOnePermissions);
|
||||||
|
SqlParameter param14 = new SqlParameter("@keyInventoryID", item.inventoryID.ToString());
|
||||||
|
command.Parameters.Add(param1);
|
||||||
|
command.Parameters.Add(param2);
|
||||||
|
command.Parameters.Add(param3);
|
||||||
|
command.Parameters.Add(param4);
|
||||||
|
command.Parameters.Add(param5);
|
||||||
|
command.Parameters.Add(param6);
|
||||||
|
command.Parameters.Add(param7);
|
||||||
|
command.Parameters.Add(param8);
|
||||||
|
command.Parameters.Add(param9);
|
||||||
|
command.Parameters.Add(param10);
|
||||||
|
command.Parameters.Add(param11);
|
||||||
|
command.Parameters.Add(param12);
|
||||||
|
command.Parameters.Add(param13);
|
||||||
|
command.Parameters.Add(param14);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
command.ExecuteNonQuery();
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
MainLog.Instance.Error(e.ToString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="item"></param>
|
||||||
|
public void deleteInventoryItem(LLUUID itemID)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Dictionary<string, string> param = new Dictionary<string, string>();
|
||||||
|
param["uuid"] = itemID.ToString();
|
||||||
|
|
||||||
|
IDbCommand cmd = database.Query("DELETE FROM inventoryitems WHERE inventoryID=@uuid", param);
|
||||||
|
cmd.ExecuteNonQuery();
|
||||||
|
cmd.Dispose();
|
||||||
|
}
|
||||||
|
catch (SqlException e)
|
||||||
|
{
|
||||||
|
database.Reconnect();
|
||||||
|
MainLog.Instance.Error(e.ToString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a new inventory folder
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="folder">Folder to create</param>
|
||||||
|
public void addInventoryFolder(InventoryFolderBase folder)
|
||||||
|
{
|
||||||
|
string sql =
|
||||||
|
"INSERT INTO inventoryfolders ([folderID], [agentID], [parentFolderID], [folderName], [type], [version]) VALUES ";
|
||||||
|
sql += "(@folderID, @agentID, @parentFolderID, @folderName, @type, @version);";
|
||||||
|
|
||||||
|
|
||||||
|
Dictionary<string, string> param = new Dictionary<string, string>();
|
||||||
|
param["folderID"] = folder.folderID.ToString();
|
||||||
|
param["agentID"] = folder.agentID.ToString();
|
||||||
|
param["parentFolderID"] = folder.parentID.ToString();
|
||||||
|
param["folderName"] = folder.name;
|
||||||
|
param["type"] = Convert.ToString(folder.type);
|
||||||
|
param["version"] = Convert.ToString(folder.version);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
IDbCommand result = database.Query(sql, param);
|
||||||
|
result.ExecuteNonQuery();
|
||||||
|
result.Dispose();
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
MainLog.Instance.Error(e.ToString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Updates an inventory folder
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="folder">Folder to update</param>
|
||||||
|
public void updateInventoryFolder(InventoryFolderBase folder)
|
||||||
|
{
|
||||||
|
SqlCommand command = new SqlCommand("UPDATE inventoryfolders set folderID = @folderID, " +
|
||||||
|
"agentID = @agentID, " +
|
||||||
|
"parentFolderID = @parentFolderID," +
|
||||||
|
"folderName = @folderName," +
|
||||||
|
"type = @type," +
|
||||||
|
"version = @version where " +
|
||||||
|
"folderID = @keyFolderID;", database.getConnection());
|
||||||
|
SqlParameter param1 = new SqlParameter("@folderID", folder.folderID.ToString());
|
||||||
|
SqlParameter param2 = new SqlParameter("@agentID", folder.agentID.ToString());
|
||||||
|
SqlParameter param3 = new SqlParameter("@parentFolderID", folder.parentID.ToString());
|
||||||
|
SqlParameter param4 = new SqlParameter("@folderName", folder.name);
|
||||||
|
SqlParameter param5 = new SqlParameter("@type", folder.type);
|
||||||
|
SqlParameter param6 = new SqlParameter("@version", folder.version);
|
||||||
|
SqlParameter param7 = new SqlParameter("@keyFolderID", folder.folderID.ToString());
|
||||||
|
command.Parameters.Add(param1);
|
||||||
|
command.Parameters.Add(param2);
|
||||||
|
command.Parameters.Add(param3);
|
||||||
|
command.Parameters.Add(param4);
|
||||||
|
command.Parameters.Add(param5);
|
||||||
|
command.Parameters.Add(param6);
|
||||||
|
command.Parameters.Add(param7);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
command.ExecuteNonQuery();
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
MainLog.Instance.Error(e.ToString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Updates an inventory folder
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="folder">Folder to update</param>
|
||||||
|
public void moveInventoryFolder(InventoryFolderBase folder)
|
||||||
|
{
|
||||||
|
SqlCommand command = new SqlCommand("UPDATE inventoryfolders set folderID = @folderID, " +
|
||||||
|
"parentFolderID = @parentFolderID," +
|
||||||
|
"folderID = @keyFolderID;", database.getConnection());
|
||||||
|
SqlParameter param1 = new SqlParameter("@folderID", folder.folderID.ToString());
|
||||||
|
SqlParameter param2 = new SqlParameter("@parentFolderID", folder.parentID.ToString());
|
||||||
|
SqlParameter param3 = new SqlParameter("@keyFolderID", folder.folderID.ToString());
|
||||||
|
command.Parameters.Add(param1);
|
||||||
|
command.Parameters.Add(param2);
|
||||||
|
command.Parameters.Add(param3);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
command.ExecuteNonQuery();
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
MainLog.Instance.Error(e.ToString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Append a list of all the child folders of a parent folder
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="folders">list where folders will be appended</param>
|
||||||
|
/// <param name="parentID">ID of parent</param>
|
||||||
|
protected void getInventoryFolders(ref List<InventoryFolderBase> folders, LLUUID parentID)
|
||||||
|
{
|
||||||
|
List<InventoryFolderBase> subfolderList = getInventoryFolders(parentID);
|
||||||
|
|
||||||
|
foreach (InventoryFolderBase f in subfolderList)
|
||||||
|
folders.Add(f);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns all child folders in the hierarchy from the parent folder and down
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="parentID">The folder to get subfolders for</param>
|
||||||
|
/// <returns>A list of inventory folders</returns>
|
||||||
|
protected List<InventoryFolderBase> getFolderHierarchy(LLUUID parentID)
|
||||||
|
{
|
||||||
|
List<InventoryFolderBase> folders = new List<InventoryFolderBase>();
|
||||||
|
getInventoryFolders(ref folders, parentID);
|
||||||
|
|
||||||
|
for (int i = 0; i < folders.Count; i++)
|
||||||
|
getInventoryFolders(ref folders, folders[i].folderID);
|
||||||
|
|
||||||
|
return folders;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void deleteOneFolder(LLUUID folderID)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Dictionary<string, string> param = new Dictionary<string, string>();
|
||||||
|
param["folderID"] = folderID.ToString();
|
||||||
|
|
||||||
|
IDbCommand cmd = database.Query("DELETE FROM inventoryfolders WHERE folderID=@folderID", param);
|
||||||
|
cmd.ExecuteNonQuery();
|
||||||
|
cmd.Dispose();
|
||||||
|
}
|
||||||
|
catch (SqlException e)
|
||||||
|
{
|
||||||
|
database.Reconnect();
|
||||||
|
MainLog.Instance.Error(e.ToString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void deleteItemsInFolder(LLUUID folderID)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Dictionary<string, string> param = new Dictionary<string, string>();
|
||||||
|
param["parentFolderID"] = folderID.ToString();
|
||||||
|
|
||||||
|
|
||||||
|
IDbCommand cmd =
|
||||||
|
database.Query("DELETE FROM inventoryitems WHERE parentFolderID=@parentFolderID", param);
|
||||||
|
cmd.ExecuteNonQuery();
|
||||||
|
cmd.Dispose();
|
||||||
|
}
|
||||||
|
catch (SqlException e)
|
||||||
|
{
|
||||||
|
database.Reconnect();
|
||||||
|
MainLog.Instance.Error(e.ToString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Delete an inventory folder
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="folderId">Id of folder to delete</param>
|
||||||
|
public void deleteInventoryFolder(LLUUID folderID)
|
||||||
|
{
|
||||||
|
lock (database)
|
||||||
|
{
|
||||||
|
List<InventoryFolderBase> subFolders = getFolderHierarchy(folderID);
|
||||||
|
|
||||||
|
//Delete all sub-folders
|
||||||
|
foreach (InventoryFolderBase f in subFolders)
|
||||||
|
{
|
||||||
|
deleteOneFolder(f.folderID);
|
||||||
|
deleteItemsInFolder(f.folderID);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Delete the actual row
|
||||||
|
deleteOneFolder(folderID);
|
||||||
|
deleteItemsInFolder(folderID);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,105 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) Contributors, http://opensimulator.org/
|
||||||
|
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of the OpenSim 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.Data.MSSQL
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// An interface to the log database for MySQL
|
||||||
|
/// </summary>
|
||||||
|
internal class MSSQLLogData : ILogData
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The database manager
|
||||||
|
/// </summary>
|
||||||
|
public MSSQLManager database;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Artificial constructor called when the plugin is loaded
|
||||||
|
/// </summary>
|
||||||
|
public void Initialise()
|
||||||
|
{
|
||||||
|
IniFile GridDataMySqlFile = new IniFile("mssql_connection.ini");
|
||||||
|
string settingDataSource = GridDataMySqlFile.ParseFileReadValue("data_source");
|
||||||
|
string settingInitialCatalog = GridDataMySqlFile.ParseFileReadValue("initial_catalog");
|
||||||
|
string settingPersistSecurityInfo = GridDataMySqlFile.ParseFileReadValue("persist_security_info");
|
||||||
|
string settingUserId = GridDataMySqlFile.ParseFileReadValue("user_id");
|
||||||
|
string settingPassword = GridDataMySqlFile.ParseFileReadValue("password");
|
||||||
|
|
||||||
|
database =
|
||||||
|
new MSSQLManager(settingDataSource, settingInitialCatalog, settingPersistSecurityInfo, settingUserId,
|
||||||
|
settingPassword);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Saves a log item to the database
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="serverDaemon">The daemon triggering the event</param>
|
||||||
|
/// <param name="target">The target of the action (region / agent UUID, etc)</param>
|
||||||
|
/// <param name="methodCall">The method call where the problem occured</param>
|
||||||
|
/// <param name="arguments">The arguments passed to the method</param>
|
||||||
|
/// <param name="priority">How critical is this?</param>
|
||||||
|
/// <param name="logMessage">The message to log</param>
|
||||||
|
public void saveLog(string serverDaemon, string target, string methodCall, string arguments, int priority,
|
||||||
|
string logMessage)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
database.insertLogRow(serverDaemon, target, methodCall, arguments, priority, logMessage);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
database.Reconnect();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the name of this DB provider
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>A string containing the DB provider name</returns>
|
||||||
|
public string getName()
|
||||||
|
{
|
||||||
|
return "MSSQL Logdata Interface";
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Closes the database provider
|
||||||
|
/// </summary>
|
||||||
|
public void Close()
|
||||||
|
{
|
||||||
|
// Do nothing.
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the version of this DB provider
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>A string containing the provider version</returns>
|
||||||
|
public string getVersion()
|
||||||
|
{
|
||||||
|
return "0.1";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,769 @@
|
||||||
|
/*
|
||||||
|
* 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 OpenSim 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.Data;
|
||||||
|
using System.Data.SqlClient;
|
||||||
|
using System.IO;
|
||||||
|
using System.Reflection;
|
||||||
|
using libsecondlife;
|
||||||
|
using OpenSim.Framework.Console;
|
||||||
|
|
||||||
|
namespace OpenSim.Framework.Data.MSSQL
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// A management class for the MS SQL Storage Engine
|
||||||
|
/// </summary>
|
||||||
|
internal class MSSQLManager
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The database connection object
|
||||||
|
/// </summary>
|
||||||
|
private IDbConnection dbcon;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Connection string for ADO.net
|
||||||
|
/// </summary>
|
||||||
|
private string connectionString;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initialises and creates a new Sql connection and maintains it.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="hostname">The Sql server being connected to</param>
|
||||||
|
/// <param name="database">The name of the Sql database being used</param>
|
||||||
|
/// <param name="username">The username logging into the database</param>
|
||||||
|
/// <param name="password">The password for the user logging in</param>
|
||||||
|
/// <param name="cpooling">Whether to use connection pooling or not, can be one of the following: 'yes', 'true', 'no' or 'false', if unsure use 'false'.</param>
|
||||||
|
public MSSQLManager(string dataSource, string initialCatalog, string persistSecurityInfo, string userId,
|
||||||
|
string password)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
connectionString = "Data Source=" + dataSource + ";Initial Catalog=" + initialCatalog +
|
||||||
|
";Persist Security Info=" + persistSecurityInfo + ";User ID=" + userId + ";Password=" +
|
||||||
|
password + ";";
|
||||||
|
dbcon = new SqlConnection(connectionString);
|
||||||
|
TestTables(dbcon);
|
||||||
|
//System.Threading.Thread.Sleep(3000);
|
||||||
|
dbcon.Open();
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
throw new Exception("Error initialising Sql Database: " + e.ToString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool TestTables(IDbConnection conn)
|
||||||
|
{
|
||||||
|
IDbCommand cmd = Query("SELECT * FROM regions", new Dictionary<string, string>());
|
||||||
|
//SqlCommand cmd = (SqlCommand)dbcon.CreateCommand();
|
||||||
|
//cmd.CommandText = "SELECT * FROM regions";
|
||||||
|
try
|
||||||
|
{
|
||||||
|
conn.Open();
|
||||||
|
cmd.ExecuteNonQuery();
|
||||||
|
cmd.Dispose();
|
||||||
|
conn.Close();
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
MainLog.Instance.Verbose("DATASTORE", "MSSQL Database doesn't exist... creating");
|
||||||
|
InitDB(conn);
|
||||||
|
}
|
||||||
|
cmd = Query("select top 1 webLoginKey from users", new Dictionary<string, string>());
|
||||||
|
try
|
||||||
|
{
|
||||||
|
conn.Open();
|
||||||
|
cmd.ExecuteNonQuery();
|
||||||
|
cmd.Dispose();
|
||||||
|
conn.Close();
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
conn.Close();
|
||||||
|
conn.Open();
|
||||||
|
cmd = Query("alter table users add [webLoginKey] varchar(36) default NULL", new Dictionary<string, string>());
|
||||||
|
cmd.ExecuteNonQuery();
|
||||||
|
cmd.Dispose();
|
||||||
|
conn.Close();
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void InitDB(IDbConnection conn)
|
||||||
|
{
|
||||||
|
string createRegions = defineTable(createRegionsTable());
|
||||||
|
Dictionary<string, string> param = new Dictionary<string, string>();
|
||||||
|
IDbCommand pcmd = Query(createRegions, param);
|
||||||
|
if (conn.State == ConnectionState.Closed)
|
||||||
|
{
|
||||||
|
conn.Open();
|
||||||
|
}
|
||||||
|
pcmd.ExecuteNonQuery();
|
||||||
|
pcmd.Dispose();
|
||||||
|
|
||||||
|
ExecuteResourceSql("Mssql-users.sql");
|
||||||
|
ExecuteResourceSql("Mssql-agents.sql");
|
||||||
|
ExecuteResourceSql("Mssql-logs.sql");
|
||||||
|
|
||||||
|
conn.Close();
|
||||||
|
}
|
||||||
|
|
||||||
|
private DataTable createRegionsTable()
|
||||||
|
{
|
||||||
|
DataTable regions = new DataTable("regions");
|
||||||
|
|
||||||
|
createCol(regions, "regionHandle", typeof (ulong));
|
||||||
|
createCol(regions, "regionName", typeof (String));
|
||||||
|
createCol(regions, "uuid", typeof (String));
|
||||||
|
|
||||||
|
createCol(regions, "regionRecvKey", typeof (String));
|
||||||
|
createCol(regions, "regionSecret", typeof (String));
|
||||||
|
createCol(regions, "regionSendKey", typeof (String));
|
||||||
|
|
||||||
|
createCol(regions, "regionDataURI", typeof (String));
|
||||||
|
createCol(regions, "serverIP", typeof (String));
|
||||||
|
createCol(regions, "serverPort", typeof (String));
|
||||||
|
createCol(regions, "serverURI", typeof (String));
|
||||||
|
|
||||||
|
|
||||||
|
createCol(regions, "locX", typeof (uint));
|
||||||
|
createCol(regions, "locY", typeof (uint));
|
||||||
|
createCol(regions, "locZ", typeof (uint));
|
||||||
|
|
||||||
|
createCol(regions, "eastOverrideHandle", typeof (ulong));
|
||||||
|
createCol(regions, "westOverrideHandle", typeof (ulong));
|
||||||
|
createCol(regions, "southOverrideHandle", typeof (ulong));
|
||||||
|
createCol(regions, "northOverrideHandle", typeof (ulong));
|
||||||
|
|
||||||
|
createCol(regions, "regionAssetURI", typeof (String));
|
||||||
|
createCol(regions, "regionAssetRecvKey", typeof (String));
|
||||||
|
createCol(regions, "regionAssetSendKey", typeof (String));
|
||||||
|
|
||||||
|
createCol(regions, "regionUserURI", typeof (String));
|
||||||
|
createCol(regions, "regionUserRecvKey", typeof (String));
|
||||||
|
createCol(regions, "regionUserSendKey", typeof (String));
|
||||||
|
|
||||||
|
createCol(regions, "regionMapTexture", typeof (String));
|
||||||
|
createCol(regions, "serverHttpPort", typeof (String));
|
||||||
|
createCol(regions, "serverRemotingPort", typeof (uint));
|
||||||
|
|
||||||
|
// Add in contraints
|
||||||
|
regions.PrimaryKey = new DataColumn[] {regions.Columns["UUID"]};
|
||||||
|
return regions;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static void createCol(DataTable dt, string name, Type type)
|
||||||
|
{
|
||||||
|
DataColumn col = new DataColumn(name, type);
|
||||||
|
dt.Columns.Add(col);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static string defineTable(DataTable dt)
|
||||||
|
{
|
||||||
|
string sql = "create table " + dt.TableName + "(";
|
||||||
|
string subsql = "";
|
||||||
|
foreach (DataColumn col in dt.Columns)
|
||||||
|
{
|
||||||
|
if (subsql.Length > 0)
|
||||||
|
{
|
||||||
|
// a map function would rock so much here
|
||||||
|
subsql += ",\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
subsql += col.ColumnName + " " + SqlType(col.DataType);
|
||||||
|
if (col == dt.PrimaryKey[0])
|
||||||
|
{
|
||||||
|
subsql += " primary key";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sql += subsql;
|
||||||
|
sql += ")";
|
||||||
|
return sql;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// this is something we'll need to implement for each db
|
||||||
|
// slightly differently.
|
||||||
|
private static string SqlType(Type type)
|
||||||
|
{
|
||||||
|
if (type == typeof (String))
|
||||||
|
{
|
||||||
|
return "varchar(255)";
|
||||||
|
}
|
||||||
|
else if (type == typeof (Int32))
|
||||||
|
{
|
||||||
|
return "integer";
|
||||||
|
}
|
||||||
|
else if (type == typeof (Double))
|
||||||
|
{
|
||||||
|
return "float";
|
||||||
|
}
|
||||||
|
else if (type == typeof (Byte[]))
|
||||||
|
{
|
||||||
|
return "image";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return "varchar(255)";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Shuts down the database connection
|
||||||
|
/// </summary>
|
||||||
|
public void Close()
|
||||||
|
{
|
||||||
|
dbcon.Close();
|
||||||
|
dbcon = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Reconnects to the database
|
||||||
|
/// </summary>
|
||||||
|
public void Reconnect()
|
||||||
|
{
|
||||||
|
lock (dbcon)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
//string connectionString = "Data Source=WRK-OU-738\\SQLEXPRESS;Initial Catalog=rex;Persist Security Info=True;User ID=sa;Password=rex";
|
||||||
|
// Close the DB connection
|
||||||
|
dbcon.Close();
|
||||||
|
// Try reopen it
|
||||||
|
dbcon = new SqlConnection(connectionString);
|
||||||
|
dbcon.Open();
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
MainLog.Instance.Error("Unable to reconnect to database " + e.ToString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Runs a query with protection against SQL Injection by using parameterised input.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="sql">The SQL string - replace any variables such as WHERE x = "y" with WHERE x = @y</param>
|
||||||
|
/// <param name="parameters">The parameters - index so that @y is indexed as 'y'</param>
|
||||||
|
/// <returns>A Sql DB Command</returns>
|
||||||
|
public IDbCommand Query(string sql, Dictionary<string, string> parameters)
|
||||||
|
{
|
||||||
|
SqlCommand dbcommand = (SqlCommand) dbcon.CreateCommand();
|
||||||
|
dbcommand.CommandText = sql;
|
||||||
|
foreach (KeyValuePair<string, string> param in parameters)
|
||||||
|
{
|
||||||
|
dbcommand.Parameters.AddWithValue(param.Key, param.Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (IDbCommand) dbcommand;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Runs a database reader object and returns a region row
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="reader">An active database reader</param>
|
||||||
|
/// <returns>A region row</returns>
|
||||||
|
public RegionProfileData getRegionRow(IDataReader reader)
|
||||||
|
{
|
||||||
|
RegionProfileData regionprofile = new RegionProfileData();
|
||||||
|
|
||||||
|
if (reader.Read())
|
||||||
|
{
|
||||||
|
// Region Main
|
||||||
|
regionprofile.regionHandle = Convert.ToUInt64(reader["regionHandle"]);
|
||||||
|
regionprofile.regionName = (string) reader["regionName"];
|
||||||
|
regionprofile.UUID = new LLUUID((string) reader["uuid"]);
|
||||||
|
|
||||||
|
// Secrets
|
||||||
|
regionprofile.regionRecvKey = (string) reader["regionRecvKey"];
|
||||||
|
regionprofile.regionSecret = (string) reader["regionSecret"];
|
||||||
|
regionprofile.regionSendKey = (string) reader["regionSendKey"];
|
||||||
|
|
||||||
|
// Region Server
|
||||||
|
regionprofile.regionDataURI = (string) reader["regionDataURI"];
|
||||||
|
regionprofile.regionOnline = false; // Needs to be pinged before this can be set.
|
||||||
|
regionprofile.serverIP = (string) reader["serverIP"];
|
||||||
|
regionprofile.serverPort = Convert.ToUInt32(reader["serverPort"]);
|
||||||
|
regionprofile.serverURI = (string) reader["serverURI"];
|
||||||
|
regionprofile.httpPort = Convert.ToUInt32(reader["serverHttpPort"]);
|
||||||
|
regionprofile.remotingPort = Convert.ToUInt32(reader["serverRemotingPort"]);
|
||||||
|
|
||||||
|
|
||||||
|
// Location
|
||||||
|
regionprofile.regionLocX = Convert.ToUInt32(reader["locX"]);
|
||||||
|
regionprofile.regionLocY = Convert.ToUInt32(reader["locY"]);
|
||||||
|
regionprofile.regionLocZ = Convert.ToUInt32(reader["locZ"]);
|
||||||
|
|
||||||
|
// Neighbours - 0 = No Override
|
||||||
|
regionprofile.regionEastOverrideHandle = Convert.ToUInt64(reader["eastOverrideHandle"]);
|
||||||
|
regionprofile.regionWestOverrideHandle = Convert.ToUInt64(reader["westOverrideHandle"]);
|
||||||
|
regionprofile.regionSouthOverrideHandle = Convert.ToUInt64(reader["southOverrideHandle"]);
|
||||||
|
regionprofile.regionNorthOverrideHandle = Convert.ToUInt64(reader["northOverrideHandle"]);
|
||||||
|
|
||||||
|
// Assets
|
||||||
|
regionprofile.regionAssetURI = (string) reader["regionAssetURI"];
|
||||||
|
regionprofile.regionAssetRecvKey = (string) reader["regionAssetRecvKey"];
|
||||||
|
regionprofile.regionAssetSendKey = (string) reader["regionAssetSendKey"];
|
||||||
|
|
||||||
|
// Userserver
|
||||||
|
regionprofile.regionUserURI = (string) reader["regionUserURI"];
|
||||||
|
regionprofile.regionUserRecvKey = (string) reader["regionUserRecvKey"];
|
||||||
|
regionprofile.regionUserSendKey = (string) reader["regionUserSendKey"];
|
||||||
|
|
||||||
|
// World Map Addition
|
||||||
|
string tempRegionMap = reader["regionMapTexture"].ToString();
|
||||||
|
if (tempRegionMap != "")
|
||||||
|
{
|
||||||
|
regionprofile.regionMapTextureID = new LLUUID(tempRegionMap);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
regionprofile.regionMapTextureID = new LLUUID();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
reader.Close();
|
||||||
|
throw new Exception("No rows to return");
|
||||||
|
}
|
||||||
|
return regionprofile;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Reads a user profile from an active data reader
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="reader">An active database reader</param>
|
||||||
|
/// <returns>A user profile</returns>
|
||||||
|
public UserProfileData readUserRow(IDataReader reader)
|
||||||
|
{
|
||||||
|
UserProfileData retval = new UserProfileData();
|
||||||
|
|
||||||
|
if (reader.Read())
|
||||||
|
{
|
||||||
|
retval.UUID = new LLUUID((string) reader["UUID"]);
|
||||||
|
retval.username = (string) reader["username"];
|
||||||
|
retval.surname = (string) reader["lastname"];
|
||||||
|
|
||||||
|
retval.passwordHash = (string) reader["passwordHash"];
|
||||||
|
retval.passwordSalt = (string) reader["passwordSalt"];
|
||||||
|
|
||||||
|
retval.homeRegion = Convert.ToUInt64(reader["homeRegion"].ToString());
|
||||||
|
retval.homeLocation = new LLVector3(
|
||||||
|
Convert.ToSingle(reader["homeLocationX"].ToString()),
|
||||||
|
Convert.ToSingle(reader["homeLocationY"].ToString()),
|
||||||
|
Convert.ToSingle(reader["homeLocationZ"].ToString()));
|
||||||
|
retval.homeLookAt = new LLVector3(
|
||||||
|
Convert.ToSingle(reader["homeLookAtX"].ToString()),
|
||||||
|
Convert.ToSingle(reader["homeLookAtY"].ToString()),
|
||||||
|
Convert.ToSingle(reader["homeLookAtZ"].ToString()));
|
||||||
|
|
||||||
|
retval.created = Convert.ToInt32(reader["created"].ToString());
|
||||||
|
retval.lastLogin = Convert.ToInt32(reader["lastLogin"].ToString());
|
||||||
|
|
||||||
|
retval.userInventoryURI = (string) reader["userInventoryURI"];
|
||||||
|
retval.userAssetURI = (string) reader["userAssetURI"];
|
||||||
|
|
||||||
|
retval.profileCanDoMask = Convert.ToUInt32(reader["profileCanDoMask"].ToString());
|
||||||
|
retval.profileWantDoMask = Convert.ToUInt32(reader["profileWantDoMask"].ToString());
|
||||||
|
|
||||||
|
retval.profileAboutText = (string) reader["profileAboutText"];
|
||||||
|
retval.profileFirstText = (string) reader["profileFirstText"];
|
||||||
|
|
||||||
|
retval.profileImage = new LLUUID((string) reader["profileImage"]);
|
||||||
|
retval.profileFirstImage = new LLUUID((string) reader["profileFirstImage"]);
|
||||||
|
retval.webLoginKey = new LLUUID((string)reader["webLoginKey"]);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Reads an agent row from a database reader
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="reader">An active database reader</param>
|
||||||
|
/// <returns>A user session agent</returns>
|
||||||
|
public UserAgentData readAgentRow(IDataReader reader)
|
||||||
|
{
|
||||||
|
UserAgentData retval = new UserAgentData();
|
||||||
|
|
||||||
|
if (reader.Read())
|
||||||
|
{
|
||||||
|
// Agent IDs
|
||||||
|
retval.UUID = new LLUUID((string) reader["UUID"]);
|
||||||
|
retval.sessionID = new LLUUID((string) reader["sessionID"]);
|
||||||
|
retval.secureSessionID = new LLUUID((string) reader["secureSessionID"]);
|
||||||
|
|
||||||
|
// Agent Who?
|
||||||
|
retval.agentIP = (string) reader["agentIP"];
|
||||||
|
retval.agentPort = Convert.ToUInt32(reader["agentPort"].ToString());
|
||||||
|
retval.agentOnline = Convert.ToBoolean(reader["agentOnline"].ToString());
|
||||||
|
|
||||||
|
// Login/Logout times (UNIX Epoch)
|
||||||
|
retval.loginTime = Convert.ToInt32(reader["loginTime"].ToString());
|
||||||
|
retval.logoutTime = Convert.ToInt32(reader["logoutTime"].ToString());
|
||||||
|
|
||||||
|
// Current position
|
||||||
|
retval.currentRegion = (string) reader["currentRegion"];
|
||||||
|
retval.currentHandle = Convert.ToUInt64(reader["currentHandle"].ToString());
|
||||||
|
LLVector3.TryParse((string) reader["currentPos"], out retval.currentPos);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AssetBase getAssetRow(IDataReader reader)
|
||||||
|
{
|
||||||
|
AssetBase asset = new AssetBase();
|
||||||
|
if (reader.Read())
|
||||||
|
{
|
||||||
|
// Region Main
|
||||||
|
|
||||||
|
asset = new AssetBase();
|
||||||
|
asset.Data = (byte[]) reader["data"];
|
||||||
|
asset.Description = (string) reader["description"];
|
||||||
|
asset.MediaURL = (string)reader["mediaUrl"];
|
||||||
|
asset.FullID = new LLUUID((string) reader["id"]);
|
||||||
|
asset.InvType = Convert.ToSByte(reader["invType"]);
|
||||||
|
asset.Local = Convert.ToBoolean(reader["local"]); // ((sbyte)reader["local"]) != 0 ? true : false;
|
||||||
|
asset.Name = (string) reader["name"];
|
||||||
|
asset.Type = Convert.ToSByte(reader["assetType"]);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return null; // throw new Exception("No rows to return");
|
||||||
|
}
|
||||||
|
return asset;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a new region in the database
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="profile">The region profile to insert</param>
|
||||||
|
/// <returns>Successful?</returns>
|
||||||
|
public bool insertRegionRow(RegionProfileData profile)
|
||||||
|
{
|
||||||
|
//Insert new region
|
||||||
|
string sql =
|
||||||
|
"INSERT INTO regions ([regionHandle], [regionName], [uuid], [regionRecvKey], [regionSecret], [regionSendKey], [regionDataURI], ";
|
||||||
|
sql +=
|
||||||
|
"[serverIP], [serverPort], [serverURI], [locX], [locY], [locZ], [eastOverrideHandle], [westOverrideHandle], [southOverrideHandle], [northOverrideHandle], [regionAssetURI], [regionAssetRecvKey], ";
|
||||||
|
sql +=
|
||||||
|
"[regionAssetSendKey], [regionUserURI], [regionUserRecvKey], [regionUserSendKey], [regionMapTexture], [serverHttpPort], [serverRemotingPort]) VALUES ";
|
||||||
|
|
||||||
|
sql += "(@regionHandle, @regionName, @uuid, @regionRecvKey, @regionSecret, @regionSendKey, @regionDataURI, ";
|
||||||
|
sql +=
|
||||||
|
"@serverIP, @serverPort, @serverURI, @locX, @locY, @locZ, @eastOverrideHandle, @westOverrideHandle, @southOverrideHandle, @northOverrideHandle, @regionAssetURI, @regionAssetRecvKey, ";
|
||||||
|
sql +=
|
||||||
|
"@regionAssetSendKey, @regionUserURI, @regionUserRecvKey, @regionUserSendKey, @regionMapTexture, @serverHttpPort, @serverRemotingPort);";
|
||||||
|
|
||||||
|
Dictionary<string, string> parameters = new Dictionary<string, string>();
|
||||||
|
|
||||||
|
parameters["regionHandle"] = profile.regionHandle.ToString();
|
||||||
|
parameters["regionName"] = profile.regionName;
|
||||||
|
parameters["uuid"] = profile.UUID.ToString();
|
||||||
|
parameters["regionRecvKey"] = profile.regionRecvKey;
|
||||||
|
parameters["regionSecret"] = profile.regionSecret;
|
||||||
|
parameters["regionSendKey"] = profile.regionSendKey;
|
||||||
|
parameters["regionDataURI"] = profile.regionDataURI;
|
||||||
|
parameters["serverIP"] = profile.serverIP;
|
||||||
|
parameters["serverPort"] = profile.serverPort.ToString();
|
||||||
|
parameters["serverURI"] = profile.serverURI;
|
||||||
|
parameters["locX"] = profile.regionLocX.ToString();
|
||||||
|
parameters["locY"] = profile.regionLocY.ToString();
|
||||||
|
parameters["locZ"] = profile.regionLocZ.ToString();
|
||||||
|
parameters["eastOverrideHandle"] = profile.regionEastOverrideHandle.ToString();
|
||||||
|
parameters["westOverrideHandle"] = profile.regionWestOverrideHandle.ToString();
|
||||||
|
parameters["northOverrideHandle"] = profile.regionNorthOverrideHandle.ToString();
|
||||||
|
parameters["southOverrideHandle"] = profile.regionSouthOverrideHandle.ToString();
|
||||||
|
parameters["regionAssetURI"] = profile.regionAssetURI;
|
||||||
|
parameters["regionAssetRecvKey"] = profile.regionAssetRecvKey;
|
||||||
|
parameters["regionAssetSendKey"] = profile.regionAssetSendKey;
|
||||||
|
parameters["regionUserURI"] = profile.regionUserURI;
|
||||||
|
parameters["regionUserRecvKey"] = profile.regionUserRecvKey;
|
||||||
|
parameters["regionUserSendKey"] = profile.regionUserSendKey;
|
||||||
|
parameters["regionMapTexture"] = profile.regionMapTextureID.ToString();
|
||||||
|
parameters["serverHttpPort"] = profile.httpPort.ToString();
|
||||||
|
parameters["serverRemotingPort"] = profile.remotingPort.ToString();
|
||||||
|
|
||||||
|
|
||||||
|
bool returnval = false;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
IDbCommand result = Query(sql, parameters);
|
||||||
|
|
||||||
|
if (result.ExecuteNonQuery() == 1)
|
||||||
|
returnval = true;
|
||||||
|
|
||||||
|
result.Dispose();
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
MainLog.Instance.Error("MSSQLManager : " + e.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
return returnval;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Inserts a new row into the log database
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="serverDaemon">The daemon which triggered this event</param>
|
||||||
|
/// <param name="target">Who were we operating on when this occured (region UUID, user UUID, etc)</param>
|
||||||
|
/// <param name="methodCall">The method call where the problem occured</param>
|
||||||
|
/// <param name="arguments">The arguments passed to the method</param>
|
||||||
|
/// <param name="priority">How critical is this?</param>
|
||||||
|
/// <param name="logMessage">Extra message info</param>
|
||||||
|
/// <returns>Saved successfully?</returns>
|
||||||
|
public bool insertLogRow(string serverDaemon, string target, string methodCall, string arguments, int priority,
|
||||||
|
string logMessage)
|
||||||
|
{
|
||||||
|
string sql = "INSERT INTO logs ([target], [server], [method], [arguments], [priority], [message]) VALUES ";
|
||||||
|
sql += "(@target, @server, @method, @arguments, @priority, @message);";
|
||||||
|
|
||||||
|
Dictionary<string, string> parameters = new Dictionary<string, string>();
|
||||||
|
parameters["server"] = serverDaemon;
|
||||||
|
parameters["target"] = target;
|
||||||
|
parameters["method"] = methodCall;
|
||||||
|
parameters["arguments"] = arguments;
|
||||||
|
parameters["priority"] = priority.ToString();
|
||||||
|
parameters["message"] = logMessage;
|
||||||
|
|
||||||
|
bool returnval = false;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
IDbCommand result = Query(sql, parameters);
|
||||||
|
|
||||||
|
if (result.ExecuteNonQuery() == 1)
|
||||||
|
returnval = true;
|
||||||
|
|
||||||
|
result.Dispose();
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
MainLog.Instance.Error(e.ToString());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return returnval;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a new user and inserts it into the database
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="uuid">User ID</param>
|
||||||
|
/// <param name="username">First part of the login</param>
|
||||||
|
/// <param name="lastname">Second part of the login</param>
|
||||||
|
/// <param name="passwordHash">A salted hash of the users password</param>
|
||||||
|
/// <param name="passwordSalt">The salt used for the password hash</param>
|
||||||
|
/// <param name="homeRegion">A regionHandle of the users home region</param>
|
||||||
|
/// <param name="homeLocX">Home region position vector</param>
|
||||||
|
/// <param name="homeLocY">Home region position vector</param>
|
||||||
|
/// <param name="homeLocZ">Home region position vector</param>
|
||||||
|
/// <param name="homeLookAtX">Home region 'look at' vector</param>
|
||||||
|
/// <param name="homeLookAtY">Home region 'look at' vector</param>
|
||||||
|
/// <param name="homeLookAtZ">Home region 'look at' vector</param>
|
||||||
|
/// <param name="created">Account created (unix timestamp)</param>
|
||||||
|
/// <param name="lastlogin">Last login (unix timestamp)</param>
|
||||||
|
/// <param name="inventoryURI">Users inventory URI</param>
|
||||||
|
/// <param name="assetURI">Users asset URI</param>
|
||||||
|
/// <param name="canDoMask">I can do mask</param>
|
||||||
|
/// <param name="wantDoMask">I want to do mask</param>
|
||||||
|
/// <param name="aboutText">Profile text</param>
|
||||||
|
/// <param name="firstText">Firstlife text</param>
|
||||||
|
/// <param name="profileImage">UUID for profile image</param>
|
||||||
|
/// <param name="firstImage">UUID for firstlife image</param>
|
||||||
|
/// <returns>Success?</returns>
|
||||||
|
public bool insertUserRow(LLUUID uuid, string username, string lastname, string passwordHash,
|
||||||
|
string passwordSalt, UInt64 homeRegion, float homeLocX, float homeLocY, float homeLocZ,
|
||||||
|
float homeLookAtX, float homeLookAtY, float homeLookAtZ, int created, int lastlogin,
|
||||||
|
string inventoryURI, string assetURI, uint canDoMask, uint wantDoMask,
|
||||||
|
string aboutText, string firstText,
|
||||||
|
LLUUID profileImage, LLUUID firstImage, LLUUID webLoginKey)
|
||||||
|
{
|
||||||
|
string sql = "INSERT INTO users ";
|
||||||
|
sql += "([UUID], [username], [lastname], [passwordHash], [passwordSalt], [homeRegion], ";
|
||||||
|
sql +=
|
||||||
|
"[homeLocationX], [homeLocationY], [homeLocationZ], [homeLookAtX], [homeLookAtY], [homeLookAtZ], [created], ";
|
||||||
|
sql +=
|
||||||
|
"[lastLogin], [userInventoryURI], [userAssetURI], [profileCanDoMask], [profileWantDoMask], [profileAboutText], ";
|
||||||
|
sql += "[profileFirstText], [profileImage], [profileFirstImage], [webLoginKey]) VALUES ";
|
||||||
|
|
||||||
|
sql += "(@UUID, @username, @lastname, @passwordHash, @passwordSalt, @homeRegion, ";
|
||||||
|
sql +=
|
||||||
|
"@homeLocationX, @homeLocationY, @homeLocationZ, @homeLookAtX, @homeLookAtY, @homeLookAtZ, @created, ";
|
||||||
|
sql +=
|
||||||
|
"@lastLogin, @userInventoryURI, @userAssetURI, @profileCanDoMask, @profileWantDoMask, @profileAboutText, ";
|
||||||
|
sql += "@profileFirstText, @profileImage, @profileFirstImage, @webLoginKey);";
|
||||||
|
|
||||||
|
Dictionary<string, string> parameters = new Dictionary<string, string>();
|
||||||
|
parameters["UUID"] = uuid.ToString();
|
||||||
|
parameters["username"] = username.ToString();
|
||||||
|
parameters["lastname"] = lastname.ToString();
|
||||||
|
parameters["passwordHash"] = passwordHash.ToString();
|
||||||
|
parameters["passwordSalt"] = passwordSalt.ToString();
|
||||||
|
parameters["homeRegion"] = homeRegion.ToString();
|
||||||
|
parameters["homeLocationX"] = homeLocX.ToString();
|
||||||
|
parameters["homeLocationY"] = homeLocY.ToString();
|
||||||
|
parameters["homeLocationZ"] = homeLocZ.ToString();
|
||||||
|
parameters["homeLookAtX"] = homeLookAtX.ToString();
|
||||||
|
parameters["homeLookAtY"] = homeLookAtY.ToString();
|
||||||
|
parameters["homeLookAtZ"] = homeLookAtZ.ToString();
|
||||||
|
parameters["created"] = created.ToString();
|
||||||
|
parameters["lastLogin"] = lastlogin.ToString();
|
||||||
|
parameters["userInventoryURI"] = "";
|
||||||
|
parameters["userAssetURI"] = "";
|
||||||
|
parameters["profileCanDoMask"] = "0";
|
||||||
|
parameters["profileWantDoMask"] = "0";
|
||||||
|
parameters["profileAboutText"] = "";
|
||||||
|
parameters["profileFirstText"] = "";
|
||||||
|
parameters["profileImage"] = LLUUID.Zero.ToString();
|
||||||
|
parameters["profileFirstImage"] = LLUUID.Zero.ToString();
|
||||||
|
parameters["webLoginKey"] = LLUUID.Random().ToString();
|
||||||
|
|
||||||
|
bool returnval = false;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
IDbCommand result = Query(sql, parameters);
|
||||||
|
|
||||||
|
if (result.ExecuteNonQuery() == 1)
|
||||||
|
returnval = true;
|
||||||
|
|
||||||
|
result.Dispose();
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
MainLog.Instance.Error(e.ToString());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return returnval;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Execute a SQL statement stored in a resource, as a string
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="name"></param>
|
||||||
|
public void ExecuteResourceSql(string name)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
SqlCommand cmd = new SqlCommand(getResourceString(name), (SqlConnection) dbcon);
|
||||||
|
cmd.ExecuteNonQuery();
|
||||||
|
cmd.Dispose();
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
MainLog.Instance.Error("Unable to execute query " + e.ToString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public SqlConnection getConnection()
|
||||||
|
{
|
||||||
|
return (SqlConnection) dbcon;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Given a list of tables, return the version of the tables, as seen in the database
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="tableList"></param>
|
||||||
|
public void GetTableVersion(Dictionary<string, string> tableList)
|
||||||
|
{
|
||||||
|
lock (dbcon)
|
||||||
|
{
|
||||||
|
Dictionary<string, string> param = new Dictionary<string, string>();
|
||||||
|
param["dbname"] = dbcon.Database;
|
||||||
|
IDbCommand tablesCmd =
|
||||||
|
Query("SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_CATALOG=@dbname", param);
|
||||||
|
using (IDataReader tables = tablesCmd.ExecuteReader())
|
||||||
|
{
|
||||||
|
while (tables.Read())
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
string tableName = (string) tables["TABLE_NAME"];
|
||||||
|
if (tableList.ContainsKey(tableName))
|
||||||
|
tableList[tableName] = tableName;
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
MainLog.Instance.Error(e.ToString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tables.Close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private string getResourceString(string name)
|
||||||
|
{
|
||||||
|
Assembly assem = GetType().Assembly;
|
||||||
|
string[] names = assem.GetManifestResourceNames();
|
||||||
|
|
||||||
|
foreach (string s in names)
|
||||||
|
if (s.EndsWith(name))
|
||||||
|
using (Stream resource = assem.GetManifestResourceStream(s))
|
||||||
|
{
|
||||||
|
using (StreamReader resourceReader = new StreamReader(resource))
|
||||||
|
{
|
||||||
|
string resourceString = resourceReader.ReadToEnd();
|
||||||
|
return resourceString;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new Exception(string.Format("Resource '{0}' was not found", name));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the version of this DB provider
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>A string containing the DB provider</returns>
|
||||||
|
public string getVersion()
|
||||||
|
{
|
||||||
|
Module module = GetType().Module;
|
||||||
|
string dllName = module.Assembly.ManifestModule.Name;
|
||||||
|
Version dllVersion = module.Assembly.GetName().Version;
|
||||||
|
|
||||||
|
|
||||||
|
return
|
||||||
|
string.Format("{0}.{1}.{2}.{3}", dllVersion.Major, dllVersion.Minor, dllVersion.Build,
|
||||||
|
dllVersion.Revision);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,521 @@
|
||||||
|
/*
|
||||||
|
* 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 OpenSim 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.Data;
|
||||||
|
using System.Data.SqlClient;
|
||||||
|
using libsecondlife;
|
||||||
|
using OpenSim.Framework.Console;
|
||||||
|
|
||||||
|
namespace OpenSim.Framework.Data.MSSQL
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// A database interface class to a user profile storage system
|
||||||
|
/// </summary>
|
||||||
|
internal class MSSQLUserData : IUserData
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Database manager for MySQL
|
||||||
|
/// </summary>
|
||||||
|
public MSSQLManager database;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Loads and initialises the MySQL storage plugin
|
||||||
|
/// </summary>
|
||||||
|
public void Initialise()
|
||||||
|
{
|
||||||
|
// Load from an INI file connection details
|
||||||
|
// TODO: move this to XML?
|
||||||
|
IniFile GridDataMySqlFile = new IniFile("mssql_connection.ini");
|
||||||
|
string settingDataSource = GridDataMySqlFile.ParseFileReadValue("data_source");
|
||||||
|
string settingInitialCatalog = GridDataMySqlFile.ParseFileReadValue("initial_catalog");
|
||||||
|
string settingPersistSecurityInfo = GridDataMySqlFile.ParseFileReadValue("persist_security_info");
|
||||||
|
string settingUserId = GridDataMySqlFile.ParseFileReadValue("user_id");
|
||||||
|
string settingPassword = GridDataMySqlFile.ParseFileReadValue("password");
|
||||||
|
|
||||||
|
database =
|
||||||
|
new MSSQLManager(settingDataSource, settingInitialCatalog, settingPersistSecurityInfo, settingUserId,
|
||||||
|
settingPassword);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Searches the database for a specified user profile by name components
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="user">The first part of the account name</param>
|
||||||
|
/// <param name="last">The second part of the account name</param>
|
||||||
|
/// <returns>A user profile</returns>
|
||||||
|
public UserProfileData GetUserByName(string user, string last)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
lock (database)
|
||||||
|
{
|
||||||
|
Dictionary<string, string> param = new Dictionary<string, string>();
|
||||||
|
param["first"] = user;
|
||||||
|
param["second"] = last;
|
||||||
|
|
||||||
|
IDbCommand result =
|
||||||
|
database.Query("SELECT * FROM users WHERE username = @first AND lastname = @second", param);
|
||||||
|
IDataReader reader = result.ExecuteReader();
|
||||||
|
|
||||||
|
UserProfileData row = database.readUserRow(reader);
|
||||||
|
|
||||||
|
reader.Close();
|
||||||
|
result.Dispose();
|
||||||
|
|
||||||
|
return row;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
database.Reconnect();
|
||||||
|
MainLog.Instance.Error(e.ToString());
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#region User Friends List Data
|
||||||
|
|
||||||
|
public void AddNewUserFriend(LLUUID friendlistowner, LLUUID friend, uint perms)
|
||||||
|
{
|
||||||
|
MainLog.Instance.Verbose("FRIEND", "Stub AddNewUserFriend called");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RemoveUserFriend(LLUUID friendlistowner, LLUUID friend)
|
||||||
|
{
|
||||||
|
MainLog.Instance.Verbose("FRIEND", "Stub RemoveUserFriend called");
|
||||||
|
}
|
||||||
|
public void UpdateUserFriendPerms(LLUUID friendlistowner, LLUUID friend, uint perms)
|
||||||
|
{
|
||||||
|
MainLog.Instance.Verbose("FRIEND", "Stub UpdateUserFriendPerms called");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public List<FriendListItem> GetUserFriendList(LLUUID friendlistowner)
|
||||||
|
{
|
||||||
|
MainLog.Instance.Verbose("FRIEND", "Stub GetUserFriendList called");
|
||||||
|
return new List<FriendListItem>();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
public void UpdateUserCurrentRegion(LLUUID avatarid, LLUUID regionuuid)
|
||||||
|
{
|
||||||
|
MainLog.Instance.Verbose("USER", "Stub UpdateUserCUrrentRegion called");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void LogOffUser(LLUUID avatarid)
|
||||||
|
{
|
||||||
|
MainLog.Instance.Verbose("USER", "Stub LogOffUser called");
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Framework.AvatarPickerAvatar> GeneratePickerResults(LLUUID queryID, string query)
|
||||||
|
{
|
||||||
|
List<Framework.AvatarPickerAvatar> returnlist = new List<Framework.AvatarPickerAvatar>();
|
||||||
|
string[] querysplit;
|
||||||
|
querysplit = query.Split(' ');
|
||||||
|
if (querysplit.Length == 2)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
lock (database)
|
||||||
|
{
|
||||||
|
Dictionary<string, string> param = new Dictionary<string, string>();
|
||||||
|
param["first"] = querysplit[0];
|
||||||
|
param["second"] = querysplit[1];
|
||||||
|
|
||||||
|
IDbCommand result =
|
||||||
|
database.Query(
|
||||||
|
"SELECT UUID,username,surname FROM users WHERE username = @first AND lastname = @second",
|
||||||
|
param);
|
||||||
|
IDataReader reader = result.ExecuteReader();
|
||||||
|
|
||||||
|
|
||||||
|
while (reader.Read())
|
||||||
|
{
|
||||||
|
Framework.AvatarPickerAvatar user = new Framework.AvatarPickerAvatar();
|
||||||
|
user.AvatarID = new LLUUID((string) reader["UUID"]);
|
||||||
|
user.firstName = (string) reader["username"];
|
||||||
|
user.lastName = (string) reader["surname"];
|
||||||
|
returnlist.Add(user);
|
||||||
|
}
|
||||||
|
reader.Close();
|
||||||
|
result.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
database.Reconnect();
|
||||||
|
MainLog.Instance.Error(e.ToString());
|
||||||
|
return returnlist;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (querysplit.Length == 1)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
lock (database)
|
||||||
|
{
|
||||||
|
Dictionary<string, string> param = new Dictionary<string, string>();
|
||||||
|
param["first"] = querysplit[0];
|
||||||
|
param["second"] = querysplit[1];
|
||||||
|
|
||||||
|
IDbCommand result =
|
||||||
|
database.Query(
|
||||||
|
"SELECT UUID,username,surname FROM users WHERE username = @first OR lastname = @second",
|
||||||
|
param);
|
||||||
|
IDataReader reader = result.ExecuteReader();
|
||||||
|
|
||||||
|
|
||||||
|
while (reader.Read())
|
||||||
|
{
|
||||||
|
Framework.AvatarPickerAvatar user = new Framework.AvatarPickerAvatar();
|
||||||
|
user.AvatarID = new LLUUID((string) reader["UUID"]);
|
||||||
|
user.firstName = (string) reader["username"];
|
||||||
|
user.lastName = (string) reader["surname"];
|
||||||
|
returnlist.Add(user);
|
||||||
|
}
|
||||||
|
reader.Close();
|
||||||
|
result.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
database.Reconnect();
|
||||||
|
MainLog.Instance.Error(e.ToString());
|
||||||
|
return returnlist;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return returnlist;
|
||||||
|
}
|
||||||
|
|
||||||
|
// See IUserData
|
||||||
|
public UserProfileData GetUserByUUID(LLUUID uuid)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
lock (database)
|
||||||
|
{
|
||||||
|
Dictionary<string, string> param = new Dictionary<string, string>();
|
||||||
|
param["uuid"] = uuid.ToString();
|
||||||
|
|
||||||
|
IDbCommand result = database.Query("SELECT * FROM users WHERE UUID = @uuid", param);
|
||||||
|
IDataReader reader = result.ExecuteReader();
|
||||||
|
|
||||||
|
UserProfileData row = database.readUserRow(reader);
|
||||||
|
|
||||||
|
reader.Close();
|
||||||
|
result.Dispose();
|
||||||
|
|
||||||
|
return row;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
database.Reconnect();
|
||||||
|
MainLog.Instance.Error(e.ToString());
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Searches the database for a specified user profile by account
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="uuid">The account</param>
|
||||||
|
/// <returns>The users profile</returns>
|
||||||
|
public UserProfileData GetUserByAccount(string account)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
lock (database)
|
||||||
|
{
|
||||||
|
Dictionary<string, string> param = new Dictionary<string, string>();
|
||||||
|
param["account"] = account;
|
||||||
|
|
||||||
|
IDbCommand result = database.Query("SELECT * FROM users WHERE account = @account", param);
|
||||||
|
IDataReader reader = result.ExecuteReader();
|
||||||
|
|
||||||
|
UserProfileData row = database.readUserRow(reader);
|
||||||
|
|
||||||
|
reader.Close();
|
||||||
|
result.Dispose();
|
||||||
|
|
||||||
|
if (row != null)
|
||||||
|
{
|
||||||
|
UserAgentData agentData = GetAgentByUUID(row.UUID);
|
||||||
|
if (agentData != null)
|
||||||
|
{
|
||||||
|
row.currentAgent = agentData;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return row;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
database.Reconnect();
|
||||||
|
MainLog.Instance.Error(e.ToString());
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns a user session searching by name
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="name">The account name</param>
|
||||||
|
/// <returns>The users session</returns>
|
||||||
|
public UserAgentData GetAgentByName(string name)
|
||||||
|
{
|
||||||
|
return GetAgentByName(name.Split(' ')[0], name.Split(' ')[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns a user session by account name
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="user">First part of the users account name</param>
|
||||||
|
/// <param name="last">Second part of the users account name</param>
|
||||||
|
/// <returns>The users session</returns>
|
||||||
|
public UserAgentData GetAgentByName(string user, string last)
|
||||||
|
{
|
||||||
|
UserProfileData profile = GetUserByName(user, last);
|
||||||
|
return GetAgentByUUID(profile.UUID);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns an agent session by account UUID
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="uuid">The accounts UUID</param>
|
||||||
|
/// <returns>The users session</returns>
|
||||||
|
public UserAgentData GetAgentByUUID(LLUUID uuid)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
lock (database)
|
||||||
|
{
|
||||||
|
Dictionary<string, string> param = new Dictionary<string, string>();
|
||||||
|
param["uuid"] = uuid.ToString();
|
||||||
|
|
||||||
|
IDbCommand result = database.Query("SELECT * FROM agents WHERE UUID = @uuid", param);
|
||||||
|
IDataReader reader = result.ExecuteReader();
|
||||||
|
|
||||||
|
UserAgentData row = database.readAgentRow(reader);
|
||||||
|
|
||||||
|
reader.Close();
|
||||||
|
result.Dispose();
|
||||||
|
|
||||||
|
return row;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
database.Reconnect();
|
||||||
|
MainLog.Instance.Error(e.ToString());
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a new users profile
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="user">The user profile to create</param>
|
||||||
|
public void AddNewUserProfile(UserProfileData user)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
lock (database)
|
||||||
|
{
|
||||||
|
database.insertUserRow(user.UUID, user.username, user.surname, user.passwordHash, user.passwordSalt,
|
||||||
|
user.homeRegion, user.homeLocation.X, user.homeLocation.Y,
|
||||||
|
user.homeLocation.Z,
|
||||||
|
user.homeLookAt.X, user.homeLookAt.Y, user.homeLookAt.Z, user.created,
|
||||||
|
user.lastLogin, user.userInventoryURI, user.userAssetURI,
|
||||||
|
user.profileCanDoMask, user.profileWantDoMask,
|
||||||
|
user.profileAboutText, user.profileFirstText, user.profileImage,
|
||||||
|
user.profileFirstImage,user.webLoginKey);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
database.Reconnect();
|
||||||
|
MainLog.Instance.Error(e.ToString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a new agent
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="agent">The agent to create</param>
|
||||||
|
public void AddNewUserAgent(UserAgentData agent)
|
||||||
|
{
|
||||||
|
// Do nothing.
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public bool UpdateUserProfile(UserProfileData user)
|
||||||
|
{
|
||||||
|
SqlCommand command = new SqlCommand("UPDATE users set UUID = @uuid, " +
|
||||||
|
"username = @username, " +
|
||||||
|
"lastname = @lastname," +
|
||||||
|
"passwordHash = @passwordHash," +
|
||||||
|
"passwordSalt = @passwordSalt," +
|
||||||
|
"homeRegion = @homeRegion," +
|
||||||
|
"homeLocationX = @homeLocationX," +
|
||||||
|
"homeLocationY = @homeLocationY," +
|
||||||
|
"homeLocationZ = @homeLocationZ," +
|
||||||
|
"homeLookAtX = @homeLookAtX," +
|
||||||
|
"homeLookAtY = @homeLookAtY," +
|
||||||
|
"homeLookAtZ = @homeLookAtZ," +
|
||||||
|
"created = @created," +
|
||||||
|
"lastLogin = @lastLogin," +
|
||||||
|
"userInventoryURI = @userInventoryURI," +
|
||||||
|
"userAssetURI = @userAssetURI," +
|
||||||
|
"profileCanDoMask = @profileCanDoMask," +
|
||||||
|
"profileWantDoMask = @profileWantDoMask," +
|
||||||
|
"profileAboutText = @profileAboutText," +
|
||||||
|
"profileFirstText = @profileFirstText," +
|
||||||
|
"profileImage = @profileImage," +
|
||||||
|
"profileFirstImage = @profileFirstImage where " +
|
||||||
|
"UUID = @keyUUUID;", database.getConnection());
|
||||||
|
SqlParameter param1 = new SqlParameter("@uuid", user.UUID.ToString());
|
||||||
|
SqlParameter param2 = new SqlParameter("@username", user.username);
|
||||||
|
SqlParameter param3 = new SqlParameter("@lastname", user.surname);
|
||||||
|
SqlParameter param4 = new SqlParameter("@passwordHash", user.passwordHash);
|
||||||
|
SqlParameter param5 = new SqlParameter("@passwordSalt", user.passwordSalt);
|
||||||
|
SqlParameter param6 = new SqlParameter("@homeRegion", Convert.ToInt64(user.homeRegion));
|
||||||
|
SqlParameter param7 = new SqlParameter("@homeLocationX", user.homeLocation.X);
|
||||||
|
SqlParameter param8 = new SqlParameter("@homeLocationY", user.homeLocation.Y);
|
||||||
|
SqlParameter param9 = new SqlParameter("@homeLocationZ", user.homeLocation.Y);
|
||||||
|
SqlParameter param10 = new SqlParameter("@homeLookAtX", user.homeLookAt.X);
|
||||||
|
SqlParameter param11 = new SqlParameter("@homeLookAtY", user.homeLookAt.Y);
|
||||||
|
SqlParameter param12 = new SqlParameter("@homeLookAtZ", user.homeLookAt.Z);
|
||||||
|
SqlParameter param13 = new SqlParameter("@created", Convert.ToInt32(user.created));
|
||||||
|
SqlParameter param14 = new SqlParameter("@lastLogin", Convert.ToInt32(user.lastLogin));
|
||||||
|
SqlParameter param15 = new SqlParameter("@userInventoryURI", user.userInventoryURI);
|
||||||
|
SqlParameter param16 = new SqlParameter("@userAssetURI", user.userAssetURI);
|
||||||
|
SqlParameter param17 = new SqlParameter("@profileCanDoMask", Convert.ToInt32(user.profileCanDoMask));
|
||||||
|
SqlParameter param18 = new SqlParameter("@profileWantDoMask", Convert.ToInt32(user.profileWantDoMask));
|
||||||
|
SqlParameter param19 = new SqlParameter("@profileAboutText", user.profileAboutText);
|
||||||
|
SqlParameter param20 = new SqlParameter("@profileFirstText", user.profileFirstText);
|
||||||
|
SqlParameter param21 = new SqlParameter("@profileImage", LLUUID.Zero.ToString());
|
||||||
|
SqlParameter param22 = new SqlParameter("@profileFirstImage", LLUUID.Zero.ToString());
|
||||||
|
SqlParameter param23 = new SqlParameter("@keyUUUID", user.UUID.ToString());
|
||||||
|
command.Parameters.Add(param1);
|
||||||
|
command.Parameters.Add(param2);
|
||||||
|
command.Parameters.Add(param3);
|
||||||
|
command.Parameters.Add(param4);
|
||||||
|
command.Parameters.Add(param5);
|
||||||
|
command.Parameters.Add(param6);
|
||||||
|
command.Parameters.Add(param7);
|
||||||
|
command.Parameters.Add(param8);
|
||||||
|
command.Parameters.Add(param9);
|
||||||
|
command.Parameters.Add(param10);
|
||||||
|
command.Parameters.Add(param11);
|
||||||
|
command.Parameters.Add(param12);
|
||||||
|
command.Parameters.Add(param13);
|
||||||
|
command.Parameters.Add(param14);
|
||||||
|
command.Parameters.Add(param15);
|
||||||
|
command.Parameters.Add(param16);
|
||||||
|
command.Parameters.Add(param17);
|
||||||
|
command.Parameters.Add(param18);
|
||||||
|
command.Parameters.Add(param19);
|
||||||
|
command.Parameters.Add(param20);
|
||||||
|
command.Parameters.Add(param21);
|
||||||
|
command.Parameters.Add(param22);
|
||||||
|
command.Parameters.Add(param23);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
int affected = command.ExecuteNonQuery();
|
||||||
|
if (affected != 0)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
MainLog.Instance.Error(e.ToString());
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Performs a money transfer request between two accounts
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="from">The senders account ID</param>
|
||||||
|
/// <param name="to">The receivers account ID</param>
|
||||||
|
/// <param name="amount">The amount to transfer</param>
|
||||||
|
/// <returns>Success?</returns>
|
||||||
|
public bool MoneyTransferRequest(LLUUID from, LLUUID to, uint amount)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Performs an inventory transfer request between two accounts
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>TODO: Move to inventory server</remarks>
|
||||||
|
/// <param name="from">The senders account ID</param>
|
||||||
|
/// <param name="to">The receivers account ID</param>
|
||||||
|
/// <param name="item">The item to transfer</param>
|
||||||
|
/// <returns>Success?</returns>
|
||||||
|
public bool InventoryTransferRequest(LLUUID from, LLUUID to, LLUUID item)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Database provider name
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>Provider name</returns>
|
||||||
|
public string getName()
|
||||||
|
{
|
||||||
|
return "MSSQL Userdata Interface";
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Database provider version
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>provider version</returns>
|
||||||
|
public string GetVersion()
|
||||||
|
{
|
||||||
|
return database.getVersion();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Not implemented
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="query"></param>
|
||||||
|
public void runQuery(string query)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,38 @@
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
// General Information about an assembly is controlled through the following
|
||||||
|
// set of attributes. Change these attribute values to modify the information
|
||||||
|
// associated with an assembly.
|
||||||
|
|
||||||
|
[assembly : AssemblyTitle("OpenSim.Framework.Data.MSSQL")]
|
||||||
|
[assembly : AssemblyDescription("")]
|
||||||
|
[assembly : AssemblyConfiguration("")]
|
||||||
|
[assembly : AssemblyCompany("")]
|
||||||
|
[assembly : AssemblyProduct("OpenSim.Framework.Data.MSSQL")]
|
||||||
|
[assembly : AssemblyCopyright("Copyright © 2007")]
|
||||||
|
[assembly : AssemblyTrademark("")]
|
||||||
|
[assembly : AssemblyCulture("")]
|
||||||
|
|
||||||
|
// Setting ComVisible to false makes the types in this assembly not visible
|
||||||
|
// to COM components. If you need to access a type in this assembly from
|
||||||
|
// COM, set the ComVisible attribute to true on that type.
|
||||||
|
|
||||||
|
[assembly : ComVisible(false)]
|
||||||
|
|
||||||
|
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||||
|
|
||||||
|
[assembly : Guid("0e1c1ca4-2cf2-4315-b0e7-432c02feea8a")]
|
||||||
|
|
||||||
|
// Version information for an assembly consists of the following four values:
|
||||||
|
//
|
||||||
|
// Major Version
|
||||||
|
// Minor Version
|
||||||
|
// Build Number
|
||||||
|
// Revision
|
||||||
|
//
|
||||||
|
// You can specify all the values or you can default the Revision and Build Numbers
|
||||||
|
// by using the '*' as shown below:
|
||||||
|
|
||||||
|
[assembly : AssemblyVersion("1.0.0.0")]
|
||||||
|
[assembly : AssemblyFileVersion("1.0.0.0")]
|
|
@ -0,0 +1,20 @@
|
||||||
|
SET ANSI_NULLS ON
|
||||||
|
SET QUOTED_IDENTIFIER ON
|
||||||
|
SET ANSI_PADDING ON
|
||||||
|
CREATE TABLE [assets] (
|
||||||
|
[id] [varchar](36) NOT NULL,
|
||||||
|
[name] [varchar](64) NOT NULL,
|
||||||
|
[description] [varchar](64) NOT NULL,
|
||||||
|
[mediaURL] [varchar](255) NOT NULL,
|
||||||
|
[assetType] [tinyint] NOT NULL,
|
||||||
|
[invType] [tinyint] NOT NULL,
|
||||||
|
[local] [tinyint] NOT NULL,
|
||||||
|
[temporary] [tinyint] NOT NULL,
|
||||||
|
[data] [image] NOT NULL,
|
||||||
|
PRIMARY KEY CLUSTERED
|
||||||
|
(
|
||||||
|
[id] ASC
|
||||||
|
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
|
||||||
|
) ON [PRIMARY]
|
||||||
|
|
||||||
|
SET ANSI_PADDING OFF
|
|
@ -0,0 +1,27 @@
|
||||||
|
SET ANSI_NULLS ON
|
||||||
|
SET QUOTED_IDENTIFIER ON
|
||||||
|
SET ANSI_PADDING ON
|
||||||
|
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 CLUSTERED
|
||||||
|
(
|
||||||
|
[folderID] ASC
|
||||||
|
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
|
||||||
|
) ON [PRIMARY]
|
||||||
|
|
||||||
|
CREATE NONCLUSTERED INDEX [owner] ON [inventoryfolders]
|
||||||
|
(
|
||||||
|
[agentID] ASC
|
||||||
|
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
|
||||||
|
|
||||||
|
CREATE NONCLUSTERED INDEX [parent] ON [inventoryfolders]
|
||||||
|
(
|
||||||
|
[parentFolderID] ASC
|
||||||
|
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
|
||||||
|
|
||||||
|
SET ANSI_PADDING OFF
|
|
@ -0,0 +1,39 @@
|
||||||
|
SET ANSI_NULLS ON
|
||||||
|
|
||||||
|
SET QUOTED_IDENTIFIER ON
|
||||||
|
|
||||||
|
SET ANSI_PADDING ON
|
||||||
|
|
||||||
|
CREATE TABLE [inventoryitems] (
|
||||||
|
[inventoryID] [varchar](36) NOT NULL default '',
|
||||||
|
[assetID] [varchar](36) default NULL,
|
||||||
|
[assetType] [int] default NULL,
|
||||||
|
[parentFolderID] [varchar](36) default NULL,
|
||||||
|
[avatarID] [varchar](36) default NULL,
|
||||||
|
[inventoryName] [varchar](64) default NULL,
|
||||||
|
[inventoryDescription] [varchar](64) default NULL,
|
||||||
|
[inventoryNextPermissions] [int] default NULL,
|
||||||
|
[inventoryCurrentPermissions] [int] default NULL,
|
||||||
|
[invType] [int] default NULL,
|
||||||
|
[creatorID] [varchar](36) default NULL,
|
||||||
|
[inventoryBasePermissions] [int] NOT NULL default 0,
|
||||||
|
[inventoryEveryOnePermissions] [int] NOT NULL default 0,
|
||||||
|
PRIMARY KEY CLUSTERED
|
||||||
|
(
|
||||||
|
[inventoryID] ASC
|
||||||
|
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
|
||||||
|
) ON [PRIMARY]
|
||||||
|
|
||||||
|
|
||||||
|
CREATE NONCLUSTERED INDEX [owner] ON [inventoryitems]
|
||||||
|
(
|
||||||
|
[avatarID] ASC
|
||||||
|
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
|
||||||
|
|
||||||
|
CREATE NONCLUSTERED INDEX [folder] ON [inventoryitems]
|
||||||
|
(
|
||||||
|
[parentFolderID] ASC
|
||||||
|
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
|
||||||
|
|
||||||
|
SET ANSI_PADDING OFF
|
||||||
|
|
|
@ -0,0 +1,37 @@
|
||||||
|
SET ANSI_NULLS ON
|
||||||
|
|
||||||
|
SET QUOTED_IDENTIFIER ON
|
||||||
|
|
||||||
|
SET ANSI_PADDING ON
|
||||||
|
|
||||||
|
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] NOT NULL,
|
||||||
|
[agentOnline] [tinyint] NOT NULL,
|
||||||
|
[loginTime] [int] NOT NULL,
|
||||||
|
[logoutTime] [int] NOT NULL,
|
||||||
|
[currentRegion] [varchar](36) NOT NULL,
|
||||||
|
[currentHandle] [bigint] NOT NULL,
|
||||||
|
[currentPos] [varchar](64) NOT NULL,
|
||||||
|
PRIMARY KEY CLUSTERED
|
||||||
|
(
|
||||||
|
[UUID] ASC
|
||||||
|
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
|
||||||
|
) ON [PRIMARY]
|
||||||
|
|
||||||
|
|
||||||
|
CREATE NONCLUSTERED INDEX [session] ON [agents]
|
||||||
|
(
|
||||||
|
[sessionID] ASC
|
||||||
|
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
|
||||||
|
|
||||||
|
CREATE NONCLUSTERED INDEX [ssession] ON [agents]
|
||||||
|
(
|
||||||
|
[secureSessionID] ASC
|
||||||
|
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
|
||||||
|
|
||||||
|
SET ANSI_PADDING OFF
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
SET ANSI_NULLS ON
|
||||||
|
|
||||||
|
SET QUOTED_IDENTIFIER ON
|
||||||
|
|
||||||
|
SET ANSI_PADDING ON
|
||||||
|
|
||||||
|
CREATE TABLE [logs] (
|
||||||
|
[logID] [int] NOT NULL,
|
||||||
|
[target] [varchar](36) default NULL,
|
||||||
|
[server] [varchar](64) default NULL,
|
||||||
|
[method] [varchar](64) default NULL,
|
||||||
|
[arguments] [varchar](255) default NULL,
|
||||||
|
[priority] [int] default NULL,
|
||||||
|
[message] [ntext],
|
||||||
|
PRIMARY KEY CLUSTERED
|
||||||
|
(
|
||||||
|
[logID] ASC
|
||||||
|
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
|
||||||
|
) ON [PRIMARY]
|
||||||
|
|
|
@ -0,0 +1,42 @@
|
||||||
|
SET ANSI_NULLS ON
|
||||||
|
|
||||||
|
SET QUOTED_IDENTIFIER ON
|
||||||
|
|
||||||
|
SET ANSI_PADDING ON
|
||||||
|
|
||||||
|
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] 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] NOT NULL,
|
||||||
|
[lastLogin] [int] NOT NULL,
|
||||||
|
[userInventoryURI] [varchar](255) default NULL,
|
||||||
|
[userAssetURI] [varchar](255) default NULL,
|
||||||
|
[profileCanDoMask] [int] default NULL,
|
||||||
|
[profileWantDoMask] [int] default NULL,
|
||||||
|
[profileAboutText] [ntext],
|
||||||
|
[profileFirstText] [ntext],
|
||||||
|
[profileImage] [varchar](36) default NULL,
|
||||||
|
[profileFirstImage] [varchar](36) default NULL,
|
||||||
|
[webLoginKey] [varchar](36) default NULL,
|
||||||
|
PRIMARY KEY CLUSTERED
|
||||||
|
(
|
||||||
|
[UUID] ASC
|
||||||
|
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
|
||||||
|
) ON [PRIMARY]
|
||||||
|
|
||||||
|
|
||||||
|
CREATE NONCLUSTERED INDEX [usernames] ON [users]
|
||||||
|
(
|
||||||
|
[username] ASC,
|
||||||
|
[lastname] ASC
|
||||||
|
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
|
|
@ -0,0 +1,194 @@
|
||||||
|
/*
|
||||||
|
* 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 OpenSim 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.Data;
|
||||||
|
using libsecondlife;
|
||||||
|
using MySql.Data.MySqlClient;
|
||||||
|
using OpenSim.Framework.Console;
|
||||||
|
|
||||||
|
namespace OpenSim.Framework.Data.MySQL
|
||||||
|
{
|
||||||
|
internal class MySQLAssetData : IAssetProvider
|
||||||
|
{
|
||||||
|
private MySQLManager _dbConnection;
|
||||||
|
|
||||||
|
#region IAssetProvider Members
|
||||||
|
|
||||||
|
private void UpgradeAssetsTable(string oldVersion)
|
||||||
|
{
|
||||||
|
// null as the version, indicates that the table didn't exist
|
||||||
|
if (oldVersion == null)
|
||||||
|
{
|
||||||
|
MainLog.Instance.Notice("ASSETS", "Creating new database tables");
|
||||||
|
_dbConnection.ExecuteResourceSql("CreateAssetsTable.sql");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Ensure that the assets related tables exists and are at the latest version
|
||||||
|
/// </summary>
|
||||||
|
private void TestTables()
|
||||||
|
{
|
||||||
|
Dictionary<string, string> tableList = new Dictionary<string, string>();
|
||||||
|
|
||||||
|
tableList["assets"] = null;
|
||||||
|
_dbConnection.GetTableVersion(tableList);
|
||||||
|
|
||||||
|
UpgradeAssetsTable(tableList["assets"]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public AssetBase FetchAsset(LLUUID assetID)
|
||||||
|
{
|
||||||
|
AssetBase asset = null;
|
||||||
|
lock (_dbConnection)
|
||||||
|
{
|
||||||
|
MySqlCommand cmd =
|
||||||
|
new MySqlCommand(
|
||||||
|
"SELECT name, description, assetType, invType, local, temporary, data FROM assets WHERE id=?id",
|
||||||
|
_dbConnection.Connection);
|
||||||
|
MySqlParameter p = cmd.Parameters.Add("?id", MySqlDbType.Binary, 16);
|
||||||
|
p.Value = assetID.GetBytes();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using (MySqlDataReader dbReader = cmd.ExecuteReader(CommandBehavior.SingleRow))
|
||||||
|
{
|
||||||
|
if (dbReader.Read())
|
||||||
|
{
|
||||||
|
asset = new AssetBase();
|
||||||
|
asset.Data = (byte[]) dbReader["data"];
|
||||||
|
asset.Description = (string) dbReader["description"];
|
||||||
|
asset.FullID = assetID;
|
||||||
|
asset.InvType = (sbyte) dbReader["invType"];
|
||||||
|
asset.Local = ((sbyte) dbReader["local"]) != 0 ? true : false;
|
||||||
|
asset.Name = (string) dbReader["name"];
|
||||||
|
asset.Type = (sbyte) dbReader["assetType"];
|
||||||
|
}
|
||||||
|
dbReader.Close();
|
||||||
|
cmd.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
MainLog.Instance.Warn("ASSETS", "MySql failure fetching asset");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return asset;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void CreateAsset(AssetBase asset)
|
||||||
|
{
|
||||||
|
MySqlCommand cmd =
|
||||||
|
new MySqlCommand(
|
||||||
|
"REPLACE INTO assets(id, name, description, assetType, invType, local, temporary, data)" +
|
||||||
|
"VALUES(?id, ?name, ?description, ?assetType, ?invType, ?local, ?temporary, ?data)",
|
||||||
|
_dbConnection.Connection);
|
||||||
|
|
||||||
|
// need to ensure we dispose
|
||||||
|
using (cmd)
|
||||||
|
{
|
||||||
|
MySqlParameter p = cmd.Parameters.Add("?id", MySqlDbType.Binary, 16);
|
||||||
|
p.Value = asset.FullID.GetBytes();
|
||||||
|
cmd.Parameters.AddWithValue("?name", asset.Name);
|
||||||
|
cmd.Parameters.AddWithValue("?description", asset.Description);
|
||||||
|
cmd.Parameters.AddWithValue("?assetType", asset.Type);
|
||||||
|
cmd.Parameters.AddWithValue("?invType", asset.InvType);
|
||||||
|
cmd.Parameters.AddWithValue("?local", asset.Local);
|
||||||
|
cmd.Parameters.AddWithValue("?temporary", asset.Temporary);
|
||||||
|
cmd.Parameters.AddWithValue("?data", asset.Data);
|
||||||
|
cmd.ExecuteNonQuery();
|
||||||
|
cmd.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void UpdateAsset(AssetBase asset)
|
||||||
|
{
|
||||||
|
CreateAsset(asset);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool ExistsAsset(LLUUID uuid)
|
||||||
|
{
|
||||||
|
throw new Exception("The method or operation is not implemented.");
|
||||||
|
}
|
||||||
|
|
||||||
|
// rex, new function, fixme not implemented
|
||||||
|
public List<AssetBase> GetAssetList(int vAssetType)
|
||||||
|
{
|
||||||
|
List<AssetBase> retvals = new List<AssetBase>();
|
||||||
|
return retvals;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// All writes are immediately commited to the database, so this is a no-op
|
||||||
|
/// </summary>
|
||||||
|
public void CommitAssets()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// rex new function for "replace assets" functionality
|
||||||
|
// TODO: actual implementation by someone, should return LLUUID of an asset
|
||||||
|
// with matching type & name, or zero if not in DB
|
||||||
|
public LLUUID ExistsAsset(sbyte type, string name)
|
||||||
|
{
|
||||||
|
return LLUUID.Zero;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region IPlugin Members
|
||||||
|
|
||||||
|
public void Initialise()
|
||||||
|
{
|
||||||
|
IniFile GridDataMySqlFile = new IniFile("mysql_connection.ini");
|
||||||
|
string hostname = GridDataMySqlFile.ParseFileReadValue("hostname");
|
||||||
|
string database = GridDataMySqlFile.ParseFileReadValue("database");
|
||||||
|
string username = GridDataMySqlFile.ParseFileReadValue("username");
|
||||||
|
string password = GridDataMySqlFile.ParseFileReadValue("password");
|
||||||
|
string pooling = GridDataMySqlFile.ParseFileReadValue("pooling");
|
||||||
|
string port = GridDataMySqlFile.ParseFileReadValue("port");
|
||||||
|
|
||||||
|
_dbConnection = new MySQLManager(hostname, database, username, password, pooling, port);
|
||||||
|
|
||||||
|
TestTables();
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Version
|
||||||
|
{
|
||||||
|
get { return _dbConnection.getVersion(); }
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Name
|
||||||
|
{
|
||||||
|
get { return "MySQL Asset storage engine"; }
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,413 @@
|
||||||
|
/*
|
||||||
|
* 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 OpenSim 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.Data;
|
||||||
|
using System.Security.Cryptography;
|
||||||
|
using System.Text;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
using libsecondlife;
|
||||||
|
using OpenSim.Framework.Console;
|
||||||
|
|
||||||
|
namespace OpenSim.Framework.Data.MySQL
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// A MySQL Interface for the Grid Server
|
||||||
|
/// </summary>
|
||||||
|
public class MySQLGridData : IGridData
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// MySQL Database Manager
|
||||||
|
/// </summary>
|
||||||
|
private MySQLManager database;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initialises the Grid Interface
|
||||||
|
/// </summary>
|
||||||
|
public void Initialise()
|
||||||
|
{
|
||||||
|
IniFile GridDataMySqlFile = new IniFile("mysql_connection.ini");
|
||||||
|
string settingHostname = GridDataMySqlFile.ParseFileReadValue("hostname");
|
||||||
|
string settingDatabase = GridDataMySqlFile.ParseFileReadValue("database");
|
||||||
|
string settingUsername = GridDataMySqlFile.ParseFileReadValue("username");
|
||||||
|
string settingPassword = GridDataMySqlFile.ParseFileReadValue("password");
|
||||||
|
string settingPooling = GridDataMySqlFile.ParseFileReadValue("pooling");
|
||||||
|
string settingPort = GridDataMySqlFile.ParseFileReadValue("port");
|
||||||
|
|
||||||
|
database =
|
||||||
|
new MySQLManager(settingHostname, settingDatabase, settingUsername, settingPassword, settingPooling,
|
||||||
|
settingPort);
|
||||||
|
|
||||||
|
TestTables();
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Test and initialization code
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Ensure that the user related tables exists and are at the latest version
|
||||||
|
/// </summary>
|
||||||
|
private void TestTables()
|
||||||
|
{
|
||||||
|
Dictionary<string, string> tableList = new Dictionary<string, string>();
|
||||||
|
|
||||||
|
tableList["regions"] = null;
|
||||||
|
database.GetTableVersion(tableList);
|
||||||
|
|
||||||
|
UpgradeRegionsTable(tableList["regions"]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Create or upgrade the table if necessary
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="oldVersion">A null indicates that the table does not
|
||||||
|
/// currently exist</param>
|
||||||
|
private void UpgradeRegionsTable(string oldVersion)
|
||||||
|
{
|
||||||
|
// null as the version, indicates that the table didn't exist
|
||||||
|
if (oldVersion == null)
|
||||||
|
{
|
||||||
|
database.ExecuteResourceSql("CreateRegionsTable.sql");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Shuts down the grid interface
|
||||||
|
/// </summary>
|
||||||
|
public void Close()
|
||||||
|
{
|
||||||
|
database.Close();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the plugin name
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>Plugin name</returns>
|
||||||
|
public string getName()
|
||||||
|
{
|
||||||
|
return "MySql OpenGridData";
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the plugin version
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>Plugin version</returns>
|
||||||
|
public string getVersion()
|
||||||
|
{
|
||||||
|
return "0.1";
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns all the specified region profiles within coordates -- coordinates are inclusive
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="xmin">Minimum X coordinate</param>
|
||||||
|
/// <param name="ymin">Minimum Y coordinate</param>
|
||||||
|
/// <param name="xmax">Maximum X coordinate</param>
|
||||||
|
/// <param name="ymax">Maximum Y coordinate</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public RegionProfileData[] GetProfilesInRange(uint xmin, uint ymin, uint xmax, uint ymax)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
lock (database)
|
||||||
|
{
|
||||||
|
Dictionary<string, string> param = new Dictionary<string, string>();
|
||||||
|
param["?xmin"] = xmin.ToString();
|
||||||
|
param["?ymin"] = ymin.ToString();
|
||||||
|
param["?xmax"] = xmax.ToString();
|
||||||
|
param["?ymax"] = ymax.ToString();
|
||||||
|
|
||||||
|
IDbCommand result =
|
||||||
|
database.Query(
|
||||||
|
"SELECT * FROM regions WHERE locX >= ?xmin AND locX <= ?xmax AND locY >= ?ymin AND locY <= ?ymax",
|
||||||
|
param);
|
||||||
|
IDataReader reader = result.ExecuteReader();
|
||||||
|
|
||||||
|
RegionProfileData row;
|
||||||
|
|
||||||
|
List<RegionProfileData> rows = new List<RegionProfileData>();
|
||||||
|
|
||||||
|
while ((row = database.readSimRow(reader)) != null)
|
||||||
|
{
|
||||||
|
rows.Add(row);
|
||||||
|
}
|
||||||
|
reader.Close();
|
||||||
|
result.Dispose();
|
||||||
|
|
||||||
|
return rows.ToArray();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
database.Reconnect();
|
||||||
|
MainLog.Instance.Error(e.ToString());
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns a sim profile from it's location
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="handle">Region location handle</param>
|
||||||
|
/// <returns>Sim profile</returns>
|
||||||
|
public RegionProfileData GetProfileByHandle(ulong handle)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
lock (database)
|
||||||
|
{
|
||||||
|
Dictionary<string, string> param = new Dictionary<string, string>();
|
||||||
|
param["?handle"] = handle.ToString();
|
||||||
|
|
||||||
|
IDbCommand result = database.Query("SELECT * FROM regions WHERE regionHandle = ?handle", param);
|
||||||
|
IDataReader reader = result.ExecuteReader();
|
||||||
|
|
||||||
|
RegionProfileData row = database.readSimRow(reader);
|
||||||
|
reader.Close();
|
||||||
|
result.Dispose();
|
||||||
|
|
||||||
|
return row;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
database.Reconnect();
|
||||||
|
MainLog.Instance.Error(e.ToString());
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// // Returns a list of avatar and UUIDs that match the query
|
||||||
|
/// </summary>
|
||||||
|
public List<AvatarPickerAvatar> GeneratePickerResults(LLUUID queryID, string query)
|
||||||
|
{
|
||||||
|
List<AvatarPickerAvatar> returnlist = new List<AvatarPickerAvatar>();
|
||||||
|
|
||||||
|
Regex objAlphaNumericPattern = new Regex("[^a-zA-Z0-9]");
|
||||||
|
|
||||||
|
string[] querysplit;
|
||||||
|
querysplit = query.Split(' ');
|
||||||
|
if (querysplit.Length == 2)
|
||||||
|
{
|
||||||
|
Dictionary<string, string> param = new Dictionary<string, string>();
|
||||||
|
param["?first"] = objAlphaNumericPattern.Replace(querysplit[0], "") + "%";
|
||||||
|
param["?second"] = objAlphaNumericPattern.Replace(querysplit[1], "") + "%";
|
||||||
|
try
|
||||||
|
{
|
||||||
|
lock (database)
|
||||||
|
{
|
||||||
|
IDbCommand result =
|
||||||
|
database.Query(
|
||||||
|
"SELECT UUID,username,surname FROM users WHERE username like ?first AND lastname like ?second LIMIT 100",
|
||||||
|
param);
|
||||||
|
IDataReader reader = result.ExecuteReader();
|
||||||
|
|
||||||
|
|
||||||
|
while (reader.Read())
|
||||||
|
{
|
||||||
|
AvatarPickerAvatar user = new AvatarPickerAvatar();
|
||||||
|
user.AvatarID = new LLUUID((string) reader["UUID"]);
|
||||||
|
user.firstName = (string) reader["username"];
|
||||||
|
user.lastName = (string) reader["surname"];
|
||||||
|
returnlist.Add(user);
|
||||||
|
}
|
||||||
|
reader.Close();
|
||||||
|
result.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
database.Reconnect();
|
||||||
|
MainLog.Instance.Error(e.ToString());
|
||||||
|
return returnlist;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (querysplit.Length == 1)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
lock (database)
|
||||||
|
{
|
||||||
|
Dictionary<string, string> param = new Dictionary<string, string>();
|
||||||
|
param["?first"] = objAlphaNumericPattern.Replace(querysplit[0], "") + "%";
|
||||||
|
|
||||||
|
IDbCommand result =
|
||||||
|
database.Query(
|
||||||
|
"SELECT UUID,username,surname FROM users WHERE username like ?first OR lastname like ?second",
|
||||||
|
param);
|
||||||
|
IDataReader reader = result.ExecuteReader();
|
||||||
|
|
||||||
|
|
||||||
|
while (reader.Read())
|
||||||
|
{
|
||||||
|
AvatarPickerAvatar user = new AvatarPickerAvatar();
|
||||||
|
user.AvatarID = new LLUUID((string) reader["UUID"]);
|
||||||
|
user.firstName = (string) reader["username"];
|
||||||
|
user.lastName = (string) reader["surname"];
|
||||||
|
returnlist.Add(user);
|
||||||
|
}
|
||||||
|
reader.Close();
|
||||||
|
result.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
database.Reconnect();
|
||||||
|
MainLog.Instance.Error(e.ToString());
|
||||||
|
return returnlist;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return returnlist;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns a sim profile from it's UUID
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="uuid">The region UUID</param>
|
||||||
|
/// <returns>The sim profile</returns>
|
||||||
|
public RegionProfileData GetProfileByLLUUID(LLUUID uuid)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
lock (database)
|
||||||
|
{
|
||||||
|
Dictionary<string, string> param = new Dictionary<string, string>();
|
||||||
|
param["?uuid"] = uuid.ToString();
|
||||||
|
|
||||||
|
IDbCommand result = database.Query("SELECT * FROM regions WHERE uuid = ?uuid", param);
|
||||||
|
IDataReader reader = result.ExecuteReader();
|
||||||
|
|
||||||
|
RegionProfileData row = database.readSimRow(reader);
|
||||||
|
reader.Close();
|
||||||
|
result.Dispose();
|
||||||
|
|
||||||
|
return row;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
database.Reconnect();
|
||||||
|
MainLog.Instance.Error(e.ToString());
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Adds a new profile to the database
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="profile">The profile to add</param>
|
||||||
|
/// <returns>Successful?</returns>
|
||||||
|
public DataResponse AddProfile(RegionProfileData profile)
|
||||||
|
{
|
||||||
|
lock (database)
|
||||||
|
{
|
||||||
|
if (database.insertRegion(profile))
|
||||||
|
{
|
||||||
|
return DataResponse.RESPONSE_OK;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return DataResponse.RESPONSE_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// DEPRECIATED. Attempts to authenticate a region by comparing a shared secret.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="uuid">The UUID of the challenger</param>
|
||||||
|
/// <param name="handle">The attempted regionHandle of the challenger</param>
|
||||||
|
/// <param name="authkey">The secret</param>
|
||||||
|
/// <returns>Whether the secret and regionhandle match the database entry for UUID</returns>
|
||||||
|
public bool AuthenticateSim(LLUUID uuid, ulong handle, string authkey)
|
||||||
|
{
|
||||||
|
bool throwHissyFit = false; // Should be true by 1.0
|
||||||
|
|
||||||
|
if (throwHissyFit)
|
||||||
|
throw new Exception("CRYPTOWEAK AUTHENTICATE: Refusing to authenticate due to replay potential.");
|
||||||
|
|
||||||
|
RegionProfileData data = GetProfileByLLUUID(uuid);
|
||||||
|
|
||||||
|
return (handle == data.regionHandle && authkey == data.regionSecret);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// NOT YET FUNCTIONAL. Provides a cryptographic authentication of a region
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>This requires a security audit.</remarks>
|
||||||
|
/// <param name="uuid"></param>
|
||||||
|
/// <param name="handle"></param>
|
||||||
|
/// <param name="authhash"></param>
|
||||||
|
/// <param name="challenge"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public bool AuthenticateSim(LLUUID uuid, ulong handle, string authhash, string challenge)
|
||||||
|
{
|
||||||
|
SHA512Managed HashProvider = new SHA512Managed();
|
||||||
|
ASCIIEncoding TextProvider = new ASCIIEncoding();
|
||||||
|
|
||||||
|
byte[] stream = TextProvider.GetBytes(uuid.ToString() + ":" + handle.ToString() + ":" + challenge);
|
||||||
|
byte[] hash = HashProvider.ComputeHash(stream);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ReservationData GetReservationAtPoint(uint x, uint y)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
lock (database)
|
||||||
|
{
|
||||||
|
Dictionary<string, string> param = new Dictionary<string, string>();
|
||||||
|
param["?x"] = x.ToString();
|
||||||
|
param["?y"] = y.ToString();
|
||||||
|
IDbCommand result =
|
||||||
|
database.Query(
|
||||||
|
"SELECT * FROM reservations WHERE resXMin <= ?x AND resXMax >= ?x AND resYMin <= ?y AND resYMax >= ?y",
|
||||||
|
param);
|
||||||
|
IDataReader reader = result.ExecuteReader();
|
||||||
|
|
||||||
|
ReservationData row = database.readReservationRow(reader);
|
||||||
|
reader.Close();
|
||||||
|
result.Dispose();
|
||||||
|
|
||||||
|
return row;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
database.Reconnect();
|
||||||
|
MainLog.Instance.Error(e.ToString());
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,640 @@
|
||||||
|
/*
|
||||||
|
* 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 OpenSim 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 libsecondlife;
|
||||||
|
using MySql.Data.MySqlClient;
|
||||||
|
using OpenSim.Framework.Console;
|
||||||
|
|
||||||
|
namespace OpenSim.Framework.Data.MySQL
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// A MySQL interface for the inventory server
|
||||||
|
/// </summary>
|
||||||
|
public class MySQLInventoryData : IInventoryData
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The database manager
|
||||||
|
/// </summary>
|
||||||
|
private MySQLManager database;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Loads and initialises this database plugin
|
||||||
|
/// </summary>
|
||||||
|
public void Initialise()
|
||||||
|
{
|
||||||
|
IniFile GridDataMySqlFile = new IniFile("mysql_connection.ini");
|
||||||
|
string settingHostname = GridDataMySqlFile.ParseFileReadValue("hostname");
|
||||||
|
string settingDatabase = GridDataMySqlFile.ParseFileReadValue("database");
|
||||||
|
string settingUsername = GridDataMySqlFile.ParseFileReadValue("username");
|
||||||
|
string settingPassword = GridDataMySqlFile.ParseFileReadValue("password");
|
||||||
|
string settingPooling = GridDataMySqlFile.ParseFileReadValue("pooling");
|
||||||
|
string settingPort = GridDataMySqlFile.ParseFileReadValue("port");
|
||||||
|
|
||||||
|
database =
|
||||||
|
new MySQLManager(settingHostname, settingDatabase, settingUsername, settingPassword, settingPooling,
|
||||||
|
settingPort);
|
||||||
|
TestTables(database.Connection);
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Test and initialization code
|
||||||
|
|
||||||
|
private void UpgradeFoldersTable(string oldVersion)
|
||||||
|
{
|
||||||
|
// null as the version, indicates that the table didn't exist
|
||||||
|
if (oldVersion == null)
|
||||||
|
{
|
||||||
|
database.ExecuteResourceSql("CreateFoldersTable.sql");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if the table is already at the current version, then we can exit immediately
|
||||||
|
// if (oldVersion == "Rev. 2")
|
||||||
|
// return;
|
||||||
|
|
||||||
|
// database.ExecuteResourceSql("UpgradeFoldersTableToVersion2.sql");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UpgradeItemsTable(string oldVersion)
|
||||||
|
{
|
||||||
|
// null as the version, indicates that the table didn't exist
|
||||||
|
if (oldVersion == null)
|
||||||
|
{
|
||||||
|
database.ExecuteResourceSql("CreateItemsTable.sql");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if the table is already at the current version, then we can exit immediately
|
||||||
|
// if (oldVersion == "Rev. 2")
|
||||||
|
// return;
|
||||||
|
|
||||||
|
// database.ExecuteResourceSql("UpgradeItemsTableToVersion2.sql");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void TestTables(MySqlConnection conn)
|
||||||
|
{
|
||||||
|
Dictionary<string, string> tableList = new Dictionary<string, string>();
|
||||||
|
|
||||||
|
tableList["inventoryfolders"] = null;
|
||||||
|
tableList["inventoryitems"] = null;
|
||||||
|
|
||||||
|
database.GetTableVersion(tableList);
|
||||||
|
MainLog.Instance.Verbose("MYSQL", "Inventory Folder Version: " + tableList["inventoryfolders"]);
|
||||||
|
MainLog.Instance.Verbose("MYSQL", "Inventory Items Version: " + tableList["inventoryitems"]);
|
||||||
|
|
||||||
|
UpgradeFoldersTable(tableList["inventoryfolders"]);
|
||||||
|
UpgradeItemsTable(tableList["inventoryitems"]);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The name of this DB provider
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>Name of DB provider</returns>
|
||||||
|
public string getName()
|
||||||
|
{
|
||||||
|
return "MySQL Inventory Data Interface";
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Closes this DB provider
|
||||||
|
/// </summary>
|
||||||
|
public void Close()
|
||||||
|
{
|
||||||
|
// Do nothing.
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the version of this DB provider
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>A string containing the DB provider</returns>
|
||||||
|
public string getVersion()
|
||||||
|
{
|
||||||
|
return database.getVersion();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns a list of items in a specified folder
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="folderID">The folder to search</param>
|
||||||
|
/// <returns>A list containing inventory items</returns>
|
||||||
|
public List<InventoryItemBase> getInventoryInFolder(LLUUID folderID)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
lock (database)
|
||||||
|
{
|
||||||
|
List<InventoryItemBase> items = new List<InventoryItemBase>();
|
||||||
|
|
||||||
|
MySqlCommand result =
|
||||||
|
new MySqlCommand("SELECT * FROM inventoryitems WHERE parentFolderID = ?uuid",
|
||||||
|
database.Connection);
|
||||||
|
result.Parameters.AddWithValue("?uuid", folderID.ToString());
|
||||||
|
MySqlDataReader reader = result.ExecuteReader();
|
||||||
|
|
||||||
|
while (reader.Read())
|
||||||
|
items.Add(readInventoryItem(reader));
|
||||||
|
|
||||||
|
reader.Close();
|
||||||
|
result.Dispose();
|
||||||
|
|
||||||
|
return items;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
database.Reconnect();
|
||||||
|
MainLog.Instance.Error(e.ToString());
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns a list of the root folders within a users inventory
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="user">The user whos inventory is to be searched</param>
|
||||||
|
/// <returns>A list of folder objects</returns>
|
||||||
|
public List<InventoryFolderBase> getUserRootFolders(LLUUID user)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
lock (database)
|
||||||
|
{
|
||||||
|
MySqlCommand result =
|
||||||
|
new MySqlCommand(
|
||||||
|
"SELECT * FROM inventoryfolders WHERE parentFolderID = ?zero AND agentID = ?uuid",
|
||||||
|
database.Connection);
|
||||||
|
result.Parameters.AddWithValue("?uuid", user.ToString());
|
||||||
|
result.Parameters.AddWithValue("?zero", LLUUID.Zero.ToString());
|
||||||
|
MySqlDataReader reader = result.ExecuteReader();
|
||||||
|
|
||||||
|
List<InventoryFolderBase> items = new List<InventoryFolderBase>();
|
||||||
|
while (reader.Read())
|
||||||
|
items.Add(readInventoryFolder(reader));
|
||||||
|
|
||||||
|
|
||||||
|
reader.Close();
|
||||||
|
result.Dispose();
|
||||||
|
|
||||||
|
return items;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
database.Reconnect();
|
||||||
|
MainLog.Instance.Error(e.ToString());
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// see InventoryItemBase.getUserRootFolder
|
||||||
|
public InventoryFolderBase getUserRootFolder(LLUUID user)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
lock (database)
|
||||||
|
{
|
||||||
|
MySqlCommand result =
|
||||||
|
new MySqlCommand(
|
||||||
|
"SELECT * FROM inventoryfolders WHERE parentFolderID = ?zero AND agentID = ?uuid",
|
||||||
|
database.Connection);
|
||||||
|
result.Parameters.AddWithValue("?uuid", user.ToString());
|
||||||
|
result.Parameters.AddWithValue("?zero", LLUUID.Zero.ToString());
|
||||||
|
|
||||||
|
MySqlDataReader reader = result.ExecuteReader();
|
||||||
|
|
||||||
|
List<InventoryFolderBase> items = new List<InventoryFolderBase>();
|
||||||
|
while (reader.Read())
|
||||||
|
items.Add(readInventoryFolder(reader));
|
||||||
|
|
||||||
|
InventoryFolderBase rootFolder = null;
|
||||||
|
|
||||||
|
// There should only ever be one root folder for a user. However, if there's more
|
||||||
|
// than one we'll simply use the first one rather than failing. It would be even
|
||||||
|
// nicer to print some message to this effect, but this feels like it's too low a
|
||||||
|
// to put such a message out, and it's too minor right now to spare the time to
|
||||||
|
// suitably refactor.
|
||||||
|
if (items.Count > 0)
|
||||||
|
{
|
||||||
|
rootFolder = items[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
reader.Close();
|
||||||
|
result.Dispose();
|
||||||
|
|
||||||
|
return rootFolder;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
database.Reconnect();
|
||||||
|
MainLog.Instance.Error(e.ToString());
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Return a list of folders in a users inventory contained within the specified folder.
|
||||||
|
/// This method is only used in tests - in normal operation the user always have one,
|
||||||
|
/// and only one, root folder.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="parentID">The folder to search</param>
|
||||||
|
/// <returns>A list of inventory folders</returns>
|
||||||
|
public List<InventoryFolderBase> getInventoryFolders(LLUUID parentID)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
lock (database)
|
||||||
|
{
|
||||||
|
MySqlCommand result =
|
||||||
|
new MySqlCommand("SELECT * FROM inventoryfolders WHERE parentFolderID = ?uuid",
|
||||||
|
database.Connection);
|
||||||
|
result.Parameters.AddWithValue("?uuid", parentID.ToString());
|
||||||
|
MySqlDataReader reader = result.ExecuteReader();
|
||||||
|
|
||||||
|
List<InventoryFolderBase> items = new List<InventoryFolderBase>();
|
||||||
|
|
||||||
|
while (reader.Read())
|
||||||
|
items.Add(readInventoryFolder(reader));
|
||||||
|
|
||||||
|
reader.Close();
|
||||||
|
result.Dispose();
|
||||||
|
|
||||||
|
return items;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
database.Reconnect();
|
||||||
|
MainLog.Instance.Error(e.ToString());
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Reads a one item from an SQL result
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="reader">The SQL Result</param>
|
||||||
|
/// <returns>the item read</returns>
|
||||||
|
private InventoryItemBase readInventoryItem(MySqlDataReader reader)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
InventoryItemBase item = new InventoryItemBase();
|
||||||
|
|
||||||
|
item.inventoryID = new LLUUID((string) reader["inventoryID"]);
|
||||||
|
item.assetID = new LLUUID((string) reader["assetID"]);
|
||||||
|
item.assetType = (int) reader["assetType"];
|
||||||
|
item.parentFolderID = new LLUUID((string) reader["parentFolderID"]);
|
||||||
|
item.avatarID = new LLUUID((string) reader["avatarID"]);
|
||||||
|
item.inventoryName = (string) reader["inventoryName"];
|
||||||
|
item.inventoryDescription = (string) reader["inventoryDescription"];
|
||||||
|
item.inventoryNextPermissions = (uint) reader["inventoryNextPermissions"];
|
||||||
|
item.inventoryCurrentPermissions = (uint) reader["inventoryCurrentPermissions"];
|
||||||
|
item.invType = (int) reader["invType"];
|
||||||
|
item.creatorsID = new LLUUID((string) reader["creatorID"]);
|
||||||
|
item.inventoryBasePermissions = (uint) reader["inventoryBasePermissions"];
|
||||||
|
item.inventoryEveryOnePermissions = (uint) reader["inventoryEveryOnePermissions"];
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
catch (MySqlException e)
|
||||||
|
{
|
||||||
|
MainLog.Instance.Error(e.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns a specified inventory item
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="item">The item to return</param>
|
||||||
|
/// <returns>An inventory item</returns>
|
||||||
|
public InventoryItemBase getInventoryItem(LLUUID itemID)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
lock (database)
|
||||||
|
{
|
||||||
|
Dictionary<string, string> param = new Dictionary<string, string>();
|
||||||
|
|
||||||
|
MySqlCommand result =
|
||||||
|
new MySqlCommand("SELECT * FROM inventoryitems WHERE inventoryID = ?uuid", database.Connection);
|
||||||
|
result.Parameters.AddWithValue("?uuid", itemID.ToString());
|
||||||
|
MySqlDataReader reader = result.ExecuteReader();
|
||||||
|
|
||||||
|
InventoryItemBase item = null;
|
||||||
|
if (reader.Read())
|
||||||
|
item = readInventoryItem(reader);
|
||||||
|
|
||||||
|
reader.Close();
|
||||||
|
result.Dispose();
|
||||||
|
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
database.Reconnect();
|
||||||
|
MainLog.Instance.Error(e.ToString());
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Reads a list of inventory folders returned by a query.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="reader">A MySQL Data Reader</param>
|
||||||
|
/// <returns>A List containing inventory folders</returns>
|
||||||
|
protected InventoryFolderBase readInventoryFolder(MySqlDataReader reader)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
InventoryFolderBase folder = new InventoryFolderBase();
|
||||||
|
folder.agentID = new LLUUID((string) reader["agentID"]);
|
||||||
|
folder.parentID = new LLUUID((string) reader["parentFolderID"]);
|
||||||
|
folder.folderID = new LLUUID((string) reader["folderID"]);
|
||||||
|
folder.name = (string) reader["folderName"];
|
||||||
|
folder.type = (short) reader["type"];
|
||||||
|
folder.version = (ushort) ((int) reader["version"]);
|
||||||
|
return folder;
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
MainLog.Instance.Error(e.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns a specified inventory folder
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="folder">The folder to return</param>
|
||||||
|
/// <returns>A folder class</returns>
|
||||||
|
public InventoryFolderBase getInventoryFolder(LLUUID folderID)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
lock (database)
|
||||||
|
{
|
||||||
|
MySqlCommand result =
|
||||||
|
new MySqlCommand("SELECT * FROM inventoryfolders WHERE folderID = ?uuid", database.Connection);
|
||||||
|
result.Parameters.AddWithValue("?uuid", folderID.ToString());
|
||||||
|
MySqlDataReader reader = result.ExecuteReader();
|
||||||
|
|
||||||
|
reader.Read();
|
||||||
|
InventoryFolderBase folder = readInventoryFolder(reader);
|
||||||
|
reader.Close();
|
||||||
|
result.Dispose();
|
||||||
|
|
||||||
|
return folder;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
database.Reconnect();
|
||||||
|
MainLog.Instance.Error(e.ToString());
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Adds a specified item to the database
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="item">The inventory item</param>
|
||||||
|
public void addInventoryItem(InventoryItemBase item)
|
||||||
|
{
|
||||||
|
string sql =
|
||||||
|
"REPLACE INTO inventoryitems (inventoryID, assetID, assetType, parentFolderID, avatarID, inventoryName, inventoryDescription, inventoryNextPermissions, inventoryCurrentPermissions, invType, creatorID, inventoryBasePermissions, inventoryEveryOnePermissions) VALUES ";
|
||||||
|
sql +=
|
||||||
|
"(?inventoryID, ?assetID, ?assetType, ?parentFolderID, ?avatarID, ?inventoryName, ?inventoryDescription, ?inventoryNextPermissions, ?inventoryCurrentPermissions, ?invType, ?creatorID, ?inventoryBasePermissions, ?inventoryEveryOnePermissions)";
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
MySqlCommand result = new MySqlCommand(sql, database.Connection);
|
||||||
|
result.Parameters.AddWithValue("?inventoryID", item.inventoryID.ToString());
|
||||||
|
result.Parameters.AddWithValue("?assetID", item.assetID.ToString());
|
||||||
|
result.Parameters.AddWithValue("?assetType", item.assetType.ToString());
|
||||||
|
result.Parameters.AddWithValue("?parentFolderID", item.parentFolderID.ToString());
|
||||||
|
result.Parameters.AddWithValue("?avatarID", item.avatarID.ToString());
|
||||||
|
result.Parameters.AddWithValue("?inventoryName", item.inventoryName);
|
||||||
|
result.Parameters.AddWithValue("?inventoryDescription", item.inventoryDescription);
|
||||||
|
result.Parameters.AddWithValue("?inventoryNextPermissions", item.inventoryNextPermissions.ToString());
|
||||||
|
result.Parameters.AddWithValue("?inventoryCurrentPermissions",
|
||||||
|
item.inventoryCurrentPermissions.ToString());
|
||||||
|
result.Parameters.AddWithValue("?invType", item.invType);
|
||||||
|
result.Parameters.AddWithValue("?creatorID", item.creatorsID.ToString());
|
||||||
|
result.Parameters.AddWithValue("?inventoryBasePermissions", item.inventoryBasePermissions);
|
||||||
|
result.Parameters.AddWithValue("?inventoryEveryOnePermissions", item.inventoryEveryOnePermissions);
|
||||||
|
result.ExecuteNonQuery();
|
||||||
|
result.Dispose();
|
||||||
|
}
|
||||||
|
catch (MySqlException e)
|
||||||
|
{
|
||||||
|
MainLog.Instance.Error(e.ToString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Updates the specified inventory item
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="item">Inventory item to update</param>
|
||||||
|
public void updateInventoryItem(InventoryItemBase item)
|
||||||
|
{
|
||||||
|
addInventoryItem(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="item"></param>
|
||||||
|
public void deleteInventoryItem(LLUUID itemID)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
MySqlCommand cmd =
|
||||||
|
new MySqlCommand("DELETE FROM inventoryitems WHERE inventoryID=?uuid", database.Connection);
|
||||||
|
cmd.Parameters.AddWithValue("?uuid", itemID.ToString());
|
||||||
|
cmd.ExecuteNonQuery();
|
||||||
|
}
|
||||||
|
catch (MySqlException e)
|
||||||
|
{
|
||||||
|
database.Reconnect();
|
||||||
|
MainLog.Instance.Error(e.ToString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a new inventory folder
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="folder">Folder to create</param>
|
||||||
|
public void addInventoryFolder(InventoryFolderBase folder)
|
||||||
|
{
|
||||||
|
string sql =
|
||||||
|
"REPLACE INTO inventoryfolders (folderID, agentID, parentFolderID, folderName, type, version) VALUES ";
|
||||||
|
sql += "(?folderID, ?agentID, ?parentFolderID, ?folderName, ?type, ?version)";
|
||||||
|
|
||||||
|
MySqlCommand cmd = new MySqlCommand(sql, database.Connection);
|
||||||
|
cmd.Parameters.AddWithValue("?folderID", folder.folderID.ToString());
|
||||||
|
cmd.Parameters.AddWithValue("?agentID", folder.agentID.ToString());
|
||||||
|
cmd.Parameters.AddWithValue("?parentFolderID", folder.parentID.ToString());
|
||||||
|
cmd.Parameters.AddWithValue("?folderName", folder.name);
|
||||||
|
cmd.Parameters.AddWithValue("?type", (short) folder.type);
|
||||||
|
cmd.Parameters.AddWithValue("?version", folder.version);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
cmd.ExecuteNonQuery();
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
MainLog.Instance.Error(e.ToString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Updates an inventory folder
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="folder">Folder to update</param>
|
||||||
|
public void updateInventoryFolder(InventoryFolderBase folder)
|
||||||
|
{
|
||||||
|
addInventoryFolder(folder);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Creates a new inventory folder
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="folder">Folder to create</param>
|
||||||
|
public void moveInventoryFolder(InventoryFolderBase folder)
|
||||||
|
{
|
||||||
|
string sql =
|
||||||
|
"UPDATE inventoryfolders SET parentFolderID=?parentFolderID WHERE folderID=?folderID";
|
||||||
|
|
||||||
|
MySqlCommand cmd = new MySqlCommand(sql, database.Connection);
|
||||||
|
cmd.Parameters.AddWithValue("?folderID", folder.folderID.ToString());
|
||||||
|
cmd.Parameters.AddWithValue("?parentFolderID", folder.parentID.ToString());
|
||||||
|
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
cmd.ExecuteNonQuery();
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
MainLog.Instance.Error(e.ToString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Append a list of all the child folders of a parent folder
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="folders">list where folders will be appended</param>
|
||||||
|
/// <param name="parentID">ID of parent</param>
|
||||||
|
protected void getInventoryFolders(ref List<InventoryFolderBase> folders, LLUUID parentID)
|
||||||
|
{
|
||||||
|
List<InventoryFolderBase> subfolderList = getInventoryFolders(parentID);
|
||||||
|
|
||||||
|
foreach (InventoryFolderBase f in subfolderList)
|
||||||
|
folders.Add(f);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns all child folders in the hierarchy from the parent folder and down
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="parentID">The folder to get subfolders for</param>
|
||||||
|
/// <returns>A list of inventory folders</returns>
|
||||||
|
protected List<InventoryFolderBase> getFolderHierarchy(LLUUID parentID)
|
||||||
|
{
|
||||||
|
List<InventoryFolderBase> folders = new List<InventoryFolderBase>();
|
||||||
|
getInventoryFolders(ref folders, parentID);
|
||||||
|
|
||||||
|
for (int i = 0; i < folders.Count; i++)
|
||||||
|
getInventoryFolders(ref folders, folders[i].folderID);
|
||||||
|
|
||||||
|
return folders;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void deleteOneFolder(LLUUID folderID)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
MySqlCommand cmd =
|
||||||
|
new MySqlCommand("DELETE FROM inventoryfolders WHERE folderID=?uuid", database.Connection);
|
||||||
|
cmd.Parameters.AddWithValue("?uuid", folderID.ToString());
|
||||||
|
cmd.ExecuteNonQuery();
|
||||||
|
}
|
||||||
|
catch (MySqlException e)
|
||||||
|
{
|
||||||
|
database.Reconnect();
|
||||||
|
MainLog.Instance.Error(e.ToString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void deleteItemsInFolder(LLUUID folderID)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
MySqlCommand cmd =
|
||||||
|
new MySqlCommand("DELETE FROM inventoryitems WHERE parentFolderID=?uuid", database.Connection);
|
||||||
|
cmd.Parameters.AddWithValue("?uuid", folderID.ToString());
|
||||||
|
cmd.ExecuteNonQuery();
|
||||||
|
}
|
||||||
|
catch (MySqlException e)
|
||||||
|
{
|
||||||
|
database.Reconnect();
|
||||||
|
MainLog.Instance.Error(e.ToString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Delete an inventory folder
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="folderId">Id of folder to delete</param>
|
||||||
|
public void deleteInventoryFolder(LLUUID folderID)
|
||||||
|
{
|
||||||
|
lock (database)
|
||||||
|
{
|
||||||
|
List<InventoryFolderBase> subFolders = getFolderHierarchy(folderID);
|
||||||
|
|
||||||
|
//Delete all sub-folders
|
||||||
|
foreach (InventoryFolderBase f in subFolders)
|
||||||
|
{
|
||||||
|
deleteOneFolder(f.folderID);
|
||||||
|
deleteItemsInFolder(f.folderID);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Delete the actual row
|
||||||
|
deleteOneFolder(folderID);
|
||||||
|
deleteItemsInFolder(folderID);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,106 @@
|
||||||
|
/*
|
||||||
|
* 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 OpenSim 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.Data.MySQL
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// An interface to the log database for MySQL
|
||||||
|
/// </summary>
|
||||||
|
internal class MySQLLogData : ILogData
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The database manager
|
||||||
|
/// </summary>
|
||||||
|
public MySQLManager database;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Artificial constructor called when the plugin is loaded
|
||||||
|
/// </summary>
|
||||||
|
public void Initialise()
|
||||||
|
{
|
||||||
|
IniFile GridDataMySqlFile = new IniFile("mysql_connection.ini");
|
||||||
|
string settingHostname = GridDataMySqlFile.ParseFileReadValue("hostname");
|
||||||
|
string settingDatabase = GridDataMySqlFile.ParseFileReadValue("database");
|
||||||
|
string settingUsername = GridDataMySqlFile.ParseFileReadValue("username");
|
||||||
|
string settingPassword = GridDataMySqlFile.ParseFileReadValue("password");
|
||||||
|
string settingPooling = GridDataMySqlFile.ParseFileReadValue("pooling");
|
||||||
|
string settingPort = GridDataMySqlFile.ParseFileReadValue("port");
|
||||||
|
|
||||||
|
database =
|
||||||
|
new MySQLManager(settingHostname, settingDatabase, settingUsername, settingPassword, settingPooling,
|
||||||
|
settingPort);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Saves a log item to the database
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="serverDaemon">The daemon triggering the event</param>
|
||||||
|
/// <param name="target">The target of the action (region / agent UUID, etc)</param>
|
||||||
|
/// <param name="methodCall">The method call where the problem occured</param>
|
||||||
|
/// <param name="arguments">The arguments passed to the method</param>
|
||||||
|
/// <param name="priority">How critical is this?</param>
|
||||||
|
/// <param name="logMessage">The message to log</param>
|
||||||
|
public void saveLog(string serverDaemon, string target, string methodCall, string arguments, int priority,
|
||||||
|
string logMessage)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
database.insertLogRow(serverDaemon, target, methodCall, arguments, priority, logMessage);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
database.Reconnect();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the name of this DB provider
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>A string containing the DB provider name</returns>
|
||||||
|
public string getName()
|
||||||
|
{
|
||||||
|
return "MySQL Logdata Interface";
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Closes the database provider
|
||||||
|
/// </summary>
|
||||||
|
public void Close()
|
||||||
|
{
|
||||||
|
// Do nothing.
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the version of this DB provider
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>A string containing the provider version</returns>
|
||||||
|
public string getVersion()
|
||||||
|
{
|
||||||
|
return "0.1";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,690 @@
|
||||||
|
/*
|
||||||
|
* 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 OpenSim 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.Data;
|
||||||
|
using System.IO;
|
||||||
|
using System.Reflection;
|
||||||
|
using libsecondlife;
|
||||||
|
using MySql.Data.MySqlClient;
|
||||||
|
using OpenSim.Framework.Console;
|
||||||
|
|
||||||
|
namespace OpenSim.Framework.Data.MySQL
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// A MySQL Database manager
|
||||||
|
/// </summary>
|
||||||
|
internal class MySQLManager
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The database connection object
|
||||||
|
/// </summary>
|
||||||
|
private MySqlConnection dbcon;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Connection string for ADO.net
|
||||||
|
/// </summary>
|
||||||
|
private string connectionString;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initialises and creates a new MySQL connection and maintains it.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="hostname">The MySQL server being connected to</param>
|
||||||
|
/// <param name="database">The name of the MySQL database being used</param>
|
||||||
|
/// <param name="username">The username logging into the database</param>
|
||||||
|
/// <param name="password">The password for the user logging in</param>
|
||||||
|
/// <param name="cpooling">Whether to use connection pooling or not, can be one of the following: 'yes', 'true', 'no' or 'false', if unsure use 'false'.</param>
|
||||||
|
public MySQLManager(string hostname, string database, string username, string password, string cpooling,
|
||||||
|
string port)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
connectionString = "Server=" + hostname + ";Port=" + port + ";Database=" + database + ";User ID=" +
|
||||||
|
username + ";Password=" + password + ";Pooling=" + cpooling + ";";
|
||||||
|
dbcon = new MySqlConnection(connectionString);
|
||||||
|
|
||||||
|
dbcon.Open();
|
||||||
|
|
||||||
|
MainLog.Instance.Verbose("MYSQL", "Connection established");
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
throw new Exception("Error initialising MySql Database: " + e.ToString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the connection being used
|
||||||
|
/// </summary>
|
||||||
|
public MySqlConnection Connection
|
||||||
|
{
|
||||||
|
get { return dbcon; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Shuts down the database connection
|
||||||
|
/// </summary>
|
||||||
|
public void Close()
|
||||||
|
{
|
||||||
|
dbcon.Close();
|
||||||
|
dbcon = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Reconnects to the database
|
||||||
|
/// </summary>
|
||||||
|
public void Reconnect()
|
||||||
|
{
|
||||||
|
lock (dbcon)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// Close the DB connection
|
||||||
|
dbcon.Close();
|
||||||
|
// Try reopen it
|
||||||
|
dbcon = new MySqlConnection(connectionString);
|
||||||
|
dbcon.Open();
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
MainLog.Instance.Error("Unable to reconnect to database " + e.ToString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the version of this DB provider
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>A string containing the DB provider</returns>
|
||||||
|
public string getVersion()
|
||||||
|
{
|
||||||
|
Module module = GetType().Module;
|
||||||
|
string dllName = module.Assembly.ManifestModule.Name;
|
||||||
|
Version dllVersion = module.Assembly.GetName().Version;
|
||||||
|
|
||||||
|
|
||||||
|
return
|
||||||
|
string.Format("{0}.{1}.{2}.{3}", dllVersion.Major, dllVersion.Minor, dllVersion.Build,
|
||||||
|
dllVersion.Revision);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Extract a named string resource from the embedded resources
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="name">name of embedded resource</param>
|
||||||
|
/// <returns>string contained within the embedded resource</returns>
|
||||||
|
private string getResourceString(string name)
|
||||||
|
{
|
||||||
|
Assembly assem = GetType().Assembly;
|
||||||
|
string[] names = assem.GetManifestResourceNames();
|
||||||
|
|
||||||
|
foreach (string s in names)
|
||||||
|
if (s.EndsWith(name))
|
||||||
|
using (Stream resource = assem.GetManifestResourceStream(s))
|
||||||
|
{
|
||||||
|
using (StreamReader resourceReader = new StreamReader(resource))
|
||||||
|
{
|
||||||
|
string resourceString = resourceReader.ReadToEnd();
|
||||||
|
return resourceString;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new Exception(string.Format("Resource '{0}' was not found", name));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Execute a SQL statement stored in a resource, as a string
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="name"></param>
|
||||||
|
public void ExecuteResourceSql(string name)
|
||||||
|
{
|
||||||
|
MySqlCommand cmd = new MySqlCommand(getResourceString(name), dbcon);
|
||||||
|
cmd.ExecuteNonQuery();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Given a list of tables, return the version of the tables, as seen in the database
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="tableList"></param>
|
||||||
|
public void GetTableVersion(Dictionary<string, string> tableList)
|
||||||
|
{
|
||||||
|
lock (dbcon)
|
||||||
|
{
|
||||||
|
MySqlCommand tablesCmd =
|
||||||
|
new MySqlCommand(
|
||||||
|
"SELECT TABLE_NAME, TABLE_COMMENT FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA=?dbname",
|
||||||
|
dbcon);
|
||||||
|
tablesCmd.Parameters.AddWithValue("?dbname", dbcon.Database);
|
||||||
|
using (MySqlDataReader tables = tablesCmd.ExecuteReader())
|
||||||
|
{
|
||||||
|
while (tables.Read())
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
string tableName = (string) tables["TABLE_NAME"];
|
||||||
|
string comment = (string) tables["TABLE_COMMENT"];
|
||||||
|
if (tableList.ContainsKey(tableName))
|
||||||
|
tableList[tableName] = comment;
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
MainLog.Instance.Error(e.ToString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tables.Close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// at some time this code should be cleaned up
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Runs a query with protection against SQL Injection by using parameterised input.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="sql">The SQL string - replace any variables such as WHERE x = "y" with WHERE x = @y</param>
|
||||||
|
/// <param name="parameters">The parameters - index so that @y is indexed as 'y'</param>
|
||||||
|
/// <returns>A MySQL DB Command</returns>
|
||||||
|
public IDbCommand Query(string sql, Dictionary<string, string> parameters)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
MySqlCommand dbcommand = (MySqlCommand) dbcon.CreateCommand();
|
||||||
|
dbcommand.CommandText = sql;
|
||||||
|
foreach (KeyValuePair<string, string> param in parameters)
|
||||||
|
{
|
||||||
|
dbcommand.Parameters.AddWithValue(param.Key, param.Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (IDbCommand) dbcommand;
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
lock (dbcon)
|
||||||
|
{
|
||||||
|
// Close the DB connection
|
||||||
|
try
|
||||||
|
{
|
||||||
|
dbcon.Close();
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try reopen it
|
||||||
|
try
|
||||||
|
{
|
||||||
|
dbcon = new MySqlConnection(connectionString);
|
||||||
|
dbcon.Open();
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
MainLog.Instance.Error("Unable to reconnect to database " + e.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Run the query again
|
||||||
|
try
|
||||||
|
{
|
||||||
|
MySqlCommand dbcommand = (MySqlCommand) dbcon.CreateCommand();
|
||||||
|
dbcommand.CommandText = sql;
|
||||||
|
foreach (KeyValuePair<string, string> param in parameters)
|
||||||
|
{
|
||||||
|
dbcommand.Parameters.AddWithValue(param.Key, param.Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (IDbCommand) dbcommand;
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
// Return null if it fails.
|
||||||
|
MainLog.Instance.Error("Failed during Query generation: " + e.ToString());
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Reads a region row from a database reader
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="reader">An active database reader</param>
|
||||||
|
/// <returns>A region profile</returns>
|
||||||
|
public RegionProfileData readSimRow(IDataReader reader)
|
||||||
|
{
|
||||||
|
RegionProfileData retval = new RegionProfileData();
|
||||||
|
|
||||||
|
if (reader.Read())
|
||||||
|
{
|
||||||
|
// Region Main
|
||||||
|
retval.regionHandle = Convert.ToUInt64(reader["regionHandle"].ToString());
|
||||||
|
retval.regionName = (string) reader["regionName"];
|
||||||
|
retval.UUID = new LLUUID((string) reader["uuid"]);
|
||||||
|
|
||||||
|
// Secrets
|
||||||
|
retval.regionRecvKey = (string) reader["regionRecvKey"];
|
||||||
|
retval.regionSecret = (string) reader["regionSecret"];
|
||||||
|
retval.regionSendKey = (string) reader["regionSendKey"];
|
||||||
|
|
||||||
|
// Region Server
|
||||||
|
retval.regionDataURI = (string) reader["regionDataURI"];
|
||||||
|
retval.regionOnline = false; // Needs to be pinged before this can be set.
|
||||||
|
retval.serverIP = (string) reader["serverIP"];
|
||||||
|
retval.serverPort = uint.Parse(reader["serverPort"].ToString());
|
||||||
|
//retval.serverPort = (uint) reader["serverPort"]; // this caused exceptions
|
||||||
|
retval.serverURI = (string) reader["serverURI"];
|
||||||
|
retval.httpPort = Convert.ToUInt32(reader["serverHttpPort"].ToString());
|
||||||
|
retval.remotingPort = Convert.ToUInt32(reader["serverRemotingPort"].ToString());
|
||||||
|
|
||||||
|
// Location
|
||||||
|
retval.regionLocX = Convert.ToUInt32(reader["locX"].ToString());
|
||||||
|
retval.regionLocY = Convert.ToUInt32(reader["locY"].ToString());
|
||||||
|
retval.regionLocZ = Convert.ToUInt32(reader["locZ"].ToString());
|
||||||
|
|
||||||
|
// Neighbours - 0 = No Override
|
||||||
|
retval.regionEastOverrideHandle = Convert.ToUInt64(reader["eastOverrideHandle"].ToString());
|
||||||
|
retval.regionWestOverrideHandle = Convert.ToUInt64(reader["westOverrideHandle"].ToString());
|
||||||
|
retval.regionSouthOverrideHandle = Convert.ToUInt64(reader["southOverrideHandle"].ToString());
|
||||||
|
retval.regionNorthOverrideHandle = Convert.ToUInt64(reader["northOverrideHandle"].ToString());
|
||||||
|
|
||||||
|
// Assets
|
||||||
|
retval.regionAssetURI = (string) reader["regionAssetURI"];
|
||||||
|
retval.regionAssetRecvKey = (string) reader["regionAssetRecvKey"];
|
||||||
|
retval.regionAssetSendKey = (string) reader["regionAssetSendKey"];
|
||||||
|
|
||||||
|
// Userserver
|
||||||
|
retval.regionUserURI = (string) reader["regionUserURI"];
|
||||||
|
retval.regionUserRecvKey = (string) reader["regionUserRecvKey"];
|
||||||
|
retval.regionUserSendKey = (string) reader["regionUserSendKey"];
|
||||||
|
|
||||||
|
// World Map Addition
|
||||||
|
string tempRegionMap = reader["regionMapTexture"].ToString();
|
||||||
|
if (tempRegionMap != "")
|
||||||
|
{
|
||||||
|
retval.regionMapTextureID = new LLUUID(tempRegionMap);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
retval.regionMapTextureID = LLUUID.Zero;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Reads a reservation row from a database reader
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="reader">An active database reader</param>
|
||||||
|
/// <returns>A reservation data object</returns>
|
||||||
|
public ReservationData readReservationRow(IDataReader reader)
|
||||||
|
{
|
||||||
|
ReservationData retval = new ReservationData();
|
||||||
|
if (reader.Read())
|
||||||
|
{
|
||||||
|
retval.gridRecvKey = (string) reader["gridRecvKey"];
|
||||||
|
retval.gridSendKey = (string) reader["gridSendKey"];
|
||||||
|
retval.reservationCompany = (string) reader["resCompany"];
|
||||||
|
retval.reservationMaxX = Convert.ToInt32(reader["resXMax"].ToString());
|
||||||
|
retval.reservationMaxY = Convert.ToInt32(reader["resYMax"].ToString());
|
||||||
|
retval.reservationMinX = Convert.ToInt32(reader["resXMin"].ToString());
|
||||||
|
retval.reservationMinY = Convert.ToInt32(reader["resYMin"].ToString());
|
||||||
|
retval.reservationName = (string) reader["resName"];
|
||||||
|
retval.status = Convert.ToInt32(reader["status"].ToString()) == 1;
|
||||||
|
retval.userUUID = new LLUUID((string) reader["userUUID"]);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Reads an agent row from a database reader
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="reader">An active database reader</param>
|
||||||
|
/// <returns>A user session agent</returns>
|
||||||
|
public UserAgentData readAgentRow(IDataReader reader)
|
||||||
|
{
|
||||||
|
UserAgentData retval = new UserAgentData();
|
||||||
|
|
||||||
|
if (reader.Read())
|
||||||
|
{
|
||||||
|
// Agent IDs
|
||||||
|
retval.UUID = new LLUUID((string) reader["UUID"]);
|
||||||
|
retval.sessionID = new LLUUID((string) reader["sessionID"]);
|
||||||
|
retval.secureSessionID = new LLUUID((string) reader["secureSessionID"]);
|
||||||
|
|
||||||
|
// Agent Who?
|
||||||
|
retval.agentIP = (string) reader["agentIP"];
|
||||||
|
retval.agentPort = Convert.ToUInt32(reader["agentPort"].ToString());
|
||||||
|
retval.agentOnline = Convert.ToBoolean(reader["agentOnline"].ToString());
|
||||||
|
|
||||||
|
// Login/Logout times (UNIX Epoch)
|
||||||
|
retval.loginTime = Convert.ToInt32(reader["loginTime"].ToString());
|
||||||
|
retval.logoutTime = Convert.ToInt32(reader["logoutTime"].ToString());
|
||||||
|
|
||||||
|
// Current position
|
||||||
|
retval.currentRegion = (string) reader["currentRegion"];
|
||||||
|
retval.currentHandle = Convert.ToUInt64(reader["currentHandle"].ToString());
|
||||||
|
LLVector3.TryParse((string) reader["currentPos"], out retval.currentPos);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Reads a user profile from an active data reader
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="reader">An active database reader</param>
|
||||||
|
/// <returns>A user profile</returns>
|
||||||
|
public UserProfileData readUserRow(IDataReader reader)
|
||||||
|
{
|
||||||
|
UserProfileData retval = new UserProfileData();
|
||||||
|
|
||||||
|
if (reader.Read())
|
||||||
|
{
|
||||||
|
retval.UUID = new LLUUID((string) reader["UUID"]);
|
||||||
|
retval.username = (string) reader["username"];
|
||||||
|
retval.surname = (string) reader["lastname"];
|
||||||
|
|
||||||
|
retval.passwordHash = (string) reader["passwordHash"];
|
||||||
|
retval.passwordSalt = (string) reader["passwordSalt"];
|
||||||
|
|
||||||
|
retval.homeRegion = Convert.ToUInt64(reader["homeRegion"].ToString());
|
||||||
|
retval.homeLocation = new LLVector3(
|
||||||
|
Convert.ToSingle(reader["homeLocationX"].ToString()),
|
||||||
|
Convert.ToSingle(reader["homeLocationY"].ToString()),
|
||||||
|
Convert.ToSingle(reader["homeLocationZ"].ToString()));
|
||||||
|
retval.homeLookAt = new LLVector3(
|
||||||
|
Convert.ToSingle(reader["homeLookAtX"].ToString()),
|
||||||
|
Convert.ToSingle(reader["homeLookAtY"].ToString()),
|
||||||
|
Convert.ToSingle(reader["homeLookAtZ"].ToString()));
|
||||||
|
|
||||||
|
retval.created = Convert.ToInt32(reader["created"].ToString());
|
||||||
|
retval.lastLogin = Convert.ToInt32(reader["lastLogin"].ToString());
|
||||||
|
|
||||||
|
retval.userInventoryURI = (string) reader["userInventoryURI"];
|
||||||
|
retval.userAssetURI = (string) reader["userAssetURI"];
|
||||||
|
|
||||||
|
retval.profileCanDoMask = Convert.ToUInt32(reader["profileCanDoMask"].ToString());
|
||||||
|
retval.profileWantDoMask = Convert.ToUInt32(reader["profileWantDoMask"].ToString());
|
||||||
|
|
||||||
|
retval.profileAboutText = (string) reader["profileAboutText"];
|
||||||
|
retval.profileFirstText = (string) reader["profileFirstText"];
|
||||||
|
|
||||||
|
retval.profileImage = new LLUUID((string) reader["profileImage"]);
|
||||||
|
retval.profileFirstImage = new LLUUID((string) reader["profileFirstImage"]);
|
||||||
|
retval.webLoginKey = new LLUUID((string)reader["webLoginKey"]);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Inserts a new row into the log database
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="serverDaemon">The daemon which triggered this event</param>
|
||||||
|
/// <param name="target">Who were we operating on when this occured (region UUID, user UUID, etc)</param>
|
||||||
|
/// <param name="methodCall">The method call where the problem occured</param>
|
||||||
|
/// <param name="arguments">The arguments passed to the method</param>
|
||||||
|
/// <param name="priority">How critical is this?</param>
|
||||||
|
/// <param name="logMessage">Extra message info</param>
|
||||||
|
/// <returns>Saved successfully?</returns>
|
||||||
|
public bool insertLogRow(string serverDaemon, string target, string methodCall, string arguments, int priority,
|
||||||
|
string logMessage)
|
||||||
|
{
|
||||||
|
string sql = "INSERT INTO logs (`target`, `server`, `method`, `arguments`, `priority`, `message`) VALUES ";
|
||||||
|
sql += "(?target, ?server, ?method, ?arguments, ?priority, ?message)";
|
||||||
|
|
||||||
|
Dictionary<string, string> parameters = new Dictionary<string, string>();
|
||||||
|
parameters["?server"] = serverDaemon;
|
||||||
|
parameters["?target"] = target;
|
||||||
|
parameters["?method"] = methodCall;
|
||||||
|
parameters["?arguments"] = arguments;
|
||||||
|
parameters["?priority"] = priority.ToString();
|
||||||
|
parameters["?message"] = logMessage;
|
||||||
|
|
||||||
|
bool returnval = false;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
IDbCommand result = Query(sql, parameters);
|
||||||
|
|
||||||
|
if (result.ExecuteNonQuery() == 1)
|
||||||
|
returnval = true;
|
||||||
|
|
||||||
|
result.Dispose();
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
MainLog.Instance.Error(e.ToString());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return returnval;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a new user and inserts it into the database
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="uuid">User ID</param>
|
||||||
|
/// <param name="username">First part of the login</param>
|
||||||
|
/// <param name="lastname">Second part of the login</param>
|
||||||
|
/// <param name="passwordHash">A salted hash of the users password</param>
|
||||||
|
/// <param name="passwordSalt">The salt used for the password hash</param>
|
||||||
|
/// <param name="homeRegion">A regionHandle of the users home region</param>
|
||||||
|
/// <param name="homeLocX">Home region position vector</param>
|
||||||
|
/// <param name="homeLocY">Home region position vector</param>
|
||||||
|
/// <param name="homeLocZ">Home region position vector</param>
|
||||||
|
/// <param name="homeLookAtX">Home region 'look at' vector</param>
|
||||||
|
/// <param name="homeLookAtY">Home region 'look at' vector</param>
|
||||||
|
/// <param name="homeLookAtZ">Home region 'look at' vector</param>
|
||||||
|
/// <param name="created">Account created (unix timestamp)</param>
|
||||||
|
/// <param name="lastlogin">Last login (unix timestamp)</param>
|
||||||
|
/// <param name="inventoryURI">Users inventory URI</param>
|
||||||
|
/// <param name="assetURI">Users asset URI</param>
|
||||||
|
/// <param name="canDoMask">I can do mask</param>
|
||||||
|
/// <param name="wantDoMask">I want to do mask</param>
|
||||||
|
/// <param name="aboutText">Profile text</param>
|
||||||
|
/// <param name="firstText">Firstlife text</param>
|
||||||
|
/// <param name="profileImage">UUID for profile image</param>
|
||||||
|
/// <param name="firstImage">UUID for firstlife image</param>
|
||||||
|
/// <returns>Success?</returns>
|
||||||
|
public bool insertUserRow(LLUUID uuid, string username, string lastname, string passwordHash,
|
||||||
|
string passwordSalt, UInt64 homeRegion, float homeLocX, float homeLocY, float homeLocZ,
|
||||||
|
float homeLookAtX, float homeLookAtY, float homeLookAtZ, int created, int lastlogin,
|
||||||
|
string inventoryURI, string assetURI, uint canDoMask, uint wantDoMask,
|
||||||
|
string aboutText, string firstText,
|
||||||
|
LLUUID profileImage, LLUUID firstImage, LLUUID webLoginKey)
|
||||||
|
{
|
||||||
|
string sql =
|
||||||
|
"INSERT INTO users (`UUID`, `username`, `lastname`, `passwordHash`, `passwordSalt`, `homeRegion`, ";
|
||||||
|
sql +=
|
||||||
|
"`homeLocationX`, `homeLocationY`, `homeLocationZ`, `homeLookAtX`, `homeLookAtY`, `homeLookAtZ`, `created`, ";
|
||||||
|
sql +=
|
||||||
|
"`lastLogin`, `userInventoryURI`, `userAssetURI`, `profileCanDoMask`, `profileWantDoMask`, `profileAboutText`, ";
|
||||||
|
sql += "`profileFirstText`, `profileImage`, `profileFirstImage`, `webLoginKey`) VALUES ";
|
||||||
|
|
||||||
|
sql += "(?UUID, ?username, ?lastname, ?passwordHash, ?passwordSalt, ?homeRegion, ";
|
||||||
|
sql +=
|
||||||
|
"?homeLocationX, ?homeLocationY, ?homeLocationZ, ?homeLookAtX, ?homeLookAtY, ?homeLookAtZ, ?created, ";
|
||||||
|
sql +=
|
||||||
|
"?lastLogin, ?userInventoryURI, ?userAssetURI, ?profileCanDoMask, ?profileWantDoMask, ?profileAboutText, ";
|
||||||
|
sql += "?profileFirstText, ?profileImage, ?profileFirstImage, ?webLoginKey)";
|
||||||
|
|
||||||
|
Dictionary<string, string> parameters = new Dictionary<string, string>();
|
||||||
|
parameters["?UUID"] = uuid.ToString();
|
||||||
|
parameters["?username"] = username.ToString();
|
||||||
|
parameters["?lastname"] = lastname.ToString();
|
||||||
|
parameters["?passwordHash"] = passwordHash.ToString();
|
||||||
|
parameters["?passwordSalt"] = passwordSalt.ToString();
|
||||||
|
parameters["?homeRegion"] = homeRegion.ToString();
|
||||||
|
parameters["?homeLocationX"] = homeLocX.ToString();
|
||||||
|
parameters["?homeLocationY"] = homeLocY.ToString();
|
||||||
|
parameters["?homeLocationZ"] = homeLocZ.ToString();
|
||||||
|
parameters["?homeLookAtX"] = homeLookAtX.ToString();
|
||||||
|
parameters["?homeLookAtY"] = homeLookAtY.ToString();
|
||||||
|
parameters["?homeLookAtZ"] = homeLookAtZ.ToString();
|
||||||
|
parameters["?created"] = created.ToString();
|
||||||
|
parameters["?lastLogin"] = lastlogin.ToString();
|
||||||
|
parameters["?userInventoryURI"] = "";
|
||||||
|
parameters["?userAssetURI"] = "";
|
||||||
|
parameters["?profileCanDoMask"] = "0";
|
||||||
|
parameters["?profileWantDoMask"] = "0";
|
||||||
|
parameters["?profileAboutText"] = "";
|
||||||
|
parameters["?profileFirstText"] = "";
|
||||||
|
parameters["?profileImage"] = LLUUID.Zero.ToString();
|
||||||
|
parameters["?profileFirstImage"] = LLUUID.Zero.ToString();
|
||||||
|
parameters["?webLoginKey"] = LLUUID.Random().ToString();
|
||||||
|
|
||||||
|
bool returnval = false;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
IDbCommand result = Query(sql, parameters);
|
||||||
|
|
||||||
|
if (result.ExecuteNonQuery() == 1)
|
||||||
|
returnval = true;
|
||||||
|
|
||||||
|
result.Dispose();
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
MainLog.Instance.Error(e.ToString());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return returnval;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Inserts a new region into the database
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="profile">The region to insert</param>
|
||||||
|
/// <returns>Success?</returns>
|
||||||
|
public bool insertRegion(RegionProfileData regiondata)
|
||||||
|
{
|
||||||
|
bool GRID_ONLY_UPDATE_NECESSARY_DATA = false;
|
||||||
|
|
||||||
|
string sql = "";
|
||||||
|
if (GRID_ONLY_UPDATE_NECESSARY_DATA)
|
||||||
|
{
|
||||||
|
sql += "INSERT INTO ";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sql += "REPLACE INTO ";
|
||||||
|
}
|
||||||
|
|
||||||
|
sql += "regions (regionHandle, regionName, uuid, regionRecvKey, regionSecret, regionSendKey, regionDataURI, ";
|
||||||
|
sql +=
|
||||||
|
"serverIP, serverPort, serverURI, locX, locY, locZ, eastOverrideHandle, westOverrideHandle, southOverrideHandle, northOverrideHandle, regionAssetURI, regionAssetRecvKey, ";
|
||||||
|
sql +=
|
||||||
|
"regionAssetSendKey, regionUserURI, regionUserRecvKey, regionUserSendKey, regionMapTexture, serverHttpPort, serverRemotingPort) VALUES ";
|
||||||
|
|
||||||
|
sql += "(?regionHandle, ?regionName, ?uuid, ?regionRecvKey, ?regionSecret, ?regionSendKey, ?regionDataURI, ";
|
||||||
|
sql +=
|
||||||
|
"?serverIP, ?serverPort, ?serverURI, ?locX, ?locY, ?locZ, ?eastOverrideHandle, ?westOverrideHandle, ?southOverrideHandle, ?northOverrideHandle, ?regionAssetURI, ?regionAssetRecvKey, ";
|
||||||
|
sql +=
|
||||||
|
"?regionAssetSendKey, ?regionUserURI, ?regionUserRecvKey, ?regionUserSendKey, ?regionMapTexture, ?serverHttpPort, ?serverRemotingPort)";
|
||||||
|
|
||||||
|
if (GRID_ONLY_UPDATE_NECESSARY_DATA)
|
||||||
|
{
|
||||||
|
sql += "ON DUPLICATE KEY UPDATE serverIP = ?serverIP, serverPort = ?serverPort, serverURI = ?serverURI;";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sql += ";";
|
||||||
|
}
|
||||||
|
|
||||||
|
Dictionary<string, string> parameters = new Dictionary<string, string>();
|
||||||
|
|
||||||
|
parameters["?regionHandle"] = regiondata.regionHandle.ToString();
|
||||||
|
parameters["?regionName"] = regiondata.regionName.ToString();
|
||||||
|
parameters["?uuid"] = regiondata.UUID.ToString();
|
||||||
|
parameters["?regionRecvKey"] = regiondata.regionRecvKey.ToString();
|
||||||
|
parameters["?regionSecret"] = regiondata.regionSecret.ToString();
|
||||||
|
parameters["?regionSendKey"] = regiondata.regionSendKey.ToString();
|
||||||
|
parameters["?regionDataURI"] = regiondata.regionDataURI.ToString();
|
||||||
|
parameters["?serverIP"] = regiondata.serverIP.ToString();
|
||||||
|
parameters["?serverPort"] = regiondata.serverPort.ToString();
|
||||||
|
parameters["?serverURI"] = regiondata.serverURI.ToString();
|
||||||
|
parameters["?locX"] = regiondata.regionLocX.ToString();
|
||||||
|
parameters["?locY"] = regiondata.regionLocY.ToString();
|
||||||
|
parameters["?locZ"] = regiondata.regionLocZ.ToString();
|
||||||
|
parameters["?eastOverrideHandle"] = regiondata.regionEastOverrideHandle.ToString();
|
||||||
|
parameters["?westOverrideHandle"] = regiondata.regionWestOverrideHandle.ToString();
|
||||||
|
parameters["?northOverrideHandle"] = regiondata.regionNorthOverrideHandle.ToString();
|
||||||
|
parameters["?southOverrideHandle"] = regiondata.regionSouthOverrideHandle.ToString();
|
||||||
|
parameters["?regionAssetURI"] = regiondata.regionAssetURI.ToString();
|
||||||
|
parameters["?regionAssetRecvKey"] = regiondata.regionAssetRecvKey.ToString();
|
||||||
|
parameters["?regionAssetSendKey"] = regiondata.regionAssetSendKey.ToString();
|
||||||
|
parameters["?regionUserURI"] = regiondata.regionUserURI.ToString();
|
||||||
|
parameters["?regionUserRecvKey"] = regiondata.regionUserRecvKey.ToString();
|
||||||
|
parameters["?regionUserSendKey"] = regiondata.regionUserSendKey.ToString();
|
||||||
|
parameters["?regionMapTexture"] = regiondata.regionMapTextureID.ToString();
|
||||||
|
parameters["?serverHttpPort"] = regiondata.httpPort.ToString();
|
||||||
|
parameters["?serverRemotingPort"] = regiondata.remotingPort.ToString();
|
||||||
|
bool returnval = false;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
IDbCommand result = Query(sql, parameters);
|
||||||
|
|
||||||
|
//Console.WriteLine(result.CommandText);
|
||||||
|
int x;
|
||||||
|
if ((x = result.ExecuteNonQuery()) > 0)
|
||||||
|
{
|
||||||
|
returnval = true;
|
||||||
|
}
|
||||||
|
result.Dispose();
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
MainLog.Instance.Error(e.ToString());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return returnval;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,626 @@
|
||||||
|
/*
|
||||||
|
* 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 OpenSim 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.Data;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
using libsecondlife;
|
||||||
|
using OpenSim.Framework.Console;
|
||||||
|
|
||||||
|
namespace OpenSim.Framework.Data.MySQL
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// A database interface class to a user profile storage system
|
||||||
|
/// </summary>
|
||||||
|
internal class MySQLUserData : IUserData
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Database manager for MySQL
|
||||||
|
/// </summary>
|
||||||
|
public MySQLManager database;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Loads and initialises the MySQL storage plugin
|
||||||
|
/// </summary>
|
||||||
|
public void Initialise()
|
||||||
|
{
|
||||||
|
// Load from an INI file connection details
|
||||||
|
// TODO: move this to XML?
|
||||||
|
IniFile GridDataMySqlFile = new IniFile("mysql_connection.ini");
|
||||||
|
string settingHostname = GridDataMySqlFile.ParseFileReadValue("hostname");
|
||||||
|
string settingDatabase = GridDataMySqlFile.ParseFileReadValue("database");
|
||||||
|
string settingUsername = GridDataMySqlFile.ParseFileReadValue("username");
|
||||||
|
string settingPassword = GridDataMySqlFile.ParseFileReadValue("password");
|
||||||
|
string settingPooling = GridDataMySqlFile.ParseFileReadValue("pooling");
|
||||||
|
string settingPort = GridDataMySqlFile.ParseFileReadValue("port");
|
||||||
|
|
||||||
|
database =
|
||||||
|
new MySQLManager(settingHostname, settingDatabase, settingUsername, settingPassword, settingPooling,
|
||||||
|
settingPort);
|
||||||
|
|
||||||
|
TestTables();
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Test and initialization code
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Ensure that the user related tables exists and are at the latest version
|
||||||
|
/// </summary>
|
||||||
|
private void TestTables()
|
||||||
|
{
|
||||||
|
Dictionary<string, string> tableList = new Dictionary<string, string>();
|
||||||
|
|
||||||
|
tableList["agents"] = null;
|
||||||
|
tableList["users"] = null;
|
||||||
|
tableList["userfriends"] = null;
|
||||||
|
database.GetTableVersion(tableList);
|
||||||
|
|
||||||
|
UpgradeAgentsTable(tableList["agents"]);
|
||||||
|
UpgradeUsersTable(tableList["users"]);
|
||||||
|
UpgradeFriendsTable(tableList["userfriends"]);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Create or upgrade the table if necessary
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="oldVersion">A null indicates that the table does not
|
||||||
|
/// currently exist</param>
|
||||||
|
private void UpgradeAgentsTable(string oldVersion)
|
||||||
|
{
|
||||||
|
// null as the version, indicates that the table didn't exist
|
||||||
|
if (oldVersion == null)
|
||||||
|
{
|
||||||
|
database.ExecuteResourceSql("CreateAgentsTable.sql");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Create or upgrade the table if necessary
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="oldVersion">A null indicates that the table does not
|
||||||
|
/// currently exist</param>
|
||||||
|
private void UpgradeUsersTable(string oldVersion)
|
||||||
|
{
|
||||||
|
// null as the version, indicates that the table didn't exist
|
||||||
|
if (oldVersion == null)
|
||||||
|
{
|
||||||
|
database.ExecuteResourceSql("CreateUsersTable.sql");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if (oldVersion.Contains("Rev. 1"))
|
||||||
|
{
|
||||||
|
database.ExecuteResourceSql("UpgradeUsersTableToVersion2.sql");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
//MainLog.Instance.Verbose("DB","DBVers:" + oldVersion);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Create or upgrade the table if necessary
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="oldVersion">A null indicates that the table does not
|
||||||
|
/// currently exist</param>
|
||||||
|
private void UpgradeFriendsTable(string oldVersion)
|
||||||
|
{
|
||||||
|
// null as the version, indicates that the table didn't exist
|
||||||
|
if (oldVersion == null)
|
||||||
|
{
|
||||||
|
database.ExecuteResourceSql("CreateUserFriendsTable.sql");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
// see IUserData
|
||||||
|
public UserProfileData GetUserByName(string user, string last)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
lock (database)
|
||||||
|
{
|
||||||
|
Dictionary<string, string> param = new Dictionary<string, string>();
|
||||||
|
param["?first"] = user;
|
||||||
|
param["?second"] = last;
|
||||||
|
|
||||||
|
IDbCommand result =
|
||||||
|
database.Query("SELECT * FROM users WHERE username = ?first AND lastname = ?second", param);
|
||||||
|
IDataReader reader = result.ExecuteReader();
|
||||||
|
|
||||||
|
UserProfileData row = database.readUserRow(reader);
|
||||||
|
|
||||||
|
reader.Close();
|
||||||
|
result.Dispose();
|
||||||
|
return row;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
database.Reconnect();
|
||||||
|
MainLog.Instance.Error(e.ToString());
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#region User Friends List Data
|
||||||
|
|
||||||
|
public void AddNewUserFriend(LLUUID friendlistowner, LLUUID friend, uint perms)
|
||||||
|
{
|
||||||
|
int dtvalue = Util.UnixTimeSinceEpoch();
|
||||||
|
|
||||||
|
Dictionary<string, string> param = new Dictionary<string, string>();
|
||||||
|
param["?ownerID"] = friendlistowner.UUID.ToString();
|
||||||
|
param["?friendID"] = friend.UUID.ToString();
|
||||||
|
param["?friendPerms"] = perms.ToString();
|
||||||
|
param["?datetimestamp"] = dtvalue.ToString();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
lock (database)
|
||||||
|
{
|
||||||
|
IDbCommand adder =
|
||||||
|
database.Query(
|
||||||
|
"INSERT INTO `userfriends` " +
|
||||||
|
"(`ownerID`,`friendID`,`friendPerms`,`datetimestamp`) " +
|
||||||
|
"VALUES " +
|
||||||
|
"(?ownerID,?friendID,?friendPerms,?datetimestamp)",
|
||||||
|
param);
|
||||||
|
adder.ExecuteNonQuery();
|
||||||
|
|
||||||
|
adder =
|
||||||
|
database.Query(
|
||||||
|
"INSERT INTO `userfriends` " +
|
||||||
|
"(`ownerID`,`friendID`,`friendPerms`,`datetimestamp`) " +
|
||||||
|
"VALUES " +
|
||||||
|
"(?friendID,?ownerID,?friendPerms,?datetimestamp)",
|
||||||
|
param);
|
||||||
|
adder.ExecuteNonQuery();
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
database.Reconnect();
|
||||||
|
MainLog.Instance.Error(e.ToString());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RemoveUserFriend(LLUUID friendlistowner, LLUUID friend)
|
||||||
|
{
|
||||||
|
Dictionary<string, string> param = new Dictionary<string, string>();
|
||||||
|
param["?ownerID"] = friendlistowner.UUID.ToString();
|
||||||
|
param["?friendID"] = friend.UUID.ToString();
|
||||||
|
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
lock (database)
|
||||||
|
{
|
||||||
|
IDbCommand updater =
|
||||||
|
database.Query(
|
||||||
|
"delete from userfriends " +
|
||||||
|
"where ownerID = ?ownerID and friendID = ?friendID",
|
||||||
|
param);
|
||||||
|
updater.ExecuteNonQuery();
|
||||||
|
|
||||||
|
updater =
|
||||||
|
database.Query(
|
||||||
|
"delete from userfriends " +
|
||||||
|
"where ownerID = ?friendID and friendID = ?ownerID",
|
||||||
|
param);
|
||||||
|
updater.ExecuteNonQuery();
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
database.Reconnect();
|
||||||
|
MainLog.Instance.Error(e.ToString());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public void UpdateUserFriendPerms(LLUUID friendlistowner, LLUUID friend, uint perms)
|
||||||
|
{
|
||||||
|
Dictionary<string, string> param = new Dictionary<string, string>();
|
||||||
|
param["?ownerID"] = friendlistowner.UUID.ToString();
|
||||||
|
param["?friendID"] = friend.UUID.ToString();
|
||||||
|
param["?friendPerms"] = perms.ToString();
|
||||||
|
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
lock (database)
|
||||||
|
{
|
||||||
|
IDbCommand updater =
|
||||||
|
database.Query(
|
||||||
|
"update userfriends " +
|
||||||
|
"SET friendPerms = ?friendPerms " +
|
||||||
|
"where ownerID = ?ownerID and friendID = ?friendID",
|
||||||
|
param);
|
||||||
|
updater.ExecuteNonQuery();
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
database.Reconnect();
|
||||||
|
MainLog.Instance.Error(e.ToString());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public List<FriendListItem> GetUserFriendList(LLUUID friendlistowner)
|
||||||
|
{
|
||||||
|
List<FriendListItem> Lfli = new List<FriendListItem>();
|
||||||
|
|
||||||
|
Dictionary<string, string> param = new Dictionary<string, string>();
|
||||||
|
param["?ownerID"] = friendlistowner.UUID.ToString();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
lock (database)
|
||||||
|
{
|
||||||
|
//Left Join userfriends to itself
|
||||||
|
IDbCommand result =
|
||||||
|
database.Query(
|
||||||
|
"select a.ownerID,a.friendID,a.friendPerms,b.friendPerms as ownerperms from userfriends as a, userfriends as b" +
|
||||||
|
" where a.ownerID = ?ownerID and b.ownerID = a.friendID and b.friendID = a.ownerID",
|
||||||
|
param);
|
||||||
|
IDataReader reader = result.ExecuteReader();
|
||||||
|
|
||||||
|
|
||||||
|
while (reader.Read())
|
||||||
|
{
|
||||||
|
FriendListItem fli = new FriendListItem();
|
||||||
|
fli.FriendListOwner = new LLUUID((string)reader["ownerID"]);
|
||||||
|
fli.Friend = new LLUUID((string)reader["friendID"]);
|
||||||
|
fli.FriendPerms = (uint)Convert.ToInt32(reader["friendPerms"]);
|
||||||
|
|
||||||
|
// This is not a real column in the database table, it's a joined column from the opposite record
|
||||||
|
fli.FriendListOwnerPerms = (uint)Convert.ToInt32(reader["ownerperms"]);
|
||||||
|
|
||||||
|
Lfli.Add(fli);
|
||||||
|
}
|
||||||
|
reader.Close();
|
||||||
|
result.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
database.Reconnect();
|
||||||
|
MainLog.Instance.Error(e.ToString());
|
||||||
|
return Lfli;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Lfli;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
public void UpdateUserCurrentRegion(LLUUID avatarid, LLUUID regionuuid)
|
||||||
|
{
|
||||||
|
MainLog.Instance.Verbose("USER", "Stub UpdateUserCUrrentRegion called");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void LogOffUser(LLUUID avatarid)
|
||||||
|
{
|
||||||
|
MainLog.Instance.Verbose("USER", "Stub LogOffUser called");
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Framework.AvatarPickerAvatar> GeneratePickerResults(LLUUID queryID, string query)
|
||||||
|
{
|
||||||
|
List<Framework.AvatarPickerAvatar> returnlist = new List<Framework.AvatarPickerAvatar>();
|
||||||
|
|
||||||
|
Regex objAlphaNumericPattern = new Regex("[^a-zA-Z0-9]");
|
||||||
|
|
||||||
|
string[] querysplit;
|
||||||
|
querysplit = query.Split(' ');
|
||||||
|
if (querysplit.Length == 2)
|
||||||
|
{
|
||||||
|
Dictionary<string, string> param = new Dictionary<string, string>();
|
||||||
|
param["?first"] = objAlphaNumericPattern.Replace(querysplit[0], "") + "%";
|
||||||
|
param["?second"] = objAlphaNumericPattern.Replace(querysplit[1], "") + "%";
|
||||||
|
try
|
||||||
|
{
|
||||||
|
lock (database)
|
||||||
|
{
|
||||||
|
IDbCommand result =
|
||||||
|
database.Query(
|
||||||
|
"SELECT UUID,username,lastname FROM users WHERE username like ?first AND lastname like ?second LIMIT 100",
|
||||||
|
param);
|
||||||
|
IDataReader reader = result.ExecuteReader();
|
||||||
|
|
||||||
|
|
||||||
|
while (reader.Read())
|
||||||
|
{
|
||||||
|
Framework.AvatarPickerAvatar user = new Framework.AvatarPickerAvatar();
|
||||||
|
user.AvatarID = new LLUUID((string) reader["UUID"]);
|
||||||
|
user.firstName = (string) reader["username"];
|
||||||
|
user.lastName = (string) reader["lastname"];
|
||||||
|
returnlist.Add(user);
|
||||||
|
}
|
||||||
|
reader.Close();
|
||||||
|
result.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
database.Reconnect();
|
||||||
|
MainLog.Instance.Error(e.ToString());
|
||||||
|
return returnlist;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (querysplit.Length == 1)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
lock (database)
|
||||||
|
{
|
||||||
|
Dictionary<string, string> param = new Dictionary<string, string>();
|
||||||
|
param["?first"] = objAlphaNumericPattern.Replace(querysplit[0], "") + "%";
|
||||||
|
|
||||||
|
IDbCommand result =
|
||||||
|
database.Query(
|
||||||
|
"SELECT UUID,username,lastname FROM users WHERE username like ?first OR lastname like ?first LIMIT 100",
|
||||||
|
param);
|
||||||
|
IDataReader reader = result.ExecuteReader();
|
||||||
|
|
||||||
|
|
||||||
|
while (reader.Read())
|
||||||
|
{
|
||||||
|
Framework.AvatarPickerAvatar user = new Framework.AvatarPickerAvatar();
|
||||||
|
user.AvatarID = new LLUUID((string) reader["UUID"]);
|
||||||
|
user.firstName = (string) reader["username"];
|
||||||
|
user.lastName = (string) reader["lastname"];
|
||||||
|
returnlist.Add(user);
|
||||||
|
}
|
||||||
|
reader.Close();
|
||||||
|
result.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
database.Reconnect();
|
||||||
|
MainLog.Instance.Error(e.ToString());
|
||||||
|
return returnlist;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return returnlist;
|
||||||
|
}
|
||||||
|
|
||||||
|
// see IUserData
|
||||||
|
public UserProfileData GetUserByUUID(LLUUID uuid)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
lock (database)
|
||||||
|
{
|
||||||
|
Dictionary<string, string> param = new Dictionary<string, string>();
|
||||||
|
param["?uuid"] = uuid.ToString();
|
||||||
|
|
||||||
|
IDbCommand result = database.Query("SELECT * FROM users WHERE UUID = ?uuid", param);
|
||||||
|
IDataReader reader = result.ExecuteReader();
|
||||||
|
|
||||||
|
UserProfileData row = database.readUserRow(reader);
|
||||||
|
|
||||||
|
reader.Close();
|
||||||
|
result.Dispose();
|
||||||
|
|
||||||
|
return row;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
database.Reconnect();
|
||||||
|
MainLog.Instance.Error(e.ToString());
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Searches the database for a specified user profile by account
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="uuid">The account</param>
|
||||||
|
/// <returns>The users profile</returns>
|
||||||
|
public UserProfileData GetUserByAccount(string account)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
lock (database)
|
||||||
|
{
|
||||||
|
Dictionary<string, string> param = new Dictionary<string, string>();
|
||||||
|
param["?account"] = account;
|
||||||
|
|
||||||
|
IDbCommand result = database.Query("SELECT * FROM users WHERE account = ?account", param);
|
||||||
|
IDataReader reader = result.ExecuteReader();
|
||||||
|
|
||||||
|
UserProfileData row = database.readUserRow(reader);
|
||||||
|
|
||||||
|
reader.Close();
|
||||||
|
result.Dispose();
|
||||||
|
|
||||||
|
return row;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
database.Reconnect();
|
||||||
|
MainLog.Instance.Error(e.ToString());
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns a user session searching by name
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="name">The account name</param>
|
||||||
|
/// <returns>The users session</returns>
|
||||||
|
public UserAgentData GetAgentByName(string name)
|
||||||
|
{
|
||||||
|
return GetAgentByName(name.Split(' ')[0], name.Split(' ')[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns a user session by account name
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="user">First part of the users account name</param>
|
||||||
|
/// <param name="last">Second part of the users account name</param>
|
||||||
|
/// <returns>The users session</returns>
|
||||||
|
public UserAgentData GetAgentByName(string user, string last)
|
||||||
|
{
|
||||||
|
UserProfileData profile = GetUserByName(user, last);
|
||||||
|
return GetAgentByUUID(profile.UUID);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns an agent session by account UUID
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="uuid">The accounts UUID</param>
|
||||||
|
/// <returns>The users session</returns>
|
||||||
|
public UserAgentData GetAgentByUUID(LLUUID uuid)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
lock (database)
|
||||||
|
{
|
||||||
|
Dictionary<string, string> param = new Dictionary<string, string>();
|
||||||
|
param["?uuid"] = uuid.ToString();
|
||||||
|
|
||||||
|
IDbCommand result = database.Query("SELECT * FROM agents WHERE UUID = ?uuid", param);
|
||||||
|
IDataReader reader = result.ExecuteReader();
|
||||||
|
|
||||||
|
UserAgentData row = database.readAgentRow(reader);
|
||||||
|
|
||||||
|
reader.Close();
|
||||||
|
result.Dispose();
|
||||||
|
|
||||||
|
return row;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
database.Reconnect();
|
||||||
|
MainLog.Instance.Error(e.ToString());
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a new users profile
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="user">The user profile to create</param>
|
||||||
|
public void AddNewUserProfile(UserProfileData user)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
lock (database)
|
||||||
|
{
|
||||||
|
database.insertUserRow(user.UUID, user.username, user.surname, user.passwordHash, user.passwordSalt,
|
||||||
|
user.homeRegion, user.homeLocation.X, user.homeLocation.Y,
|
||||||
|
user.homeLocation.Z,
|
||||||
|
user.homeLookAt.X, user.homeLookAt.Y, user.homeLookAt.Z, user.created,
|
||||||
|
user.lastLogin, user.userInventoryURI, user.userAssetURI,
|
||||||
|
user.profileCanDoMask, user.profileWantDoMask,
|
||||||
|
user.profileAboutText, user.profileFirstText, user.profileImage,
|
||||||
|
user.profileFirstImage, user.webLoginKey);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
database.Reconnect();
|
||||||
|
MainLog.Instance.Error(e.ToString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a new agent
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="agent">The agent to create</param>
|
||||||
|
public void AddNewUserAgent(UserAgentData agent)
|
||||||
|
{
|
||||||
|
// Do nothing.
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Updates a user profile stored in the DB
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="user">The profile data to use to update the DB</param>
|
||||||
|
public bool UpdateUserProfile(UserProfileData user)
|
||||||
|
{
|
||||||
|
// TODO: implement
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Performs a money transfer request between two accounts
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="from">The senders account ID</param>
|
||||||
|
/// <param name="to">The receivers account ID</param>
|
||||||
|
/// <param name="amount">The amount to transfer</param>
|
||||||
|
/// <returns>Success?</returns>
|
||||||
|
public bool MoneyTransferRequest(LLUUID from, LLUUID to, uint amount)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Performs an inventory transfer request between two accounts
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>TODO: Move to inventory server</remarks>
|
||||||
|
/// <param name="from">The senders account ID</param>
|
||||||
|
/// <param name="to">The receivers account ID</param>
|
||||||
|
/// <param name="item">The item to transfer</param>
|
||||||
|
/// <returns>Success?</returns>
|
||||||
|
public bool InventoryTransferRequest(LLUUID from, LLUUID to, LLUUID item)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Database provider name
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>Provider name</returns>
|
||||||
|
public string getName()
|
||||||
|
{
|
||||||
|
return "MySQL Userdata Interface";
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Database provider version
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>provider version</returns>
|
||||||
|
public string GetVersion()
|
||||||
|
{
|
||||||
|
return "0.1";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,38 @@
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
// General Information about an assembly is controlled through the following
|
||||||
|
// set of attributes. Change these attribute values to modify the information
|
||||||
|
// associated with an assembly.
|
||||||
|
|
||||||
|
[assembly : AssemblyTitle("OpenSim.Framework.Data.MySQL")]
|
||||||
|
[assembly : AssemblyDescription("")]
|
||||||
|
[assembly : AssemblyConfiguration("")]
|
||||||
|
[assembly : AssemblyCompany("")]
|
||||||
|
[assembly : AssemblyProduct("OpenSim.Framework.Data.MySQL")]
|
||||||
|
[assembly : AssemblyCopyright("Copyright © 2007")]
|
||||||
|
[assembly : AssemblyTrademark("")]
|
||||||
|
[assembly : AssemblyCulture("")]
|
||||||
|
|
||||||
|
// Setting ComVisible to false makes the types in this assembly not visible
|
||||||
|
// to COM components. If you need to access a type in this assembly from
|
||||||
|
// COM, set the ComVisible attribute to true on that type.
|
||||||
|
|
||||||
|
[assembly : ComVisible(false)]
|
||||||
|
|
||||||
|
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||||
|
|
||||||
|
[assembly : Guid("e49826b2-dcef-41be-a5bd-596733fa3304")]
|
||||||
|
|
||||||
|
// Version information for an assembly consists of the following four values:
|
||||||
|
//
|
||||||
|
// Major Version
|
||||||
|
// Minor Version
|
||||||
|
// Build Number
|
||||||
|
// Revision
|
||||||
|
//
|
||||||
|
// You can specify all the values or you can default the Revision and Build Numbers
|
||||||
|
// by using the '*' as shown below:
|
||||||
|
|
||||||
|
[assembly : AssemblyVersion("1.0.0.0")]
|
||||||
|
[assembly : AssemblyFileVersion("1.0.0.0")]
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue