Merge branch 'master' into careminster
						commit
						cef51cf91b
					
				|  | @ -1,43 +0,0 @@ | ||||||
| /* |  | ||||||
|  * Copyright (c) Contributors, http://opensimulator.org/ |  | ||||||
|  * See CONTRIBUTORS.TXT for a full list of copyright holders. |  | ||||||
|  * |  | ||||||
|  * Redistribution and use in source and binary forms, with or without |  | ||||||
|  * modification, are permitted provided that the following conditions are met: |  | ||||||
|  *     * Redistributions of source code must retain the above copyright |  | ||||||
|  *       notice, this list of conditions and the following disclaimer. |  | ||||||
|  *     * Redistributions in binary form must reproduce the above copyright |  | ||||||
|  *       notice, this list of conditions and the following disclaimer in the |  | ||||||
|  *       documentation and/or other materials provided with the distribution. |  | ||||||
|  *     * Neither the name of the OpenSimulator Project nor the |  | ||||||
|  *       names of its contributors may be used to endorse or promote products |  | ||||||
|  *       derived from this software without specific prior written permission. |  | ||||||
|  * |  | ||||||
|  * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY |  | ||||||
|  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |  | ||||||
|  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |  | ||||||
|  * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY |  | ||||||
|  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |  | ||||||
|  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |  | ||||||
|  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |  | ||||||
|  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |  | ||||||
|  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |  | ||||||
|  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |  | ||||||
|  */ |  | ||||||
| 
 |  | ||||||
| namespace OpenSim.ApplicationPlugins.Rest.Inventory |  | ||||||
| { |  | ||||||
|     /// <summary> |  | ||||||
|     /// This interface represents the boundary between the general purpose |  | ||||||
|     /// REST plugin handling, and the functionally specific handlers. The |  | ||||||
|     /// handler knows only to initialize and terminate all such handlers  |  | ||||||
|     /// that it finds. Implementing this interface identifies the class as |  | ||||||
|     /// a REST handler implementation. |  | ||||||
|     /// </summary> |  | ||||||
| 
 |  | ||||||
|     internal interface IRest |  | ||||||
|     { |  | ||||||
|         void Initialize(); |  | ||||||
|         void Close(); |  | ||||||
|     } |  | ||||||
| } |  | ||||||
|  | @ -1,59 +0,0 @@ | ||||||
| /* |  | ||||||
|  * Copyright (c) Contributors, http://opensimulator.org/ |  | ||||||
|  * See CONTRIBUTORS.TXT for a full list of copyright holders. |  | ||||||
|  * |  | ||||||
|  * Redistribution and use in source and binary forms, with or without |  | ||||||
|  * modification, are permitted provided that the following conditions are met: |  | ||||||
|  *     * Redistributions of source code must retain the above copyright |  | ||||||
|  *       notice, this list of conditions and the following disclaimer. |  | ||||||
|  *     * Redistributions in binary form must reproduce the above copyright |  | ||||||
|  *       notice, this list of conditions and the following disclaimer in the |  | ||||||
|  *       documentation and/or other materials provided with the distribution. |  | ||||||
|  *     * Neither the name of the OpenSimulator Project nor the |  | ||||||
|  *       names of its contributors may be used to endorse or promote products |  | ||||||
|  *       derived from this software without specific prior written permission. |  | ||||||
|  * |  | ||||||
|  * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY |  | ||||||
|  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |  | ||||||
|  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |  | ||||||
|  * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY |  | ||||||
|  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |  | ||||||
|  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |  | ||||||
|  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |  | ||||||
|  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |  | ||||||
|  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |  | ||||||
|  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |  | ||||||
|  */ |  | ||||||
| 
 |  | ||||||
| using OpenSim.Framework.Servers.HttpServer; |  | ||||||
| 
 |  | ||||||
| namespace OpenSim.ApplicationPlugins.Rest.Inventory |  | ||||||
| { |  | ||||||
| 
 |  | ||||||
|     /// <remarks> |  | ||||||
|     /// The handler delegates are not noteworthy. The allocator allows |  | ||||||
|     /// a given handler to optionally subclass the base RequestData |  | ||||||
|     /// structure to carry any locally required per-request state |  | ||||||
|     /// needed. |  | ||||||
|     /// </remarks> |  | ||||||
| 
 |  | ||||||
|     public delegate void        RestMethodHandler(RequestData rdata); |  | ||||||
|     public delegate RequestData RestMethodAllocator(OSHttpRequest request, OSHttpResponse response, string path); |  | ||||||
| 
 |  | ||||||
|     /// <summary> |  | ||||||
|     /// This interface exports the generic plugin-handling services |  | ||||||
|     /// available to each loaded REST services module (IRest implementation) |  | ||||||
|     /// </summary> |  | ||||||
| 
 |  | ||||||
|     internal interface IRestHandler |  | ||||||
|     { |  | ||||||
| 
 |  | ||||||
|         string MsgId     { get; } |  | ||||||
|         string RequestId { get; } |  | ||||||
| 
 |  | ||||||
|         void   AddPathHandler(RestMethodHandler mh, string path, RestMethodAllocator ma); |  | ||||||
|         void AddStreamHandler(string httpMethod, string path, RestMethod method); |  | ||||||
| 
 |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
| } |  | ||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							|  | @ -1,11 +0,0 @@ | ||||||
| <Addin id="OpenSim.ApplicationPlugins.Rest.Inventory" version="0.1"> |  | ||||||
|     <Runtime> |  | ||||||
|         <Import assembly="OpenSim.ApplicationPlugins.Rest.Inventory.dll"/> |  | ||||||
|     </Runtime> |  | ||||||
|     <Dependencies> |  | ||||||
|         <Addin id="OpenSim" version="0.5" /> |  | ||||||
|     </Dependencies> |  | ||||||
|     <Extension path = "/OpenSim/Startup"> |  | ||||||
|         <Plugin id="RestInventory" type="OpenSim.ApplicationPlugins.Rest.Inventory.RestHandler" /> |  | ||||||
|     </Extension> |  | ||||||
| </Addin> |  | ||||||
|  | @ -1,551 +0,0 @@ | ||||||
| /* |  | ||||||
|  * Copyright (c) Contributors, http://opensimulator.org/ |  | ||||||
|  * See CONTRIBUTORS.TXT for a full list of copyright holders. |  | ||||||
|  * |  | ||||||
|  * Redistribution and use in source and binary forms, with or without |  | ||||||
|  * modification, are permitted provided that the following conditions are met: |  | ||||||
|  *     * Redistributions of source code must retain the above copyright |  | ||||||
|  *       notice, this list of conditions and the following disclaimer. |  | ||||||
|  *     * Redistributions in binary form must reproduce the above copyright |  | ||||||
|  *       notice, this list of conditions and the following disclaimer in the |  | ||||||
|  *       documentation and/or other materials provided with the distribution. |  | ||||||
|  *     * Neither the name of the OpenSimulator Project nor the |  | ||||||
|  *       names of its contributors may be used to endorse or promote products |  | ||||||
|  *       derived from this software without specific prior written permission. |  | ||||||
|  * |  | ||||||
|  * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY |  | ||||||
|  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |  | ||||||
|  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |  | ||||||
|  * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY |  | ||||||
|  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |  | ||||||
|  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |  | ||||||
|  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |  | ||||||
|  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |  | ||||||
|  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |  | ||||||
|  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |  | ||||||
|  * |  | ||||||
|  */ |  | ||||||
| 
 |  | ||||||
| using System; |  | ||||||
| using System.Collections.Generic; |  | ||||||
| using System.Reflection; |  | ||||||
| using System.Text; |  | ||||||
| using log4net; |  | ||||||
| using Nini.Config; |  | ||||||
| using OpenSim.Framework; |  | ||||||
| using OpenSim.Framework.Communications; |  | ||||||
| using OpenSim.Services.Interfaces; |  | ||||||
| using IAvatarService = OpenSim.Services.Interfaces.IAvatarService; |  | ||||||
| 
 |  | ||||||
| namespace OpenSim.ApplicationPlugins.Rest.Inventory |  | ||||||
| { |  | ||||||
|     public class Rest |  | ||||||
|     { |  | ||||||
|         internal static readonly ILog Log = |  | ||||||
|             LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); |  | ||||||
| 
 |  | ||||||
|         internal static bool DEBUG = Log.IsDebugEnabled; |  | ||||||
| 
 |  | ||||||
|         /// <summary> |  | ||||||
|         /// Supported authentication schemes |  | ||||||
|         /// </summary> |  | ||||||
| 
 |  | ||||||
|         public const string AS_BASIC                      = "Basic";           // simple user/password verification |  | ||||||
|         public const string AS_DIGEST                     = "Digest";          // password safe authentication |  | ||||||
| 
 |  | ||||||
|         /// Supported Digest algorithms |  | ||||||
| 
 |  | ||||||
|         public const string Digest_MD5                    = "MD5";             // assumed default if omitted |  | ||||||
|         public const string Digest_MD5Sess                = "MD5-sess";        // session-span - not good for REST? |  | ||||||
| 
 |  | ||||||
|         public const string Qop_Auth                      = "auth";            // authentication only |  | ||||||
|         public const string Qop_Int                       = "auth-int";        // TODO |  | ||||||
| 
 |  | ||||||
|         /// <summary> |  | ||||||
|         /// These values have a single value for the whole |  | ||||||
|         /// domain and lifetime of the plugin handler. We |  | ||||||
|         /// make them static for ease of reference within |  | ||||||
|         /// the assembly. These are initialized by the |  | ||||||
|         /// RestHandler class during start-up. |  | ||||||
|         /// </summary> |  | ||||||
| 
 |  | ||||||
|         internal static IRestHandler              Plugin            = null; |  | ||||||
|         internal static OpenSimBase               main              = null; |  | ||||||
|         internal static string                    Prefix            = null; |  | ||||||
|         internal static IConfig                   Config            = null; |  | ||||||
|         internal static string                    GodKey            = null; |  | ||||||
|         internal static bool                      Authenticate      = true; |  | ||||||
|         internal static bool                      Secure            = true; |  | ||||||
|         internal static bool                      ExtendedEscape    = true; |  | ||||||
|         internal static bool                      DumpAsset         = false; |  | ||||||
|         internal static bool                      Fill              = true; |  | ||||||
|         internal static bool                      FlushEnabled      = true; |  | ||||||
|         internal static string                    Realm             = "OpenSim REST"; |  | ||||||
|         internal static string                    Scheme            = AS_BASIC; |  | ||||||
|         internal static int                       DumpLineSize      = 32; // Should be a multiple of 16 or (possibly) 4 |  | ||||||
| 
 |  | ||||||
|         /// <summary> |  | ||||||
|         /// These are all dependent upon the Comms manager |  | ||||||
|         /// being initialized. So they have to be properties |  | ||||||
|         /// because the comms manager is now a module and is |  | ||||||
|         /// not guaranteed to be there when the rest handler |  | ||||||
|         /// initializes. |  | ||||||
|         /// </summary> |  | ||||||
| 
 |  | ||||||
|         internal static IInventoryService InventoryServices |  | ||||||
|         { |  | ||||||
|             get { return main.SceneManager.CurrentOrFirstScene.InventoryService; } |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         internal static IUserAccountService UserServices |  | ||||||
|         { |  | ||||||
|             get { return main.SceneManager.CurrentOrFirstScene.UserAccountService; } |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         internal static IAuthenticationService AuthServices |  | ||||||
|         { |  | ||||||
|             get { return main.SceneManager.CurrentOrFirstScene.AuthenticationService; } |  | ||||||
|         } |  | ||||||
|          |  | ||||||
|         internal static IAvatarService AvatarServices |  | ||||||
|         { |  | ||||||
|             get { return main.SceneManager.CurrentOrFirstScene.AvatarService; } |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         internal static IAssetService AssetServices |  | ||||||
|         { |  | ||||||
|             get { return main.SceneManager.CurrentOrFirstScene.AssetService; } |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         /// <summary> |  | ||||||
|         /// HTTP requires that status information be generated for PUT |  | ||||||
|         /// and POST opertaions. This is in support of that. The |  | ||||||
|         /// operation verb gets substituted into the first string, |  | ||||||
|         /// and the completion code is inserted into the tail. The |  | ||||||
|         /// strings are put here to encourage consistency. |  | ||||||
|         /// </summary> |  | ||||||
| 
 |  | ||||||
|         internal static string                    statusHead        = "<html><body><title>{0} status</title><break>"; |  | ||||||
|         internal static string                    statusTail        = "</body></html>"; |  | ||||||
| 
 |  | ||||||
|         internal static Dictionary<int,string> HttpStatusDesc; |  | ||||||
| 
 |  | ||||||
|         static Rest() |  | ||||||
|         { |  | ||||||
|             HttpStatusDesc = new Dictionary<int,string>(); |  | ||||||
|             if (HttpStatusCodeArray.Length != HttpStatusDescArray.Length) |  | ||||||
|             { |  | ||||||
|                 Log.ErrorFormat("{0} HTTP Status Code and Description arrays do not match"); |  | ||||||
|                 throw new Exception("HTTP Status array discrepancy"); |  | ||||||
|             } |  | ||||||
| 
 |  | ||||||
|             // Repackage the data into something more tractable. The sparse |  | ||||||
|             // nature of HTTP return codes makes an array a bad choice. |  | ||||||
| 
 |  | ||||||
|             for (int i=0; i<HttpStatusCodeArray.Length; i++) |  | ||||||
|             { |  | ||||||
|                 HttpStatusDesc.Add(HttpStatusCodeArray[i], HttpStatusDescArray[i]); |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         internal static int CreationDate |  | ||||||
|         { |  | ||||||
|             get { return (int) (DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalSeconds; } |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         internal static string MsgId |  | ||||||
|         { |  | ||||||
|             get { return Plugin.MsgId; } |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         internal static string RequestId |  | ||||||
|         { |  | ||||||
|             get { return Plugin.RequestId; } |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         internal static Encoding Encoding = Util.UTF8; |  | ||||||
| 
 |  | ||||||
|         /// <summary> |  | ||||||
|         /// Version control for REST implementation. This |  | ||||||
|         /// refers to the overall infrastructure represented |  | ||||||
|         /// by the following classes |  | ||||||
|         ///     RequestData |  | ||||||
|         ///     RequestInventoryPlugin |  | ||||||
|         ///     Rest |  | ||||||
|         /// It does no describe implementation classes such as |  | ||||||
|         /// RestInventoryServices, which may morph much more |  | ||||||
|         /// often. Such classes ARE dependent upon this however |  | ||||||
|         /// and should check it in their Initialize method. |  | ||||||
|         /// </summary> |  | ||||||
| 
 |  | ||||||
|         public static readonly float Version  = 1.0F; |  | ||||||
|         public const  string  Name            = "REST 1.0"; |  | ||||||
| 
 |  | ||||||
|         /// <summary> |  | ||||||
|         /// Currently defined HTTP methods. |  | ||||||
|         /// Only GET and HEAD are required to be |  | ||||||
|         /// supported by all servers. See Respond |  | ||||||
|         /// to see how these are handled. |  | ||||||
|         /// </summary> |  | ||||||
| 
 |  | ||||||
|         // REST AGENT 1.0 interpretations |  | ||||||
|         public const string GET     = "get";       // information retrieval - server state unchanged |  | ||||||
|         public const string HEAD    = "head";      // same as get except only the headers are returned. |  | ||||||
|         public const string POST    = "post";      // Replace the URI designated resource with the entity. |  | ||||||
|         public const string PUT     = "put";       // Add the entity to the context represented by the URI |  | ||||||
|         public const string DELETE  = "delete";    // Remove the URI designated resource from the server. |  | ||||||
| 
 |  | ||||||
|         public const string OPTIONS = "options";  // |  | ||||||
|         public const string TRACE   = "trace";    // |  | ||||||
|         public const string CONNECT = "connect";  // |  | ||||||
| 
 |  | ||||||
|         // Define this in one place... |  | ||||||
| 
 |  | ||||||
|         public const string UrlPathSeparator   = "/"; |  | ||||||
|         public const string UrlMethodSeparator = ":"; |  | ||||||
| 
 |  | ||||||
|         // Redirection qualifications |  | ||||||
| 
 |  | ||||||
|         public const bool PERMANENT = false; |  | ||||||
|         public const bool TEMPORARY = true; |  | ||||||
| 
 |  | ||||||
|         // Constant arrays used by String.Split |  | ||||||
| 
 |  | ||||||
|         public   static   readonly char   C_SPACE    = ' '; |  | ||||||
|         public   static   readonly char   C_SLASH    = '/'; |  | ||||||
|         public   static   readonly char   C_PATHSEP  = '/'; |  | ||||||
|         public   static   readonly char   C_COLON    = ':'; |  | ||||||
|         public   static   readonly char   C_PLUS     = '+'; |  | ||||||
|         public   static   readonly char   C_PERIOD   = '.'; |  | ||||||
|         public   static   readonly char   C_COMMA    = ','; |  | ||||||
|         public   static   readonly char   C_DQUOTE   = '"'; |  | ||||||
| 
 |  | ||||||
|         public   static   readonly string   CS_SPACE    = " "; |  | ||||||
|         public   static   readonly string   CS_SLASH    = "/"; |  | ||||||
|         public   static   readonly string   CS_PATHSEP  = "/"; |  | ||||||
|         public   static   readonly string   CS_COLON    = ":"; |  | ||||||
|         public   static   readonly string   CS_PLUS     = "+"; |  | ||||||
|         public   static   readonly string   CS_PERIOD   = "."; |  | ||||||
|         public   static   readonly string   CS_COMMA    = ","; |  | ||||||
|         public   static   readonly string   CS_DQUOTE   = "\""; |  | ||||||
| 
 |  | ||||||
|         public   static   readonly char[] CA_SPACE   = { C_SPACE   }; |  | ||||||
|         public   static   readonly char[] CA_SLASH   = { C_SLASH   }; |  | ||||||
|         public   static   readonly char[] CA_PATHSEP = { C_PATHSEP }; |  | ||||||
|         public   static   readonly char[] CA_COLON   = { C_COLON   }; |  | ||||||
|         public   static   readonly char[] CA_PERIOD  = { C_PERIOD  }; |  | ||||||
|         public   static   readonly char[] CA_PLUS    = { C_PLUS    }; |  | ||||||
|         public   static   readonly char[] CA_COMMA   = { C_COMMA   }; |  | ||||||
|         public   static   readonly char[] CA_DQUOTE  = { C_DQUOTE  }; |  | ||||||
| 
 |  | ||||||
|         // HTTP Code Values (in value order) |  | ||||||
| 
 |  | ||||||
|         public const int HttpStatusCodeContinue           = 100; |  | ||||||
|         public const int HttpStatusCodeSwitchingProtocols = 101; |  | ||||||
| 
 |  | ||||||
|         public const int HttpStatusCodeOK                 = 200; |  | ||||||
|         public const int HttpStatusCodeCreated            = 201; |  | ||||||
|         public const int HttpStatusCodeAccepted           = 202; |  | ||||||
|         public const int HttpStatusCodeNonAuthoritative   = 203; |  | ||||||
|         public const int HttpStatusCodeNoContent          = 204; |  | ||||||
|         public const int HttpStatusCodeResetContent       = 205; |  | ||||||
|         public const int HttpStatusCodePartialContent     = 206; |  | ||||||
| 
 |  | ||||||
|         public const int HttpStatusCodeMultipleChoices    = 300; |  | ||||||
|         public const int HttpStatusCodePermanentRedirect  = 301; |  | ||||||
|         public const int HttpStatusCodeFound              = 302; |  | ||||||
|         public const int HttpStatusCodeSeeOther           = 303; |  | ||||||
|         public const int HttpStatusCodeNotModified        = 304; |  | ||||||
|         public const int HttpStatusCodeUseProxy           = 305; |  | ||||||
|         public const int HttpStatusCodeReserved306        = 306; |  | ||||||
|         public const int HttpStatusCodeTemporaryRedirect  = 307; |  | ||||||
| 
 |  | ||||||
|         public const int HttpStatusCodeBadRequest         = 400; |  | ||||||
|         public const int HttpStatusCodeNotAuthorized      = 401; |  | ||||||
|         public const int HttpStatusCodePaymentRequired    = 402; |  | ||||||
|         public const int HttpStatusCodeForbidden          = 403; |  | ||||||
|         public const int HttpStatusCodeNotFound           = 404; |  | ||||||
|         public const int HttpStatusCodeMethodNotAllowed   = 405; |  | ||||||
|         public const int HttpStatusCodeNotAcceptable      = 406; |  | ||||||
|         public const int HttpStatusCodeProxyAuthenticate  = 407; |  | ||||||
|         public const int HttpStatusCodeTimeOut            = 408; |  | ||||||
|         public const int HttpStatusCodeConflict           = 409; |  | ||||||
|         public const int HttpStatusCodeGone               = 410; |  | ||||||
|         public const int HttpStatusCodeLengthRequired     = 411; |  | ||||||
|         public const int HttpStatusCodePreconditionFailed = 412; |  | ||||||
|         public const int HttpStatusCodeEntityTooLarge     = 413; |  | ||||||
|         public const int HttpStatusCodeUriTooLarge        = 414; |  | ||||||
|         public const int HttpStatusCodeUnsupportedMedia   = 415; |  | ||||||
|         public const int HttpStatusCodeRangeNotSatsified  = 416; |  | ||||||
|         public const int HttpStatusCodeExpectationFailed  = 417; |  | ||||||
| 
 |  | ||||||
|         public const int HttpStatusCodeServerError        = 500; |  | ||||||
|         public const int HttpStatusCodeNotImplemented     = 501; |  | ||||||
|         public const int HttpStatusCodeBadGateway         = 502; |  | ||||||
|         public const int HttpStatusCodeServiceUnavailable = 503; |  | ||||||
|         public const int HttpStatusCodeGatewayTimeout     = 504; |  | ||||||
|         public const int HttpStatusCodeHttpVersionError   = 505; |  | ||||||
| 
 |  | ||||||
|         public static readonly int[] HttpStatusCodeArray  = { |  | ||||||
|             HttpStatusCodeContinue, |  | ||||||
|             HttpStatusCodeSwitchingProtocols, |  | ||||||
|             HttpStatusCodeOK, |  | ||||||
|             HttpStatusCodeCreated, |  | ||||||
|             HttpStatusCodeAccepted, |  | ||||||
|             HttpStatusCodeNonAuthoritative, |  | ||||||
|             HttpStatusCodeNoContent, |  | ||||||
|             HttpStatusCodeResetContent, |  | ||||||
|             HttpStatusCodePartialContent, |  | ||||||
|             HttpStatusCodeMultipleChoices, |  | ||||||
|             HttpStatusCodePermanentRedirect, |  | ||||||
|             HttpStatusCodeFound, |  | ||||||
|             HttpStatusCodeSeeOther, |  | ||||||
|             HttpStatusCodeNotModified, |  | ||||||
|             HttpStatusCodeUseProxy, |  | ||||||
|             HttpStatusCodeReserved306, |  | ||||||
|             HttpStatusCodeTemporaryRedirect, |  | ||||||
|             HttpStatusCodeBadRequest, |  | ||||||
|             HttpStatusCodeNotAuthorized, |  | ||||||
|             HttpStatusCodePaymentRequired, |  | ||||||
|             HttpStatusCodeForbidden, |  | ||||||
|             HttpStatusCodeNotFound, |  | ||||||
|             HttpStatusCodeMethodNotAllowed, |  | ||||||
|             HttpStatusCodeNotAcceptable, |  | ||||||
|             HttpStatusCodeProxyAuthenticate, |  | ||||||
|             HttpStatusCodeTimeOut, |  | ||||||
|             HttpStatusCodeConflict, |  | ||||||
|             HttpStatusCodeGone, |  | ||||||
|             HttpStatusCodeLengthRequired, |  | ||||||
|             HttpStatusCodePreconditionFailed, |  | ||||||
|             HttpStatusCodeEntityTooLarge, |  | ||||||
|             HttpStatusCodeUriTooLarge, |  | ||||||
|             HttpStatusCodeUnsupportedMedia, |  | ||||||
|             HttpStatusCodeRangeNotSatsified, |  | ||||||
|             HttpStatusCodeExpectationFailed, |  | ||||||
|             HttpStatusCodeServerError, |  | ||||||
|             HttpStatusCodeNotImplemented, |  | ||||||
|             HttpStatusCodeBadGateway, |  | ||||||
|             HttpStatusCodeServiceUnavailable, |  | ||||||
|             HttpStatusCodeGatewayTimeout, |  | ||||||
|             HttpStatusCodeHttpVersionError |  | ||||||
|         }; |  | ||||||
| 
 |  | ||||||
|         // HTTP Status Descriptions (in status code order) |  | ||||||
|         // This array must be kept strictly consistent with respect |  | ||||||
|         // to the status code array above. |  | ||||||
| 
 |  | ||||||
|         public static readonly string[] HttpStatusDescArray  = { |  | ||||||
|             "Continue Request", |  | ||||||
|             "Switching Protocols", |  | ||||||
|             "OK", |  | ||||||
|             "CREATED", |  | ||||||
|             "ACCEPTED", |  | ||||||
|             "NON-AUTHORITATIVE INFORMATION", |  | ||||||
|             "NO CONTENT", |  | ||||||
|             "RESET CONTENT", |  | ||||||
|             "PARTIAL CONTENT", |  | ||||||
|             "MULTIPLE CHOICES", |  | ||||||
|             "PERMANENT REDIRECT", |  | ||||||
|             "FOUND", |  | ||||||
|             "SEE OTHER", |  | ||||||
|             "NOT MODIFIED", |  | ||||||
|             "USE PROXY", |  | ||||||
|             "RESERVED CODE 306", |  | ||||||
|             "TEMPORARY REDIRECT", |  | ||||||
|             "BAD REQUEST", |  | ||||||
|             "NOT AUTHORIZED", |  | ||||||
|             "PAYMENT REQUIRED", |  | ||||||
|             "FORBIDDEN", |  | ||||||
|             "NOT FOUND", |  | ||||||
|             "METHOD NOT ALLOWED", |  | ||||||
|             "NOT ACCEPTABLE", |  | ||||||
|             "PROXY AUTHENTICATION REQUIRED", |  | ||||||
|             "TIMEOUT", |  | ||||||
|             "CONFLICT", |  | ||||||
|             "GONE", |  | ||||||
|             "LENGTH REQUIRED", |  | ||||||
|             "PRECONDITION FAILED", |  | ||||||
|             "ENTITY TOO LARGE", |  | ||||||
|             "URI TOO LARGE", |  | ||||||
|             "UNSUPPORTED MEDIA", |  | ||||||
|             "RANGE NOT SATISFIED", |  | ||||||
|             "EXPECTATION FAILED", |  | ||||||
|             "SERVER ERROR", |  | ||||||
|             "NOT IMPLEMENTED", |  | ||||||
|             "BAD GATEWAY", |  | ||||||
|             "SERVICE UNAVAILABLE", |  | ||||||
|             "GATEWAY TIMEOUT", |  | ||||||
|             "HTTP VERSION NOT SUPPORTED" |  | ||||||
|         }; |  | ||||||
| 
 |  | ||||||
|         // HTTP Headers |  | ||||||
| 
 |  | ||||||
|         public const string HttpHeaderAccept              = "Accept"; |  | ||||||
|         public const string HttpHeaderAcceptCharset       = "Accept-Charset"; |  | ||||||
|         public const string HttpHeaderAcceptEncoding      = "Accept-Encoding"; |  | ||||||
|         public const string HttpHeaderAcceptLanguage      = "Accept-Language"; |  | ||||||
|         public const string HttpHeaderAcceptRanges        = "Accept-Ranges"; |  | ||||||
|         public const string HttpHeaderAge                 = "Age"; |  | ||||||
|         public const string HttpHeaderAllow               = "Allow"; |  | ||||||
|         public const string HttpHeaderAuthorization       = "Authorization"; |  | ||||||
|         public const string HttpHeaderCacheControl        = "Cache-Control"; |  | ||||||
|         public const string HttpHeaderConnection          = "Connection"; |  | ||||||
|         public const string HttpHeaderContentEncoding     = "Content-Encoding"; |  | ||||||
|         public const string HttpHeaderContentLanguage     = "Content-Language"; |  | ||||||
|         public const string HttpHeaderContentLength       = "Content-Length"; |  | ||||||
|         public const string HttpHeaderContentLocation     = "Content-Location"; |  | ||||||
|         public const string HttpHeaderContentMD5          = "Content-MD5"; |  | ||||||
|         public const string HttpHeaderContentRange        = "Content-Range"; |  | ||||||
|         public const string HttpHeaderContentType         = "Content-Type"; |  | ||||||
|         public const string HttpHeaderDate                = "Date"; |  | ||||||
|         public const string HttpHeaderETag                = "ETag"; |  | ||||||
|         public const string HttpHeaderExpect              = "Expect"; |  | ||||||
|         public const string HttpHeaderExpires             = "Expires"; |  | ||||||
|         public const string HttpHeaderFrom                = "From"; |  | ||||||
|         public const string HttpHeaderHost                = "Host"; |  | ||||||
|         public const string HttpHeaderIfMatch             = "If-Match"; |  | ||||||
|         public const string HttpHeaderIfModifiedSince     = "If-Modified-Since"; |  | ||||||
|         public const string HttpHeaderIfNoneMatch         = "If-None-Match"; |  | ||||||
|         public const string HttpHeaderIfRange             = "If-Range"; |  | ||||||
|         public const string HttpHeaderIfUnmodifiedSince   = "If-Unmodified-Since"; |  | ||||||
|         public const string HttpHeaderLastModified        = "Last-Modified"; |  | ||||||
|         public const string HttpHeaderLocation            = "Location"; |  | ||||||
|         public const string HttpHeaderMaxForwards         = "Max-Forwards"; |  | ||||||
|         public const string HttpHeaderPragma              = "Pragma"; |  | ||||||
|         public const string HttpHeaderProxyAuthenticate   = "Proxy-Authenticate"; |  | ||||||
|         public const string HttpHeaderProxyAuthorization  = "Proxy-Authorization"; |  | ||||||
|         public const string HttpHeaderRange               = "Range"; |  | ||||||
|         public const string HttpHeaderReferer             = "Referer"; |  | ||||||
|         public const string HttpHeaderRetryAfter          = "Retry-After"; |  | ||||||
|         public const string HttpHeaderServer              = "Server"; |  | ||||||
|         public const string HttpHeaderTE                  = "TE"; |  | ||||||
|         public const string HttpHeaderTrailer             = "Trailer"; |  | ||||||
|         public const string HttpHeaderTransferEncoding    = "Transfer-Encoding"; |  | ||||||
|         public const string HttpHeaderUpgrade             = "Upgrade"; |  | ||||||
|         public const string HttpHeaderUserAgent           = "User-Agent"; |  | ||||||
|         public const string HttpHeaderVary                = "Vary"; |  | ||||||
|         public const string HttpHeaderVia                 = "Via"; |  | ||||||
|         public const string HttpHeaderWarning             = "Warning"; |  | ||||||
|         public const string HttpHeaderWWWAuthenticate     = "WWW-Authenticate"; |  | ||||||
| 
 |  | ||||||
|         /// Utility routines |  | ||||||
| 
 |  | ||||||
|         public static string StringToBase64(string str) |  | ||||||
|         { |  | ||||||
|             try |  | ||||||
|             { |  | ||||||
|                 byte[] encData_byte = new byte[str.Length]; |  | ||||||
|                 encData_byte = Util.UTF8.GetBytes(str); |  | ||||||
|                 return Convert.ToBase64String(encData_byte); |  | ||||||
|             } |  | ||||||
|             catch |  | ||||||
|             { |  | ||||||
|                 return String.Empty; |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         public static string Base64ToString(string str) |  | ||||||
|         { |  | ||||||
|             try |  | ||||||
|             { |  | ||||||
|                 return Util.Base64ToString(str); |  | ||||||
|             } |  | ||||||
|             catch |  | ||||||
|             { |  | ||||||
|                 return String.Empty; |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         private const string hvals = "0123456789abcdef"; |  | ||||||
| 
 |  | ||||||
|         public static int Hex2Int(string hex) |  | ||||||
|         { |  | ||||||
|             int    val = 0; |  | ||||||
|             int    sum = 0; |  | ||||||
|             string tmp = null; |  | ||||||
| 
 |  | ||||||
|             if (hex != null) |  | ||||||
|             { |  | ||||||
|                 tmp = hex.ToLower(); |  | ||||||
|                 for (int i = 0; i < tmp.Length; i++) |  | ||||||
|                 { |  | ||||||
|                     val = hvals.IndexOf(tmp[i]); |  | ||||||
|                     if (val == -1) |  | ||||||
|                         break; |  | ||||||
|                     sum *= 16; |  | ||||||
|                     sum += val; |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
| 
 |  | ||||||
|             return sum; |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         // Nonce management |  | ||||||
| 
 |  | ||||||
|         public static string NonceGenerator() |  | ||||||
|         { |  | ||||||
|             return StringToBase64(CreationDate + Guid.NewGuid().ToString()); |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         // Dump the specified data stream |  | ||||||
| 
 |  | ||||||
|         public static void Dump(byte[] data) |  | ||||||
|         { |  | ||||||
|             char[] buffer = new char[DumpLineSize]; |  | ||||||
|             int cc = 0; |  | ||||||
| 
 |  | ||||||
|             for (int i = 0; i < data.Length; i++) |  | ||||||
|             { |  | ||||||
|                 if (i % DumpLineSize == 0) Console.Write("\n{0}: ",i.ToString("d8")); |  | ||||||
| 
 |  | ||||||
|                 if (i % 4  == 0) Console.Write(" "); |  | ||||||
| 
 |  | ||||||
|                 Console.Write("{0}",data[i].ToString("x2")); |  | ||||||
| 
 |  | ||||||
|                 if (data[i] < 127 && data[i] > 31) |  | ||||||
|                     buffer[i % DumpLineSize] = (char) data[i]; |  | ||||||
|                 else |  | ||||||
|                     buffer[i % DumpLineSize] = '.'; |  | ||||||
| 
 |  | ||||||
|                 cc++; |  | ||||||
| 
 |  | ||||||
|                 if (i != 0 && (i + 1) % DumpLineSize == 0) |  | ||||||
|                 { |  | ||||||
|                     Console.Write(" |"+(new String(buffer))+"|"); |  | ||||||
|                     cc = 0; |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
| 
 |  | ||||||
|             // Finish off any incomplete line |  | ||||||
| 
 |  | ||||||
|             if (cc != 0) |  | ||||||
|             { |  | ||||||
|                 for (int i = cc ; i < DumpLineSize; i++) |  | ||||||
|                 { |  | ||||||
|                     if (i % 4  == 0) Console.Write(" "); |  | ||||||
|                     Console.Write("  "); |  | ||||||
|                     buffer[i % DumpLineSize] = ' '; |  | ||||||
|                 } |  | ||||||
|                 Console.WriteLine(" |"+(new String(buffer))+"|"); |  | ||||||
|             } |  | ||||||
|             else |  | ||||||
|             { |  | ||||||
|                 Console.Write("\n"); |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     // Local exception type |  | ||||||
| 
 |  | ||||||
|     public class RestException : Exception |  | ||||||
|     { |  | ||||||
|         internal int    statusCode; |  | ||||||
|         internal string statusDesc; |  | ||||||
|         internal string httpmethod; |  | ||||||
|         internal string httppath; |  | ||||||
| 
 |  | ||||||
|         public RestException(string msg) : base(msg) |  | ||||||
|         { |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| } |  | ||||||
|  | @ -1,860 +0,0 @@ | ||||||
| /* |  | ||||||
|  * Copyright (c) Contributors, http://opensimulator.org/ |  | ||||||
|  * See CONTRIBUTORS.TXT for a full list of copyright holders. |  | ||||||
|  * |  | ||||||
|  * Redistribution and use in source and binary forms, with or without |  | ||||||
|  * modification, are permitted provided that the following conditions are met: |  | ||||||
|  *     * Redistributions of source code must retain the above copyright |  | ||||||
|  *       notice, this list of conditions and the following disclaimer. |  | ||||||
|  *     * Redistributions in binary form must reproduce the above copyright |  | ||||||
|  *       notice, this list of conditions and the following disclaimer in the |  | ||||||
|  *       documentation and/or other materials provided with the distribution. |  | ||||||
|  *     * Neither the name of the OpenSimulator Project nor the |  | ||||||
|  *       names of its contributors may be used to endorse or promote products |  | ||||||
|  *       derived from this software without specific prior written permission. |  | ||||||
|  * |  | ||||||
|  * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY |  | ||||||
|  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |  | ||||||
|  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |  | ||||||
|  * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY |  | ||||||
|  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |  | ||||||
|  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |  | ||||||
|  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |  | ||||||
|  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |  | ||||||
|  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |  | ||||||
|  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |  | ||||||
|  */ |  | ||||||
| 
 |  | ||||||
| using System; |  | ||||||
| using System.Collections; |  | ||||||
| using System.Collections.Generic; |  | ||||||
| using System.Xml; |  | ||||||
| using OpenMetaverse; |  | ||||||
| using OpenSim.Framework; |  | ||||||
| using OpenSim.Framework.Servers; |  | ||||||
| using OpenSim.Framework.Servers.HttpServer; |  | ||||||
| using OpenSim.Services.Interfaces; |  | ||||||
| 
 |  | ||||||
| namespace OpenSim.ApplicationPlugins.Rest.Inventory |  | ||||||
| { |  | ||||||
| 
 |  | ||||||
|     public class RestAppearanceServices : IRest |  | ||||||
|     { |  | ||||||
| //        private static readonly int PARM_USERID = 0; |  | ||||||
| 
 |  | ||||||
|         // private static readonly int PARM_PATH   = 1; |  | ||||||
| 
 |  | ||||||
| //        private bool       enabled = false; |  | ||||||
|         private string     qPrefix = "appearance"; |  | ||||||
| 
 |  | ||||||
|         /// <summary> |  | ||||||
|         /// The constructor makes sure that the service prefix is absolute |  | ||||||
|         /// and the registers the service handler and the allocator. |  | ||||||
|         /// </summary> |  | ||||||
| 
 |  | ||||||
|         public RestAppearanceServices() |  | ||||||
|         { |  | ||||||
|             Rest.Log.InfoFormat("{0} User appearance services initializing", MsgId); |  | ||||||
|             Rest.Log.InfoFormat("{0} Using REST Implementation Version {1}", MsgId, Rest.Version); |  | ||||||
| 
 |  | ||||||
|             // If a relative path was specified for the handler's domain, |  | ||||||
|             // add the standard prefix to make it absolute, e.g. /admin |  | ||||||
| 
 |  | ||||||
|             if (!qPrefix.StartsWith(Rest.UrlPathSeparator)) |  | ||||||
|             { |  | ||||||
|                 Rest.Log.InfoFormat("{0} Domain is relative, adding absolute prefix", MsgId); |  | ||||||
|                 qPrefix = String.Format("{0}{1}{2}", Rest.Prefix, Rest.UrlPathSeparator, qPrefix); |  | ||||||
|                 qPrefix = String.Format("{0}{1}{2}", Rest.Prefix, Rest.UrlPathSeparator, qPrefix); |  | ||||||
|                 Rest.Log.InfoFormat("{0} Domain is now <{1}>", MsgId, qPrefix); |  | ||||||
|             } |  | ||||||
| 
 |  | ||||||
|             // Register interface using the absolute URI. |  | ||||||
| 
 |  | ||||||
|             Rest.Plugin.AddPathHandler(DoAppearance,qPrefix,Allocate); |  | ||||||
| 
 |  | ||||||
|             // Activate if everything went OK |  | ||||||
| 
 |  | ||||||
| //            enabled = true; |  | ||||||
| 
 |  | ||||||
|             Rest.Log.InfoFormat("{0} User appearance services initialization complete", MsgId); |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         /// <summary> |  | ||||||
|         /// Post-construction, pre-enabled initialization opportunity |  | ||||||
|         /// Not currently exploited. |  | ||||||
|         /// </summary> |  | ||||||
| 
 |  | ||||||
|         public void Initialize() |  | ||||||
|         { |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         /// <summary> |  | ||||||
|         /// Called by the plug-in to halt service processing. Local processing is |  | ||||||
|         /// disabled. |  | ||||||
|         /// </summary> |  | ||||||
| 
 |  | ||||||
|         public void Close() |  | ||||||
|         { |  | ||||||
| //            enabled = false; |  | ||||||
|             Rest.Log.InfoFormat("{0} User appearance services closing down", MsgId); |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         /// <summary> |  | ||||||
|         /// This property is declared locally because it is used a lot and |  | ||||||
|         /// brevity is nice. |  | ||||||
|         /// </summary> |  | ||||||
| 
 |  | ||||||
|         internal string MsgId |  | ||||||
|         { |  | ||||||
|             get { return Rest.MsgId; } |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         #region Interface |  | ||||||
| 
 |  | ||||||
|         /// <summary> |  | ||||||
|         /// The plugin (RestHandler) calls this method to allocate the request |  | ||||||
|         /// state carrier for a new request. It is destroyed when the request |  | ||||||
|         /// completes. All request-instance specific state is kept here. This |  | ||||||
|         /// is registered when this service provider is registered. |  | ||||||
|         /// </summary> |  | ||||||
|         /// <param name=request>Inbound HTTP request information</param> |  | ||||||
|         /// <param name=response>Outbound HTTP request information</param> |  | ||||||
|         /// <param name=qPrefix>REST service domain prefix</param> |  | ||||||
|         /// <returns>A RequestData instance suitable for this service</returns> |  | ||||||
| 
 |  | ||||||
|         private RequestData Allocate(OSHttpRequest request, OSHttpResponse response, string prefix) |  | ||||||
|         { |  | ||||||
|             return (RequestData) new AppearanceRequestData(request, response, prefix); |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         /// <summary> |  | ||||||
|         /// This method is registered with the handler when this service provider |  | ||||||
|         /// is initialized. It is called whenever the plug-in identifies this service |  | ||||||
|         /// provider as the best match for a given request. |  | ||||||
|         /// It handles all aspects of inventory REST processing, i.e. /admin/inventory |  | ||||||
|         /// </summary> |  | ||||||
|         /// <param name=hdata>A consolidated HTTP request work area</param> |  | ||||||
| 
 |  | ||||||
|         private void DoAppearance(RequestData hdata) |  | ||||||
|         { |  | ||||||
|             // !!! REFACTORIMG PROBLEM. This needs rewriting for 0.7 |  | ||||||
| 
 |  | ||||||
|             //AppearanceRequestData rdata = (AppearanceRequestData) hdata; |  | ||||||
| 
 |  | ||||||
|             //Rest.Log.DebugFormat("{0} DoAppearance ENTRY", MsgId); |  | ||||||
| 
 |  | ||||||
|             //// If we're disabled, do nothing. |  | ||||||
| 
 |  | ||||||
|             //if (!enabled) |  | ||||||
|             //{ |  | ||||||
|             //    return; |  | ||||||
|             //} |  | ||||||
| 
 |  | ||||||
|             //// Now that we know this is a serious attempt to |  | ||||||
|             //// access inventory data, we should find out who |  | ||||||
|             //// is asking, and make sure they are authorized |  | ||||||
|             //// to do so. We need to validate the caller's |  | ||||||
|             //// identity before revealing anything about the |  | ||||||
|             //// status quo. Authenticate throws an exception |  | ||||||
|             //// via Fail if no identity information is present. |  | ||||||
|             //// |  | ||||||
|             //// With the present HTTP server we can't use the |  | ||||||
|             //// builtin authentication mechanisms because they |  | ||||||
|             //// would be enforced for all in-bound requests. |  | ||||||
|             //// Instead we look at the headers ourselves and |  | ||||||
|             //// handle authentication directly. |  | ||||||
| 
 |  | ||||||
|             //try |  | ||||||
|             //{ |  | ||||||
|             //    if (!rdata.IsAuthenticated) |  | ||||||
|             //    { |  | ||||||
|             //        rdata.Fail(Rest.HttpStatusCodeNotAuthorized,String.Format("user \"{0}\" could not be authenticated", rdata.userName)); |  | ||||||
|             //    } |  | ||||||
|             //} |  | ||||||
|             //catch (RestException e) |  | ||||||
|             //{ |  | ||||||
|             //    if (e.statusCode == Rest.HttpStatusCodeNotAuthorized) |  | ||||||
|             //    { |  | ||||||
|             //        Rest.Log.WarnFormat("{0} User not authenticated", MsgId); |  | ||||||
|             //        Rest.Log.DebugFormat("{0} Authorization header: {1}", MsgId, rdata.request.Headers.Get("Authorization")); |  | ||||||
|             //    } |  | ||||||
|             //    else |  | ||||||
|             //    { |  | ||||||
|             //        Rest.Log.ErrorFormat("{0} User authentication failed", MsgId); |  | ||||||
|             //        Rest.Log.DebugFormat("{0} Authorization header: {1}", MsgId, rdata.request.Headers.Get("Authorization")); |  | ||||||
|             //    } |  | ||||||
|             //    throw (e); |  | ||||||
|             //} |  | ||||||
| 
 |  | ||||||
|             //Rest.Log.DebugFormat("{0} Authenticated {1}", MsgId, rdata.userName); |  | ||||||
| 
 |  | ||||||
|             //// We can only get here if we are authorized |  | ||||||
|             //// |  | ||||||
|             //// The requestor may have specified an UUID or |  | ||||||
|             //// a conjoined FirstName LastName string. We'll |  | ||||||
|             //// try both. If we fail with the first, UUID, |  | ||||||
|             //// attempt, we try the other. As an example, the |  | ||||||
|             //// URI for a valid inventory request might be: |  | ||||||
|             //// |  | ||||||
|             //// http://<host>:<port>/admin/inventory/Arthur Dent |  | ||||||
|             //// |  | ||||||
|             //// Indicating that this is an inventory request for |  | ||||||
|             //// an avatar named Arthur Dent. This is ALL that is |  | ||||||
|             //// required to designate a GET for an entire |  | ||||||
|             //// inventory. |  | ||||||
|             //// |  | ||||||
| 
 |  | ||||||
|             //// Do we have at least a user agent name? |  | ||||||
| 
 |  | ||||||
|             //if (rdata.Parameters.Length < 1) |  | ||||||
|             //{ |  | ||||||
|             //    Rest.Log.WarnFormat("{0} Appearance: No user agent identifier specified", MsgId); |  | ||||||
|             //    rdata.Fail(Rest.HttpStatusCodeBadRequest, "no user identity specified"); |  | ||||||
|             //} |  | ||||||
| 
 |  | ||||||
|             //// The first parameter MUST be the agent identification, either an UUID |  | ||||||
|             //// or a space-separated First-name Last-Name specification. We check for |  | ||||||
|             //// an UUID first, if anyone names their character using a valid UUID |  | ||||||
|             //// that identifies another existing avatar will cause this a problem... |  | ||||||
| 
 |  | ||||||
|             //try |  | ||||||
|             //{ |  | ||||||
|             //    rdata.uuid = new UUID(rdata.Parameters[PARM_USERID]); |  | ||||||
|             //    Rest.Log.DebugFormat("{0} UUID supplied", MsgId); |  | ||||||
|             //    rdata.userProfile = Rest.UserServices.GetUserProfile(rdata.uuid); |  | ||||||
|             //} |  | ||||||
|             //catch |  | ||||||
|             //{ |  | ||||||
|             //    string[] names = rdata.Parameters[PARM_USERID].Split(Rest.CA_SPACE); |  | ||||||
|             //    if (names.Length == 2) |  | ||||||
|             //    { |  | ||||||
|             //        Rest.Log.DebugFormat("{0} Agent Name supplied [2]", MsgId); |  | ||||||
|             //        rdata.userProfile = Rest.UserServices.GetUserProfile(names[0],names[1]); |  | ||||||
|             //    } |  | ||||||
|             //    else |  | ||||||
|             //    { |  | ||||||
|             //        Rest.Log.WarnFormat("{0} A Valid UUID or both first and last names must be specified", MsgId); |  | ||||||
|             //        rdata.Fail(Rest.HttpStatusCodeBadRequest, "invalid user identity"); |  | ||||||
|             //    } |  | ||||||
|             //} |  | ||||||
| 
 |  | ||||||
|             //// If the user profile is null then either the server is broken, or the |  | ||||||
|             //// user is not known. We always assume the latter case. |  | ||||||
| 
 |  | ||||||
|             //if (rdata.userProfile != null) |  | ||||||
|             //{ |  | ||||||
|             //    Rest.Log.DebugFormat("{0} User profile obtained for agent {1} {2}", |  | ||||||
|             //                         MsgId, rdata.userProfile.FirstName, rdata.userProfile.SurName); |  | ||||||
|             //} |  | ||||||
|             //else |  | ||||||
|             //{ |  | ||||||
|             //    Rest.Log.WarnFormat("{0} No user profile for {1}", MsgId, rdata.path); |  | ||||||
|             //    rdata.Fail(Rest.HttpStatusCodeNotFound, "unrecognized user identity"); |  | ||||||
|             //} |  | ||||||
| 
 |  | ||||||
|             //// If we get to here, then we have effectively validated the user's |  | ||||||
| 
 |  | ||||||
|             //switch (rdata.method) |  | ||||||
|             //{ |  | ||||||
|             //    case Rest.HEAD   : // Do the processing, set the status code, suppress entity |  | ||||||
|             //        DoGet(rdata); |  | ||||||
|             //        rdata.buffer = null; |  | ||||||
|             //        break; |  | ||||||
| 
 |  | ||||||
|             //    case Rest.GET    : // Do the processing, set the status code, return entity |  | ||||||
|             //        DoGet(rdata); |  | ||||||
|             //        break; |  | ||||||
| 
 |  | ||||||
|             //    case Rest.PUT    : // Update named element |  | ||||||
|             //        DoUpdate(rdata); |  | ||||||
|             //        break; |  | ||||||
| 
 |  | ||||||
|             //    case Rest.POST   : // Add new information to identified context. |  | ||||||
|             //        DoExtend(rdata); |  | ||||||
|             //        break; |  | ||||||
| 
 |  | ||||||
|             //    case Rest.DELETE : // Delete information |  | ||||||
|             //        DoDelete(rdata); |  | ||||||
|             //        break; |  | ||||||
| 
 |  | ||||||
|             //    default : |  | ||||||
|             //        Rest.Log.WarnFormat("{0} Method {1} not supported for {2}", |  | ||||||
|             //                             MsgId, rdata.method, rdata.path); |  | ||||||
|             //        rdata.Fail(Rest.HttpStatusCodeMethodNotAllowed,  |  | ||||||
|             //                   String.Format("{0} not supported", rdata.method)); |  | ||||||
|             //        break; |  | ||||||
|             //} |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         #endregion Interface |  | ||||||
| 
 |  | ||||||
|         #region method-specific processing |  | ||||||
| 
 |  | ||||||
|         /// <summary> |  | ||||||
|         /// This method implements GET processing for user's appearance. |  | ||||||
|         /// </summary> |  | ||||||
|         /// <param name=rdata>HTTP service request work area</param> |  | ||||||
| 
 |  | ||||||
| //        private void DoGet(AppearanceRequestData rdata) |  | ||||||
| //        { |  | ||||||
| //            AvatarData adata = Rest.AvatarServices.GetAvatar(rdata.userProfile.ID); |  | ||||||
| // |  | ||||||
| //            if (adata == null) |  | ||||||
| //            { |  | ||||||
| //                rdata.Fail(Rest.HttpStatusCodeNoContent, |  | ||||||
| //                    String.Format("appearance data not found for user {0} {1}",  |  | ||||||
| //                      rdata.userProfile.FirstName, rdata.userProfile.SurName)); |  | ||||||
| //            } |  | ||||||
| //            rdata.userAppearance = adata.ToAvatarAppearance(rdata.userProfile.ID); |  | ||||||
| // |  | ||||||
| //            rdata.initXmlWriter(); |  | ||||||
| // |  | ||||||
| //            FormatUserAppearance(rdata); |  | ||||||
| // |  | ||||||
| //            // Indicate a successful request |  | ||||||
| // |  | ||||||
| //            rdata.Complete(); |  | ||||||
| // |  | ||||||
| //            // Send the response to the user. The body will be implicitly |  | ||||||
| //            // constructed from the result of the XML writer. |  | ||||||
| // |  | ||||||
| //            rdata.Respond(String.Format("Appearance {0} Normal completion", rdata.method)); |  | ||||||
| //        } |  | ||||||
| 
 |  | ||||||
|         /// <summary> |  | ||||||
|         /// POST adds NEW information to the user profile database. |  | ||||||
|         /// This effectively resets the appearance before applying those |  | ||||||
|         /// characteristics supplied in the request. |  | ||||||
|         /// </summary> |  | ||||||
| 
 |  | ||||||
| //        private void DoExtend(AppearanceRequestData rdata) |  | ||||||
| //        { |  | ||||||
| // |  | ||||||
| //            bool  created  = false; |  | ||||||
| //            bool  modified = false; |  | ||||||
| //            string newnode = String.Empty; |  | ||||||
| // |  | ||||||
| //            Rest.Log.DebugFormat("{0} POST ENTRY", MsgId); |  | ||||||
| // |  | ||||||
| //            //AvatarAppearance old = Rest.AvatarServices.GetUserAppearance(rdata.userProfile.ID); |  | ||||||
| // |  | ||||||
| //            rdata.userAppearance = new AvatarAppearance(); |  | ||||||
| // |  | ||||||
| //            //  Although the following behavior is admitted by HTTP I am becoming  |  | ||||||
| //            //  increasingly doubtful that it is appropriate for REST. If I attempt to |  | ||||||
| //            //  add a new record, and it already exists, then it seems to me that the |  | ||||||
| //            //  attempt should fail, rather than update the existing record. |  | ||||||
| //            AvatarData adata = null; |  | ||||||
| //            if (GetUserAppearance(rdata)) |  | ||||||
| //            { |  | ||||||
| //                modified = rdata.userAppearance != null; |  | ||||||
| //                created  = !modified; |  | ||||||
| //                adata = new AvatarData(rdata.userAppearance); |  | ||||||
| //                Rest.AvatarServices.SetAvatar(rdata.userProfile.ID, adata); |  | ||||||
| //            //    Rest.UserServices.UpdateUserProfile(rdata.userProfile); |  | ||||||
| //            } |  | ||||||
| //            else |  | ||||||
| //            { |  | ||||||
| //                created  = true; |  | ||||||
| //                adata = new AvatarData(rdata.userAppearance); |  | ||||||
| //                Rest.AvatarServices.SetAvatar(rdata.userProfile.ID, adata); |  | ||||||
| //             //   Rest.UserServices.UpdateUserProfile(rdata.userProfile); |  | ||||||
| //            } |  | ||||||
| // |  | ||||||
| //            if (created) |  | ||||||
| //            { |  | ||||||
| //                newnode = String.Format("{0} {1}", rdata.userProfile.FirstName, |  | ||||||
| //                                   rdata.userProfile.SurName); |  | ||||||
| //                // Must include a location header with a URI that identifies the new resource. |  | ||||||
| // |  | ||||||
| //                rdata.AddHeader(Rest.HttpHeaderLocation,String.Format("http://{0}{1}:{2}{3}{4}", |  | ||||||
| //                         rdata.hostname,rdata.port,rdata.path,Rest.UrlPathSeparator, newnode)); |  | ||||||
| //                rdata.Complete(Rest.HttpStatusCodeCreated); |  | ||||||
| // |  | ||||||
| //            } |  | ||||||
| //            else |  | ||||||
| //            { |  | ||||||
| //                if (modified) |  | ||||||
| //                { |  | ||||||
| //                    rdata.Complete(Rest.HttpStatusCodeOK); |  | ||||||
| //                } |  | ||||||
| //                else |  | ||||||
| //                { |  | ||||||
| //                    rdata.Complete(Rest.HttpStatusCodeNoContent); |  | ||||||
| //                } |  | ||||||
| //            } |  | ||||||
| // |  | ||||||
| //            rdata.Respond(String.Format("Appearance {0} : Normal completion", rdata.method)); |  | ||||||
| // |  | ||||||
| //        } |  | ||||||
| 
 |  | ||||||
|         /// <summary> |  | ||||||
|         /// This updates the user's appearance. not all aspects need to be provided, |  | ||||||
|         /// only those supplied will be changed. |  | ||||||
|         /// </summary> |  | ||||||
| 
 |  | ||||||
| //        private void DoUpdate(AppearanceRequestData rdata) |  | ||||||
| //        { |  | ||||||
| // |  | ||||||
| //            // REFACTORING PROBLEM This was commented out. It doesn't work for 0.7 |  | ||||||
| // |  | ||||||
| //            //bool  created  = false; |  | ||||||
| //            //bool  modified = false; |  | ||||||
| // |  | ||||||
| // |  | ||||||
| //            //rdata.userAppearance = Rest.AvatarServices.GetUserAppearance(rdata.userProfile.ID); |  | ||||||
| // |  | ||||||
| //            //// If the user exists then this is considered a modification regardless |  | ||||||
| //            //// of what may, or may not be, specified in the payload. |  | ||||||
| // |  | ||||||
| //            //if (rdata.userAppearance != null) |  | ||||||
| //            //{ |  | ||||||
| //            //    modified = true; |  | ||||||
| //            //    Rest.AvatarServices.UpdateUserAppearance(rdata.userProfile.ID, rdata.userAppearance); |  | ||||||
| //            //    Rest.UserServices.UpdateUserProfile(rdata.userProfile); |  | ||||||
| //            //} |  | ||||||
| // |  | ||||||
| //            //if (created) |  | ||||||
| //            //{ |  | ||||||
| //            //    rdata.Complete(Rest.HttpStatusCodeCreated); |  | ||||||
| //            //} |  | ||||||
| //            //else |  | ||||||
| //            //{ |  | ||||||
| //            //    if (modified) |  | ||||||
| //            //    { |  | ||||||
| //            //        rdata.Complete(Rest.HttpStatusCodeOK); |  | ||||||
| //            //    } |  | ||||||
| //            //    else |  | ||||||
| //            //    { |  | ||||||
| //            //        rdata.Complete(Rest.HttpStatusCodeNoContent); |  | ||||||
| //            //    } |  | ||||||
| //            //} |  | ||||||
| // |  | ||||||
| //            rdata.Respond(String.Format("Appearance {0} : Normal completion", rdata.method)); |  | ||||||
| // |  | ||||||
| //        } |  | ||||||
| 
 |  | ||||||
|         /// <summary> |  | ||||||
|         /// Delete the specified user's appearance. This actually performs a reset |  | ||||||
|         /// to the default avatar appearance, if the info is already there.  |  | ||||||
|         /// Existing ownership is preserved. All prior updates are lost and can not |  | ||||||
|         /// be recovered. |  | ||||||
|         /// </summary> |  | ||||||
| //        private void DoDelete(AppearanceRequestData rdata) |  | ||||||
| //        { |  | ||||||
| //            AvatarData adata = Rest.AvatarServices.GetAvatar(rdata.userProfile.ID); |  | ||||||
| // |  | ||||||
| //            if (adata != null) |  | ||||||
| //            { |  | ||||||
| //                AvatarAppearance old = adata.ToAvatarAppearance(rdata.userProfile.ID); |  | ||||||
| //                rdata.userAppearance = new AvatarAppearance(); |  | ||||||
| //                rdata.userAppearance.Owner = old.Owner; |  | ||||||
| //                adata = new AvatarData(rdata.userAppearance); |  | ||||||
| // |  | ||||||
| //                Rest.AvatarServices.SetAvatar(rdata.userProfile.ID, adata); |  | ||||||
| // |  | ||||||
| //                rdata.Complete(); |  | ||||||
| //            } |  | ||||||
| //            else |  | ||||||
| //            { |  | ||||||
| // |  | ||||||
| //                rdata.Complete(Rest.HttpStatusCodeNoContent); |  | ||||||
| //            } |  | ||||||
| // |  | ||||||
| //            rdata.Respond(String.Format("Appearance {0} : Normal completion", rdata.method)); |  | ||||||
| //        } |  | ||||||
| 
 |  | ||||||
| #endregion method-specific processing |  | ||||||
| 
 |  | ||||||
|         private bool GetUserAppearance(AppearanceRequestData rdata) |  | ||||||
|         { |  | ||||||
| 
 |  | ||||||
|             XmlReader xml; |  | ||||||
|             bool indata = false; |  | ||||||
| 
 |  | ||||||
|             rdata.initXmlReader(); |  | ||||||
|             xml     = rdata.reader; |  | ||||||
| 
 |  | ||||||
|             while (xml.Read()) |  | ||||||
|             { |  | ||||||
|                 switch (xml.NodeType) |  | ||||||
|                 { |  | ||||||
|                     case XmlNodeType.Element : |  | ||||||
|                         switch (xml.Name) |  | ||||||
|                         { |  | ||||||
|                             case "Appearance" : |  | ||||||
|                                 if (xml.MoveToAttribute("Height")) |  | ||||||
|                                 { |  | ||||||
|                                     rdata.userAppearance.AvatarHeight = (float) Convert.ToDouble(xml.Value); |  | ||||||
|                                     indata = true; |  | ||||||
|                                 } |  | ||||||
| //                                if (xml.MoveToAttribute("Owner")) |  | ||||||
| //                                { |  | ||||||
| //                                    rdata.userAppearance.Owner = (UUID)xml.Value; |  | ||||||
| //                                    indata = true; |  | ||||||
| //                                } |  | ||||||
|                                 if (xml.MoveToAttribute("Serial")) |  | ||||||
|                                 { |  | ||||||
|                                     rdata.userAppearance.Serial = Convert.ToInt32(xml.Value); |  | ||||||
|                                     indata = true; |  | ||||||
|                                 } |  | ||||||
|                             break; |  | ||||||
| /* |  | ||||||
|                             case "Body" : |  | ||||||
|                                 if (xml.MoveToAttribute("Item")) |  | ||||||
|                                 { |  | ||||||
|                                     rdata.userAppearance.BodyItem = (UUID)xml.Value; |  | ||||||
|                                     indata = true; |  | ||||||
|                                 } |  | ||||||
|                                 if (xml.MoveToAttribute("Asset")) |  | ||||||
|                                 { |  | ||||||
|                                     rdata.userAppearance.BodyAsset = (UUID)xml.Value; |  | ||||||
|                                     indata = true; |  | ||||||
|                                 } |  | ||||||
|                             break; |  | ||||||
|                             case "Skin" : |  | ||||||
|                                 if (xml.MoveToAttribute("Item")) |  | ||||||
|                                 { |  | ||||||
|                                     rdata.userAppearance.SkinItem = (UUID)xml.Value; |  | ||||||
|                                     indata = true; |  | ||||||
|                                 } |  | ||||||
|                                 if (xml.MoveToAttribute("Asset")) |  | ||||||
|                                 { |  | ||||||
|                                     rdata.userAppearance.SkinAsset = (UUID)xml.Value; |  | ||||||
|                                     indata = true; |  | ||||||
|                                 } |  | ||||||
|                             break; |  | ||||||
|                             case "Hair" : |  | ||||||
|                                 if (xml.MoveToAttribute("Item")) |  | ||||||
|                                 { |  | ||||||
|                                     rdata.userAppearance.HairItem = (UUID)xml.Value; |  | ||||||
|                                     indata = true; |  | ||||||
|                                 } |  | ||||||
|                                 if (xml.MoveToAttribute("Asset")) |  | ||||||
|                                 { |  | ||||||
|                                     rdata.userAppearance.HairAsset = (UUID)xml.Value; |  | ||||||
|                                     indata = true; |  | ||||||
|                                 } |  | ||||||
|                             break; |  | ||||||
|                             case "Eyes" : |  | ||||||
|                                 if (xml.MoveToAttribute("Item")) |  | ||||||
|                                 { |  | ||||||
|                                     rdata.userAppearance.EyesItem = (UUID)xml.Value; |  | ||||||
|                                     indata = true; |  | ||||||
|                                 } |  | ||||||
|                                 if (xml.MoveToAttribute("Asset")) |  | ||||||
|                                 { |  | ||||||
|                                     rdata.userAppearance.EyesAsset = (UUID)xml.Value; |  | ||||||
|                                     indata = true; |  | ||||||
|                                 } |  | ||||||
|                             break; |  | ||||||
|                             case "Shirt" : |  | ||||||
|                                 if (xml.MoveToAttribute("Item")) |  | ||||||
|                                 { |  | ||||||
|                                     rdata.userAppearance.ShirtItem = (UUID)xml.Value; |  | ||||||
|                                     indata = true; |  | ||||||
|                                 } |  | ||||||
|                                 if (xml.MoveToAttribute("Asset")) |  | ||||||
|                                 { |  | ||||||
|                                     rdata.userAppearance.ShirtAsset = (UUID)xml.Value; |  | ||||||
|                                     indata = true; |  | ||||||
|                                 } |  | ||||||
|                             break; |  | ||||||
|                             case "Pants" : |  | ||||||
|                                 if (xml.MoveToAttribute("Item")) |  | ||||||
|                                 { |  | ||||||
|                                     rdata.userAppearance.PantsItem = (UUID)xml.Value; |  | ||||||
|                                     indata = true; |  | ||||||
|                                 } |  | ||||||
|                                 if (xml.MoveToAttribute("Asset")) |  | ||||||
|                                 { |  | ||||||
|                                     rdata.userAppearance.PantsAsset = (UUID)xml.Value; |  | ||||||
|                                     indata = true; |  | ||||||
|                                 } |  | ||||||
|                             break; |  | ||||||
|                             case "Shoes" : |  | ||||||
|                                 if (xml.MoveToAttribute("Item")) |  | ||||||
|                                 { |  | ||||||
|                                     rdata.userAppearance.ShoesItem = (UUID)xml.Value; |  | ||||||
|                                     indata = true; |  | ||||||
|                                 } |  | ||||||
|                                 if (xml.MoveToAttribute("Asset")) |  | ||||||
|                                 { |  | ||||||
|                                     rdata.userAppearance.ShoesAsset = (UUID)xml.Value; |  | ||||||
|                                     indata = true; |  | ||||||
|                                 } |  | ||||||
|                             break; |  | ||||||
|                             case "Socks" : |  | ||||||
|                                 if (xml.MoveToAttribute("Item")) |  | ||||||
|                                 { |  | ||||||
|                                     rdata.userAppearance.SocksItem = (UUID)xml.Value; |  | ||||||
|                                     indata = true; |  | ||||||
|                                 } |  | ||||||
|                                 if (xml.MoveToAttribute("Asset")) |  | ||||||
|                                 { |  | ||||||
|                                     rdata.userAppearance.SocksAsset = (UUID)xml.Value; |  | ||||||
|                                     indata = true; |  | ||||||
|                                 } |  | ||||||
|                             break; |  | ||||||
|                             case "Jacket" : |  | ||||||
|                                 if (xml.MoveToAttribute("Item")) |  | ||||||
|                                 { |  | ||||||
|                                     rdata.userAppearance.JacketItem = (UUID)xml.Value; |  | ||||||
|                                     indata = true; |  | ||||||
|                                 } |  | ||||||
|                                 if (xml.MoveToAttribute("Asset")) |  | ||||||
|                                 { |  | ||||||
|                                     rdata.userAppearance.JacketAsset = (UUID)xml.Value; |  | ||||||
|                                     indata = true; |  | ||||||
|                                 } |  | ||||||
|                             break; |  | ||||||
|                             case "Gloves" : |  | ||||||
|                                 if (xml.MoveToAttribute("Item")) |  | ||||||
|                                 { |  | ||||||
|                                     rdata.userAppearance.GlovesItem = (UUID)xml.Value; |  | ||||||
|                                     indata = true; |  | ||||||
|                                 } |  | ||||||
|                                 if (xml.MoveToAttribute("Asset")) |  | ||||||
|                                 { |  | ||||||
|                                     rdata.userAppearance.GlovesAsset = (UUID)xml.Value; |  | ||||||
|                                     indata = true; |  | ||||||
|                                 } |  | ||||||
|                             break; |  | ||||||
|                             case "UnderShirt" : |  | ||||||
|                                 if (xml.MoveToAttribute("Item")) |  | ||||||
|                                 { |  | ||||||
|                                     rdata.userAppearance.UnderShirtItem = (UUID)xml.Value; |  | ||||||
|                                     indata = true; |  | ||||||
|                                 } |  | ||||||
|                                 if (xml.MoveToAttribute("Asset")) |  | ||||||
|                                 { |  | ||||||
|                                     rdata.userAppearance.UnderShirtAsset = (UUID)xml.Value; |  | ||||||
|                                     indata = true; |  | ||||||
|                                 } |  | ||||||
|                             break; |  | ||||||
|                             case "UnderPants" : |  | ||||||
|                                 if (xml.MoveToAttribute("Item")) |  | ||||||
|                                 { |  | ||||||
|                                     rdata.userAppearance.UnderPantsItem = (UUID)xml.Value; |  | ||||||
|                                     indata = true; |  | ||||||
|                                 } |  | ||||||
|                                 if (xml.MoveToAttribute("Asset")) |  | ||||||
|                                 { |  | ||||||
|                                     rdata.userAppearance.UnderPantsAsset = (UUID)xml.Value; |  | ||||||
|                                     indata = true; |  | ||||||
|                                 } |  | ||||||
|                             break; |  | ||||||
|                             case "Skirt" : |  | ||||||
|                                 if (xml.MoveToAttribute("Item")) |  | ||||||
|                                 { |  | ||||||
|                                     rdata.userAppearance.SkirtItem = (UUID)xml.Value; |  | ||||||
|                                     indata = true; |  | ||||||
|                                 } |  | ||||||
|                                 if (xml.MoveToAttribute("Asset")) |  | ||||||
|                                 { |  | ||||||
|                                     rdata.userAppearance.SkirtAsset = (UUID)xml.Value; |  | ||||||
|                                     indata = true; |  | ||||||
|                                 } |  | ||||||
|                             break; |  | ||||||
| */ |  | ||||||
|                             case "Attachment" : |  | ||||||
|                                 { |  | ||||||
| 
 |  | ||||||
|                                     int  ap; |  | ||||||
|                                     UUID asset; |  | ||||||
|                                     UUID item; |  | ||||||
| 
 |  | ||||||
|                                     if (xml.MoveToAttribute("AtPoint")) |  | ||||||
|                                     { |  | ||||||
|                                         ap = Convert.ToInt32(xml.Value); |  | ||||||
|                                         if (xml.MoveToAttribute("Asset")) |  | ||||||
|                                         { |  | ||||||
|                                             asset = new UUID(xml.Value); |  | ||||||
|                                             if (xml.MoveToAttribute("Asset")) |  | ||||||
|                                             { |  | ||||||
|                                                 item = new UUID(xml.Value); |  | ||||||
|                                                 rdata.userAppearance.SetAttachment(ap, item, asset); |  | ||||||
|                                                 indata = true; |  | ||||||
|                                             } |  | ||||||
|                                         } |  | ||||||
|                                     } |  | ||||||
|                                 } |  | ||||||
|                             break; |  | ||||||
|                             case "Texture" : |  | ||||||
|                                 if (xml.MoveToAttribute("Default")) |  | ||||||
|                                 { |  | ||||||
|                                     rdata.userAppearance.Texture = new Primitive.TextureEntry(new UUID(xml.Value)); |  | ||||||
|                                     indata = true; |  | ||||||
|                                 } |  | ||||||
|                             break; |  | ||||||
|                             case "Face" : |  | ||||||
|                                 { |  | ||||||
|                                     uint index; |  | ||||||
|                                     if (xml.MoveToAttribute("Index")) |  | ||||||
|                                     { |  | ||||||
|                                         index = Convert.ToUInt32(xml.Value); |  | ||||||
|                                         if (xml.MoveToAttribute("Id")) |  | ||||||
|                                         { |  | ||||||
|                                             rdata.userAppearance.Texture.CreateFace(index).TextureID = new UUID(xml.Value); |  | ||||||
|                                             indata = true; |  | ||||||
|                                         } |  | ||||||
|                                     } |  | ||||||
|                                 } |  | ||||||
|                             break; |  | ||||||
|                             case "VisualParameters" : |  | ||||||
|                                 { |  | ||||||
|                                     xml.ReadContentAsBase64(rdata.userAppearance.VisualParams, |  | ||||||
|                                                             0, rdata.userAppearance.VisualParams.Length); |  | ||||||
|                                     indata = true; |  | ||||||
|                                 } |  | ||||||
|                             break; |  | ||||||
|                         }  |  | ||||||
|                     break; |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
| 
 |  | ||||||
|             return indata; |  | ||||||
| 
 |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         private void FormatPart(AppearanceRequestData rdata, string part, UUID item, UUID asset) |  | ||||||
|         { |  | ||||||
|             if (item != UUID.Zero || asset != UUID.Zero) |  | ||||||
|             { |  | ||||||
|                 rdata.writer.WriteStartElement(part); |  | ||||||
|                 if (item  != UUID.Zero) |  | ||||||
|                 { |  | ||||||
|                     rdata.writer.WriteAttributeString("Item",item.ToString()); |  | ||||||
|                 } |  | ||||||
| 
 |  | ||||||
|                 if (asset != UUID.Zero) |  | ||||||
|                 { |  | ||||||
|                     rdata.writer.WriteAttributeString("Asset",asset.ToString()); |  | ||||||
|                 } |  | ||||||
|                 rdata.writer.WriteEndElement(); |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         private void FormatUserAppearance(AppearanceRequestData rdata) |  | ||||||
|         { |  | ||||||
| 
 |  | ||||||
|             Rest.Log.DebugFormat("{0} FormatUserAppearance", MsgId); |  | ||||||
| 
 |  | ||||||
|             if (rdata.userAppearance != null) |  | ||||||
|             { |  | ||||||
| 
 |  | ||||||
|                 Rest.Log.DebugFormat("{0} FormatUserAppearance: appearance object exists", MsgId); |  | ||||||
|                 rdata.writer.WriteStartElement("Appearance"); |  | ||||||
| 
 |  | ||||||
|                 rdata.writer.WriteAttributeString("Height", rdata.userAppearance.AvatarHeight.ToString()); |  | ||||||
| //                if (rdata.userAppearance.Owner != UUID.Zero) |  | ||||||
| //                    rdata.writer.WriteAttributeString("Owner", rdata.userAppearance.Owner.ToString()); |  | ||||||
|                 rdata.writer.WriteAttributeString("Serial", rdata.userAppearance.Serial.ToString()); |  | ||||||
| 
 |  | ||||||
| /* |  | ||||||
|                 FormatPart(rdata, "Body", rdata.userAppearance.BodyItem, rdata.userAppearance.BodyAsset); |  | ||||||
|                 FormatPart(rdata, "Skin", rdata.userAppearance.SkinItem, rdata.userAppearance.SkinAsset); |  | ||||||
|                 FormatPart(rdata, "Hair", rdata.userAppearance.HairItem, rdata.userAppearance.HairAsset); |  | ||||||
|                 FormatPart(rdata, "Eyes", rdata.userAppearance.EyesItem, rdata.userAppearance.EyesAsset); |  | ||||||
| 
 |  | ||||||
|                 FormatPart(rdata, "Shirt", rdata.userAppearance.ShirtItem, rdata.userAppearance.ShirtAsset); |  | ||||||
|                 FormatPart(rdata, "Pants", rdata.userAppearance.PantsItem, rdata.userAppearance.PantsAsset); |  | ||||||
|                 FormatPart(rdata, "Skirt", rdata.userAppearance.SkirtItem, rdata.userAppearance.SkirtAsset); |  | ||||||
|                 FormatPart(rdata, "Shoes", rdata.userAppearance.ShoesItem, rdata.userAppearance.ShoesAsset); |  | ||||||
|                 FormatPart(rdata, "Socks", rdata.userAppearance.SocksItem, rdata.userAppearance.SocksAsset); |  | ||||||
| 
 |  | ||||||
|                 FormatPart(rdata, "Jacket", rdata.userAppearance.JacketItem, rdata.userAppearance.JacketAsset); |  | ||||||
|                 FormatPart(rdata, "Gloves", rdata.userAppearance.GlovesItem, rdata.userAppearance.GlovesAsset); |  | ||||||
| 
 |  | ||||||
|                 FormatPart(rdata, "UnderShirt", rdata.userAppearance.UnderShirtItem, rdata.userAppearance.UnderShirtAsset); |  | ||||||
|                 FormatPart(rdata, "UnderPants", rdata.userAppearance.UnderPantsItem, rdata.userAppearance.UnderPantsAsset); |  | ||||||
| */ |  | ||||||
|                 Rest.Log.DebugFormat("{0} FormatUserAppearance: Formatting attachments", MsgId); |  | ||||||
| 
 |  | ||||||
|                 rdata.writer.WriteStartElement("Attachments"); |  | ||||||
|                 List<AvatarAttachment> attachments = rdata.userAppearance.GetAttachments(); |  | ||||||
|                 foreach (AvatarAttachment attach in attachments) |  | ||||||
|                 { |  | ||||||
|                     rdata.writer.WriteStartElement("Attachment"); |  | ||||||
|                     rdata.writer.WriteAttributeString("AtPoint", attach.AttachPoint.ToString()); |  | ||||||
|                     rdata.writer.WriteAttributeString("Item", attach.ItemID.ToString()); |  | ||||||
|                     rdata.writer.WriteAttributeString("Asset", attach.AssetID.ToString()); |  | ||||||
|                     rdata.writer.WriteEndElement(); |  | ||||||
|                 } |  | ||||||
|                 rdata.writer.WriteEndElement(); |  | ||||||
| 
 |  | ||||||
|                 Primitive.TextureEntry texture = rdata.userAppearance.Texture; |  | ||||||
| 
 |  | ||||||
|                 if (texture != null && (texture.DefaultTexture != null || texture.FaceTextures != null)) |  | ||||||
|                 { |  | ||||||
|                     Rest.Log.DebugFormat("{0} FormatUserAppearance: Formatting textures", MsgId); |  | ||||||
| 
 |  | ||||||
|                     rdata.writer.WriteStartElement("Texture"); |  | ||||||
| 
 |  | ||||||
|                     if (texture.DefaultTexture != null) |  | ||||||
|                     { |  | ||||||
|                         Rest.Log.DebugFormat("{0} FormatUserAppearance: Formatting default texture", MsgId); |  | ||||||
|                         rdata.writer.WriteAttributeString("Default", |  | ||||||
|                             texture.DefaultTexture.TextureID.ToString()); |  | ||||||
|                     } |  | ||||||
| 
 |  | ||||||
|                     if (texture.FaceTextures != null) |  | ||||||
|                     { |  | ||||||
| 
 |  | ||||||
|                         Rest.Log.DebugFormat("{0} FormatUserAppearance: Formatting face textures", MsgId); |  | ||||||
| 
 |  | ||||||
|                         for (int i=0; i<texture.FaceTextures.Length;i++) |  | ||||||
|                         { |  | ||||||
|                             if (texture.FaceTextures[i] != null) |  | ||||||
|                             { |  | ||||||
|                                 rdata.writer.WriteStartElement("Face"); |  | ||||||
|                                 rdata.writer.WriteAttributeString("Index", i.ToString()); |  | ||||||
|                                 rdata.writer.WriteAttributeString("Id", |  | ||||||
|                                         texture.FaceTextures[i].TextureID.ToString()); |  | ||||||
|                                 rdata.writer.WriteEndElement(); |  | ||||||
|                             } |  | ||||||
|                         } |  | ||||||
|                     } |  | ||||||
| 
 |  | ||||||
|                     rdata.writer.WriteEndElement(); |  | ||||||
|                 } |  | ||||||
| 
 |  | ||||||
|                 Rest.Log.DebugFormat("{0} FormatUserAppearance: Formatting visual parameters", MsgId); |  | ||||||
| 
 |  | ||||||
|                 rdata.writer.WriteStartElement("VisualParameters"); |  | ||||||
|                 rdata.writer.WriteBase64(rdata.userAppearance.VisualParams,0, |  | ||||||
|                             rdata.userAppearance.VisualParams.Length); |  | ||||||
|                 rdata.writer.WriteEndElement(); |  | ||||||
|                 rdata.writer.WriteFullEndElement(); |  | ||||||
|             } |  | ||||||
| 
 |  | ||||||
|             Rest.Log.DebugFormat("{0} FormatUserAppearance: completed", MsgId); |  | ||||||
| 
 |  | ||||||
|             return; |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         #region appearance RequestData extension |  | ||||||
| 
 |  | ||||||
|         internal class AppearanceRequestData : RequestData |  | ||||||
|         { |  | ||||||
| 
 |  | ||||||
|             /// <summary> |  | ||||||
|             /// These are the inventory specific request/response state |  | ||||||
|             /// extensions. |  | ||||||
|             /// </summary> |  | ||||||
| 
 |  | ||||||
|             internal UUID                       uuid = UUID.Zero; |  | ||||||
|             internal UserProfileData     userProfile = null; |  | ||||||
|             internal AvatarAppearance userAppearance = null; |  | ||||||
| 
 |  | ||||||
|             internal AppearanceRequestData(OSHttpRequest request, OSHttpResponse response, string prefix) |  | ||||||
|                 : base(request, response, prefix) |  | ||||||
|             { |  | ||||||
|             } |  | ||||||
| 
 |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         #endregion Appearance RequestData extension |  | ||||||
| 
 |  | ||||||
|     } |  | ||||||
| } |  | ||||||
|  | @ -1,383 +0,0 @@ | ||||||
| /* |  | ||||||
|  * Copyright (c) Contributors, http://opensimulator.org/ |  | ||||||
|  * See CONTRIBUTORS.TXT for a full list of copyright holders. |  | ||||||
|  * |  | ||||||
|  * Redistribution and use in source and binary forms, with or without |  | ||||||
|  * modification, are permitted provided that the following conditions are met: |  | ||||||
|  *     * Redistributions of source code must retain the above copyright |  | ||||||
|  *       notice, this list of conditions and the following disclaimer. |  | ||||||
|  *     * Redistributions in binary form must reproduce the above copyright |  | ||||||
|  *       notice, this list of conditions and the following disclaimer in the |  | ||||||
|  *       documentation and/or other materials provided with the distribution. |  | ||||||
|  *     * Neither the name of the OpenSimulator Project nor the |  | ||||||
|  *       names of its contributors may be used to endorse or promote products |  | ||||||
|  *       derived from this software without specific prior written permission. |  | ||||||
|  * |  | ||||||
|  * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY |  | ||||||
|  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |  | ||||||
|  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |  | ||||||
|  * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY |  | ||||||
|  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |  | ||||||
|  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |  | ||||||
|  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |  | ||||||
|  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |  | ||||||
|  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |  | ||||||
|  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |  | ||||||
|  */ |  | ||||||
| 
 |  | ||||||
| using System; |  | ||||||
| using System.Xml; |  | ||||||
| using OpenMetaverse; |  | ||||||
| using OpenSim.Framework; |  | ||||||
| using OpenSim.Framework.Servers; |  | ||||||
| using OpenSim.Framework.Servers.HttpServer; |  | ||||||
| 
 |  | ||||||
| namespace OpenSim.ApplicationPlugins.Rest.Inventory |  | ||||||
| { |  | ||||||
|     public class RestAssetServices : IRest |  | ||||||
|     { |  | ||||||
|         private bool    enabled = false; |  | ||||||
|         private string  qPrefix = "assets"; |  | ||||||
| 
 |  | ||||||
|         // A simple constructor is used to handle any once-only |  | ||||||
|         // initialization of working classes. |  | ||||||
| 
 |  | ||||||
|         public RestAssetServices() |  | ||||||
|         { |  | ||||||
|             Rest.Log.InfoFormat("{0} Asset services initializing", MsgId); |  | ||||||
|             Rest.Log.InfoFormat("{0} Using REST Implementation Version {1}", MsgId, Rest.Version); |  | ||||||
| 
 |  | ||||||
|             // If the handler specifies a relative path for its domain |  | ||||||
|             // then we must add the standard absolute prefix, e.g. /admin |  | ||||||
| 
 |  | ||||||
|             if (!qPrefix.StartsWith(Rest.UrlPathSeparator)) |  | ||||||
|             { |  | ||||||
|                 Rest.Log.InfoFormat("{0} Prefixing domain name ({1})", MsgId, qPrefix); |  | ||||||
|                 qPrefix = String.Format("{0}{1}{2}", Rest.Prefix, Rest.UrlPathSeparator, qPrefix); |  | ||||||
|                 Rest.Log.InfoFormat("{0} Fully qualified domain name is <{1}>", MsgId, qPrefix); |  | ||||||
|             } |  | ||||||
| 
 |  | ||||||
|             // Register interface using the fully-qualified prefix |  | ||||||
| 
 |  | ||||||
|             Rest.Plugin.AddPathHandler(DoAsset, qPrefix, Allocate); |  | ||||||
| 
 |  | ||||||
|             // Activate if all went OK |  | ||||||
| 
 |  | ||||||
|             enabled = true; |  | ||||||
| 
 |  | ||||||
|             Rest.Log.InfoFormat("{0} Asset services initialization complete", MsgId); |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         // Post-construction, pre-enabled initialization opportunity |  | ||||||
|         // Not currently exploited. |  | ||||||
| 
 |  | ||||||
|         public void Initialize() |  | ||||||
|         { |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         // Called by the plug-in to halt REST processing. Local processing is |  | ||||||
|         // disabled, and control blocks until all current processing has |  | ||||||
|         // completed. No new processing will be started |  | ||||||
| 
 |  | ||||||
|         public void Close() |  | ||||||
|         { |  | ||||||
|             enabled = false; |  | ||||||
|             Rest.Log.InfoFormat("{0} Asset services ({1}) closing down", MsgId, qPrefix); |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         // Properties |  | ||||||
| 
 |  | ||||||
|         internal string MsgId |  | ||||||
|         { |  | ||||||
|             get { return Rest.MsgId; } |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         #region Interface |  | ||||||
| 
 |  | ||||||
|         private RequestData Allocate(OSHttpRequest request, OSHttpResponse response, string prefix) |  | ||||||
|         { |  | ||||||
|             return (RequestData) new AssetRequestData(request, response, prefix); |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         // Asset Handler |  | ||||||
| 
 |  | ||||||
|         private void DoAsset(RequestData rparm) |  | ||||||
|         { |  | ||||||
|             if (!enabled) return; |  | ||||||
| 
 |  | ||||||
|             AssetRequestData rdata = (AssetRequestData) rparm; |  | ||||||
| 
 |  | ||||||
|             Rest.Log.DebugFormat("{0} REST Asset handler ({1}) ENTRY", MsgId, qPrefix); |  | ||||||
| 
 |  | ||||||
|             // Now that we know this is a serious attempt to |  | ||||||
|             // access inventory data, we should find out who |  | ||||||
|             // is asking, and make sure they are authorized |  | ||||||
|             // to do so. We need to validate the caller's |  | ||||||
|             // identity before revealing anything about the |  | ||||||
|             // status quo. Authenticate throws an exception |  | ||||||
|             // via Fail if no identity information is present. |  | ||||||
|             // |  | ||||||
|             // With the present HTTP server we can't use the |  | ||||||
|             // builtin authentication mechanisms because they |  | ||||||
|             // would be enforced for all in-bound requests. |  | ||||||
|             // Instead we look at the headers ourselves and |  | ||||||
|             // handle authentication directly. |  | ||||||
| 
 |  | ||||||
|             try |  | ||||||
|             { |  | ||||||
|                 if (!rdata.IsAuthenticated) |  | ||||||
|                 { |  | ||||||
|                     rdata.Fail(Rest.HttpStatusCodeNotAuthorized, String.Format("user \"{0}\" could not be authenticated")); |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
|             catch (RestException e) |  | ||||||
|             { |  | ||||||
|                 if (e.statusCode == Rest.HttpStatusCodeNotAuthorized) |  | ||||||
|                 { |  | ||||||
|                     Rest.Log.WarnFormat("{0} User not authenticated", MsgId); |  | ||||||
|                     Rest.Log.DebugFormat("{0} Authorization header: {1}", MsgId, |  | ||||||
|                                          rdata.request.Headers.Get("Authorization")); |  | ||||||
|                 } |  | ||||||
|                 else |  | ||||||
|                 { |  | ||||||
|                     Rest.Log.ErrorFormat("{0} User authentication failed", MsgId); |  | ||||||
|                     Rest.Log.DebugFormat("{0} Authorization header: {1}", MsgId, |  | ||||||
|                                          rdata.request.Headers.Get("Authorization")); |  | ||||||
|                 } |  | ||||||
|                 throw (e); |  | ||||||
|             } |  | ||||||
| 
 |  | ||||||
|             // Remove the prefix and what's left are the parameters. If we don't have |  | ||||||
|             // the parameters we need, fail the request. Parameters do NOT include |  | ||||||
|             // any supplied query values. |  | ||||||
| 
 |  | ||||||
|             if (rdata.Parameters.Length > 0) |  | ||||||
|             { |  | ||||||
|                 switch (rdata.method) |  | ||||||
|                 { |  | ||||||
|                 case "get" : |  | ||||||
|                     DoGet(rdata); |  | ||||||
|                     break; |  | ||||||
|                 case "put" : |  | ||||||
|                     DoPut(rdata); |  | ||||||
|                     break; |  | ||||||
|                 case "post" : |  | ||||||
|                     DoPost(rdata); |  | ||||||
|                     break; |  | ||||||
|                 case "delete" : |  | ||||||
|                 default : |  | ||||||
|                     Rest.Log.WarnFormat("{0} Asset: Method not supported: {1}", |  | ||||||
|                                         MsgId, rdata.method); |  | ||||||
|                     rdata.Fail(Rest.HttpStatusCodeBadRequest,String.Format("method <{0}> not supported", rdata.method)); |  | ||||||
|                     break; |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
|             else |  | ||||||
|             { |  | ||||||
|                 Rest.Log.WarnFormat("{0} Asset: No agent information provided", MsgId); |  | ||||||
|                 rdata.Fail(Rest.HttpStatusCodeBadRequest, "no agent information provided"); |  | ||||||
|             } |  | ||||||
| 
 |  | ||||||
|             Rest.Log.DebugFormat("{0} REST Asset handler EXIT", MsgId); |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         #endregion Interface |  | ||||||
| 
 |  | ||||||
|         /// <summary> |  | ||||||
|         /// The only parameter we recognize is a UUID.If an asset with this identification is |  | ||||||
|         /// found, it's content, base-64 encoded, is returned to the client. |  | ||||||
|         /// </summary> |  | ||||||
| 
 |  | ||||||
|         private void DoGet(AssetRequestData rdata) |  | ||||||
|         { |  | ||||||
|             Rest.Log.DebugFormat("{0} REST Asset handler, Method = <{1}> ENTRY", MsgId, rdata.method); |  | ||||||
| 
 |  | ||||||
|             if (rdata.Parameters.Length == 1) |  | ||||||
|             { |  | ||||||
|                 UUID uuid = new UUID(rdata.Parameters[0]); |  | ||||||
|                 AssetBase asset = Rest.AssetServices.Get(uuid.ToString()); |  | ||||||
| 
 |  | ||||||
|                 if (asset != null) |  | ||||||
|                 { |  | ||||||
|                     Rest.Log.DebugFormat("{0}  Asset located <{1}>", MsgId, rdata.Parameters[0]); |  | ||||||
| 
 |  | ||||||
|                     rdata.initXmlWriter(); |  | ||||||
| 
 |  | ||||||
|                     rdata.writer.WriteStartElement(String.Empty,"Asset",String.Empty); |  | ||||||
| 
 |  | ||||||
|                     rdata.writer.WriteAttributeString("id", asset.ID); |  | ||||||
|                     rdata.writer.WriteAttributeString("name", asset.Name); |  | ||||||
|                     rdata.writer.WriteAttributeString("desc", asset.Description); |  | ||||||
|                     rdata.writer.WriteAttributeString("type", asset.Type.ToString()); |  | ||||||
|                     rdata.writer.WriteAttributeString("local", asset.Local.ToString()); |  | ||||||
|                     rdata.writer.WriteAttributeString("temporary", asset.Temporary.ToString()); |  | ||||||
| 
 |  | ||||||
|                     rdata.writer.WriteBase64(asset.Data,0,asset.Data.Length); |  | ||||||
| 
 |  | ||||||
|                     rdata.writer.WriteFullEndElement(); |  | ||||||
| 
 |  | ||||||
|                 } |  | ||||||
|                 else |  | ||||||
|                 { |  | ||||||
|                     Rest.Log.DebugFormat("{0} Invalid parameters: <{1}>", MsgId, rdata.path); |  | ||||||
|                     rdata.Fail(Rest.HttpStatusCodeNotFound, "invalid parameters"); |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
| 
 |  | ||||||
|             rdata.Complete(); |  | ||||||
|             rdata.Respond(String.Format("Asset <{0}> : Normal completion", rdata.method)); |  | ||||||
| 
 |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         /// <summary> |  | ||||||
|         /// UPDATE existing item, if it exists. URI identifies the item in question. |  | ||||||
|         /// The only parameter we recognize is a UUID. The enclosed asset data (base-64 encoded) |  | ||||||
|         /// is decoded and stored in the database, identified by the supplied UUID. |  | ||||||
|         /// </summary> |  | ||||||
|         private void DoPut(AssetRequestData rdata) |  | ||||||
|         { |  | ||||||
|             bool modified = false; |  | ||||||
|             bool created  = false; |  | ||||||
| 
 |  | ||||||
|             AssetBase asset = null; |  | ||||||
| 
 |  | ||||||
|             Rest.Log.DebugFormat("{0} REST Asset handler, Method = <{1}> ENTRY", MsgId, rdata.method); |  | ||||||
| 
 |  | ||||||
|             if (rdata.Parameters.Length == 1) |  | ||||||
|             { |  | ||||||
| 
 |  | ||||||
|                 rdata.initXmlReader(); |  | ||||||
|                 XmlReader xml = rdata.reader; |  | ||||||
| 
 |  | ||||||
|                 if (!xml.ReadToFollowing("Asset")) |  | ||||||
|                 { |  | ||||||
|                     Rest.Log.DebugFormat("{0} Invalid request data: <{1}>", MsgId, rdata.path); |  | ||||||
|                     rdata.Fail(Rest.HttpStatusCodeBadRequest,"invalid request data"); |  | ||||||
|                 } |  | ||||||
| 
 |  | ||||||
|                 UUID uuid = new UUID(rdata.Parameters[0]); |  | ||||||
|                 asset = Rest.AssetServices.Get(uuid.ToString()); |  | ||||||
| 
 |  | ||||||
|                 modified = (asset != null); |  | ||||||
|                 created  = !modified; |  | ||||||
| 
 |  | ||||||
|                 asset = new AssetBase(uuid, xml.GetAttribute("name"), SByte.Parse(xml.GetAttribute("type")), UUID.Zero.ToString()); |  | ||||||
|                 asset.Description = xml.GetAttribute("desc"); |  | ||||||
|                 asset.Local       = Int32.Parse(xml.GetAttribute("local")) != 0; |  | ||||||
|                 asset.Temporary   = Int32.Parse(xml.GetAttribute("temporary")) != 0; |  | ||||||
|                 asset.Data        = Convert.FromBase64String(xml.ReadElementContentAsString("Asset", "")); |  | ||||||
| 
 |  | ||||||
|                 if (asset.ID != rdata.Parameters[0]) |  | ||||||
|                 { |  | ||||||
|                     Rest.Log.WarnFormat("{0} URI and payload disagree on UUID U:{1} vs P:{2}", |  | ||||||
|                                         MsgId, rdata.Parameters[0], asset.ID); |  | ||||||
|                 } |  | ||||||
| 
 |  | ||||||
|                 Rest.AssetServices.Store(asset); |  | ||||||
| 
 |  | ||||||
|             } |  | ||||||
|             else |  | ||||||
|             { |  | ||||||
|                 Rest.Log.DebugFormat("{0} Invalid parameters: <{1}>", MsgId, rdata.path); |  | ||||||
|                 rdata.Fail(Rest.HttpStatusCodeNotFound, "invalid parameters"); |  | ||||||
|             } |  | ||||||
| 
 |  | ||||||
|             if (created) |  | ||||||
|             { |  | ||||||
|                 rdata.appendStatus(String.Format("<p> Created asset {0}, UUID {1} <p>", asset.Name, asset.FullID)); |  | ||||||
|                 rdata.Complete(Rest.HttpStatusCodeCreated); |  | ||||||
|             } |  | ||||||
|             else |  | ||||||
|             { |  | ||||||
|                 if (modified) |  | ||||||
|                 { |  | ||||||
|                     rdata.appendStatus(String.Format("<p> Modified asset {0}, UUID {1} <p>", asset.Name, asset.FullID)); |  | ||||||
|                     rdata.Complete(Rest.HttpStatusCodeOK); |  | ||||||
|                 } |  | ||||||
|                 else |  | ||||||
|                 { |  | ||||||
|                     rdata.Complete(Rest.HttpStatusCodeNoContent); |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
| 
 |  | ||||||
|             rdata.Respond(String.Format("Asset {0} : Normal completion", rdata.method)); |  | ||||||
| 
 |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         /// <summary> |  | ||||||
|         /// CREATE new item, replace if it exists. URI identifies the context for the item in question. |  | ||||||
|         /// No parameters are required for POST, just thepayload. |  | ||||||
|         /// </summary> |  | ||||||
| 
 |  | ||||||
|         private void DoPost(AssetRequestData rdata) |  | ||||||
|         { |  | ||||||
| 
 |  | ||||||
|             bool modified = false; |  | ||||||
|             bool created  = false; |  | ||||||
| 
 |  | ||||||
|             Rest.Log.DebugFormat("{0} REST Asset handler, Method = <{1}> ENTRY", MsgId, rdata.method); |  | ||||||
| 
 |  | ||||||
|             if (rdata.Parameters.Length != 0) |  | ||||||
|             { |  | ||||||
|                 Rest.Log.WarnFormat("{0} Parameters ignored <{1}>", MsgId, rdata.path); |  | ||||||
|                 Rest.Log.InfoFormat("{0} POST of an asset has no parameters", MsgId, rdata.path); |  | ||||||
|             } |  | ||||||
| 
 |  | ||||||
|             rdata.initXmlReader(); |  | ||||||
|             XmlReader xml = rdata.reader; |  | ||||||
| 
 |  | ||||||
|             if (!xml.ReadToFollowing("Asset")) |  | ||||||
|             { |  | ||||||
|                 Rest.Log.DebugFormat("{0} Invalid request data: <{1}>", MsgId, rdata.path); |  | ||||||
|                 rdata.Fail(Rest.HttpStatusCodeBadRequest,"invalid request data"); |  | ||||||
|             } |  | ||||||
| 
 |  | ||||||
|             UUID uuid = new UUID(xml.GetAttribute("id")); |  | ||||||
|             AssetBase asset = Rest.AssetServices.Get(uuid.ToString()); |  | ||||||
| 
 |  | ||||||
|             modified = (asset != null); |  | ||||||
|             created  = !modified; |  | ||||||
| 
 |  | ||||||
|             asset             = new AssetBase(uuid, xml.GetAttribute("name"), SByte.Parse(xml.GetAttribute("type")), UUID.Zero.ToString()); |  | ||||||
|             asset.Description = xml.GetAttribute("desc"); |  | ||||||
|             asset.Local       = Int32.Parse(xml.GetAttribute("local")) != 0; |  | ||||||
|             asset.Temporary   = Int32.Parse(xml.GetAttribute("temporary")) != 0; |  | ||||||
|             asset.Data        = Convert.FromBase64String(xml.ReadElementContentAsString("Asset", "")); |  | ||||||
| 
 |  | ||||||
|             Rest.AssetServices.Store(asset); |  | ||||||
| 
 |  | ||||||
|             if (created) |  | ||||||
|             { |  | ||||||
|                 rdata.appendStatus(String.Format("<p> Created asset {0}, UUID {1} <p>", asset.Name, asset.FullID)); |  | ||||||
|                 rdata.Complete(Rest.HttpStatusCodeCreated); |  | ||||||
|             } |  | ||||||
|             else |  | ||||||
|             { |  | ||||||
|                 if (modified) |  | ||||||
|                 { |  | ||||||
|                     rdata.appendStatus(String.Format("<p> Modified asset {0}, UUID {1} <p>", asset.Name, asset.FullID)); |  | ||||||
|                     rdata.Complete(Rest.HttpStatusCodeOK); |  | ||||||
|                 } |  | ||||||
|                 else |  | ||||||
|                 { |  | ||||||
|                     rdata.Complete(Rest.HttpStatusCodeNoContent); |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
| 
 |  | ||||||
|             rdata.Respond(String.Format("Asset {0} : Normal completion", rdata.method)); |  | ||||||
| 
 |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         /// <summary> |  | ||||||
|         /// Asset processing has no special data area requirements. |  | ||||||
|         /// </summary> |  | ||||||
| 
 |  | ||||||
|         internal class AssetRequestData : RequestData |  | ||||||
|         { |  | ||||||
|             internal AssetRequestData(OSHttpRequest request, OSHttpResponse response, string prefix) |  | ||||||
|                 : base(request, response, prefix) |  | ||||||
|             { |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| } |  | ||||||
|  | @ -1,448 +0,0 @@ | ||||||
| /* |  | ||||||
|  * Copyright (c) Contributors, http://opensimulator.org/ |  | ||||||
|  * See CONTRIBUTORS.TXT for a full list of copyright holders. |  | ||||||
|  * |  | ||||||
|  * Redistribution and use in source and binary forms, with or without |  | ||||||
|  * modification, are permitted provided that the following conditions are met: |  | ||||||
|  *     * Redistributions of source code must retain the above copyright |  | ||||||
|  *       notice, this list of conditions and the following disclaimer. |  | ||||||
|  *     * Redistributions in binary form must reproduce the above copyright |  | ||||||
|  *       notice, this list of conditions and the following disclaimer in the |  | ||||||
|  *       documentation and/or other materials provided with the distribution. |  | ||||||
|  *     * Neither the name of the OpenSimulator Project nor the |  | ||||||
|  *       names of its contributors may be used to endorse or promote products |  | ||||||
|  *       derived from this software without specific prior written permission. |  | ||||||
|  * |  | ||||||
|  * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY |  | ||||||
|  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |  | ||||||
|  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |  | ||||||
|  * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY |  | ||||||
|  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |  | ||||||
|  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |  | ||||||
|  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |  | ||||||
|  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |  | ||||||
|  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |  | ||||||
|  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |  | ||||||
|  */ |  | ||||||
| 
 |  | ||||||
| using System; |  | ||||||
| using System.Xml; |  | ||||||
| using System.IO; |  | ||||||
| using OpenMetaverse; |  | ||||||
| using OpenSim.Framework; |  | ||||||
| using OpenSim.Framework.Servers; |  | ||||||
| using OpenSim.Framework.Servers.HttpServer; |  | ||||||
| 
 |  | ||||||
| namespace OpenSim.ApplicationPlugins.Rest.Inventory |  | ||||||
| { |  | ||||||
|     public class RestFileServices : IRest |  | ||||||
|     { |  | ||||||
|         private bool    enabled = false; |  | ||||||
|         private string  qPrefix = "files"; |  | ||||||
| 
 |  | ||||||
|         // A simple constructor is used to handle any once-only |  | ||||||
|         // initialization of working classes. |  | ||||||
| 
 |  | ||||||
|         public RestFileServices() |  | ||||||
|         { |  | ||||||
|             Rest.Log.InfoFormat("{0} File services initializing", MsgId); |  | ||||||
|             Rest.Log.InfoFormat("{0} Using REST Implementation Version {1}", MsgId, Rest.Version); |  | ||||||
| 
 |  | ||||||
|             // If the handler specifies a relative path for its domain |  | ||||||
|             // then we must add the standard absolute prefix, e.g. /admin |  | ||||||
| 
 |  | ||||||
|             if (!qPrefix.StartsWith(Rest.UrlPathSeparator)) |  | ||||||
|             { |  | ||||||
|                 Rest.Log.InfoFormat("{0} Prefixing domain name ({1})", MsgId, qPrefix); |  | ||||||
|                 qPrefix = String.Format("{0}{1}{2}", Rest.Prefix, Rest.UrlPathSeparator, qPrefix); |  | ||||||
|                 Rest.Log.InfoFormat("{0} Fully qualified domain name is <{1}>", MsgId, qPrefix); |  | ||||||
|             } |  | ||||||
| 
 |  | ||||||
|             // Register interface using the fully-qualified prefix |  | ||||||
| 
 |  | ||||||
|             Rest.Plugin.AddPathHandler(DoFile, qPrefix, Allocate); |  | ||||||
| 
 |  | ||||||
|             // Activate if all went OK |  | ||||||
| 
 |  | ||||||
|             enabled = true; |  | ||||||
| 
 |  | ||||||
|             Rest.Log.InfoFormat("{0} File services initialization complete", MsgId); |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         // Post-construction, pre-enabled initialization opportunity |  | ||||||
|         // Not currently exploited. |  | ||||||
| 
 |  | ||||||
|         public void Initialize() |  | ||||||
|         { |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         // Called by the plug-in to halt REST processing. Local processing is |  | ||||||
|         // disabled, and control blocks until all current processing has |  | ||||||
|         // completed. No new processing will be started |  | ||||||
| 
 |  | ||||||
|         public void Close() |  | ||||||
|         { |  | ||||||
|             enabled = false; |  | ||||||
|             Rest.Log.InfoFormat("{0} File services ({1}) closing down", MsgId, qPrefix); |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         // Properties |  | ||||||
| 
 |  | ||||||
|         internal string MsgId |  | ||||||
|         { |  | ||||||
|             get { return Rest.MsgId; } |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         #region Interface |  | ||||||
| 
 |  | ||||||
|         private RequestData Allocate(OSHttpRequest request, OSHttpResponse response, string prefix) |  | ||||||
|         { |  | ||||||
|             return (RequestData) new FileRequestData(request, response, prefix); |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         // Asset Handler |  | ||||||
| 
 |  | ||||||
|         private void DoFile(RequestData rparm) |  | ||||||
|         { |  | ||||||
|             if (!enabled) return; |  | ||||||
| 
 |  | ||||||
|             FileRequestData rdata = (FileRequestData) rparm; |  | ||||||
| 
 |  | ||||||
|             Rest.Log.DebugFormat("{0} REST File handler ({1}) ENTRY", MsgId, qPrefix); |  | ||||||
| 
 |  | ||||||
|             // Now that we know this is a serious attempt to |  | ||||||
|             // access file data, we should find out who |  | ||||||
|             // is asking, and make sure they are authorized |  | ||||||
|             // to do so. We need to validate the caller's |  | ||||||
|             // identity before revealing anything about the |  | ||||||
|             // status quo. Authenticate throws an exception |  | ||||||
|             // via Fail if no identity information is present. |  | ||||||
|             // |  | ||||||
|             // With the present HTTP server we can't use the |  | ||||||
|             // builtin authentication mechanisms because they |  | ||||||
|             // would be enforced for all in-bound requests. |  | ||||||
|             // Instead we look at the headers ourselves and |  | ||||||
|             // handle authentication directly. |  | ||||||
| 
 |  | ||||||
|             try |  | ||||||
|             { |  | ||||||
|                 if (!rdata.IsAuthenticated) |  | ||||||
|                 { |  | ||||||
|                     rdata.Fail(Rest.HttpStatusCodeNotAuthorized, String.Format("user \"{0}\" could not be authenticated")); |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
|             catch (RestException e) |  | ||||||
|             { |  | ||||||
|                 if (e.statusCode == Rest.HttpStatusCodeNotAuthorized) |  | ||||||
|                 { |  | ||||||
|                     Rest.Log.WarnFormat("{0} User not authenticated", MsgId); |  | ||||||
|                     Rest.Log.DebugFormat("{0} Authorization header: {1}", MsgId, |  | ||||||
|                                          rdata.request.Headers.Get("Authorization")); |  | ||||||
|                 } |  | ||||||
|                 else |  | ||||||
|                 { |  | ||||||
|                     Rest.Log.ErrorFormat("{0} User authentication failed", MsgId); |  | ||||||
|                     Rest.Log.DebugFormat("{0} Authorization header: {1}", MsgId, |  | ||||||
|                                          rdata.request.Headers.Get("Authorization")); |  | ||||||
|                 } |  | ||||||
|                 throw (e); |  | ||||||
|             } |  | ||||||
| 
 |  | ||||||
|             // Remove the prefix and what's left are the parameters. If we don't have |  | ||||||
|             // the parameters we need, fail the request. Parameters do NOT include |  | ||||||
|             // any supplied query values. |  | ||||||
| 
 |  | ||||||
|             if (rdata.Parameters.Length > 0) |  | ||||||
|             { |  | ||||||
|                 switch (rdata.method) |  | ||||||
|                 { |  | ||||||
|                 case "get" : |  | ||||||
|                     DoGet(rdata); |  | ||||||
|                     break; |  | ||||||
|                 case "put" : |  | ||||||
|                     DoPut(rdata); |  | ||||||
|                     break; |  | ||||||
|                 case "post" : |  | ||||||
|                     DoPost(rdata); |  | ||||||
|                     break; |  | ||||||
|                 case "delete" : |  | ||||||
|                     DoDelete(rdata); |  | ||||||
|                     break; |  | ||||||
|                 default : |  | ||||||
|                     Rest.Log.WarnFormat("{0} File: Method not supported: {1}", |  | ||||||
|                                         MsgId, rdata.method); |  | ||||||
|                     rdata.Fail(Rest.HttpStatusCodeBadRequest,String.Format("method <{0}> not supported", rdata.method)); |  | ||||||
|                     break; |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
|             else |  | ||||||
|             { |  | ||||||
|                 Rest.Log.WarnFormat("{0} File: No agent information provided", MsgId); |  | ||||||
|                 rdata.Fail(Rest.HttpStatusCodeBadRequest, "no agent information provided"); |  | ||||||
|             } |  | ||||||
| 
 |  | ||||||
|             Rest.Log.DebugFormat("{0} REST File handler EXIT", MsgId); |  | ||||||
| 
 |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         #endregion Interface |  | ||||||
| 
 |  | ||||||
|         /// <summary> |  | ||||||
|         /// The only parameter we recognize is a UUID.If an asset with this identification is |  | ||||||
|         /// found, it's content, base-64 encoded, is returned to the client. |  | ||||||
|         /// </summary> |  | ||||||
| 
 |  | ||||||
|         private void DoGet(FileRequestData rdata) |  | ||||||
|         { |  | ||||||
| 
 |  | ||||||
|             string path = String.Empty; |  | ||||||
| 
 |  | ||||||
|             Rest.Log.DebugFormat("{0} REST File handler, Method = <{1}> ENTRY", MsgId, rdata.method); |  | ||||||
| 
 |  | ||||||
|             if (rdata.Parameters.Length > 1) |  | ||||||
|             { |  | ||||||
|                 try |  | ||||||
|                 { |  | ||||||
|                     path = rdata.path.Substring(rdata.Parameters[0].Length+qPrefix.Length+2); |  | ||||||
|                     if (File.Exists(path)) |  | ||||||
|                     { |  | ||||||
|                         Rest.Log.DebugFormat("{0}  File located <{1}>", MsgId, path); |  | ||||||
|                         Byte[] data = File.ReadAllBytes(path); |  | ||||||
|                         rdata.initXmlWriter(); |  | ||||||
|                         rdata.writer.WriteStartElement(String.Empty,"File",String.Empty); |  | ||||||
|                         rdata.writer.WriteAttributeString("name", path); |  | ||||||
|                         rdata.writer.WriteBase64(data,0,data.Length); |  | ||||||
|                         rdata.writer.WriteFullEndElement(); |  | ||||||
|                     } |  | ||||||
|                     else |  | ||||||
|                     { |  | ||||||
|                         Rest.Log.DebugFormat("{0} Invalid parameters: <{1}>", MsgId, path); |  | ||||||
|                         rdata.Fail(Rest.HttpStatusCodeNotFound, String.Format("invalid parameters : {0}", path)); |  | ||||||
|                     } |  | ||||||
|                 } |  | ||||||
|                 catch (Exception e) |  | ||||||
|                 { |  | ||||||
|                     Rest.Log.DebugFormat("{0} Invalid parameters: <{1}>", MsgId, e.Message); |  | ||||||
|                     rdata.Fail(Rest.HttpStatusCodeNotFound, String.Format("invalid parameters : {0} {1}",  |  | ||||||
|                                      path, e.Message)); |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
| 
 |  | ||||||
|             rdata.Complete(); |  | ||||||
|             rdata.Respond(String.Format("File <{0}> : Normal completion", rdata.method)); |  | ||||||
| 
 |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         /// <summary> |  | ||||||
|         /// UPDATE existing item, if it exists. URI identifies the item in question. |  | ||||||
|         /// The only parameter we recognize is a UUID. The enclosed asset data (base-64 encoded) |  | ||||||
|         /// is decoded and stored in the database, identified by the supplied UUID. |  | ||||||
|         /// </summary> |  | ||||||
|         private void DoPut(FileRequestData rdata) |  | ||||||
|         { |  | ||||||
|             bool modified = false; |  | ||||||
|             bool created  = false; |  | ||||||
|             string path   = String.Empty; |  | ||||||
| 
 |  | ||||||
|             Rest.Log.DebugFormat("{0} REST File handler, Method = <{1}> ENTRY", MsgId, rdata.method); |  | ||||||
| 
 |  | ||||||
|             if (rdata.Parameters.Length > 1) |  | ||||||
|             { |  | ||||||
|                 try |  | ||||||
|                 { |  | ||||||
|                     path = rdata.path.Substring(rdata.Parameters[0].Length+qPrefix.Length+2); |  | ||||||
|                     bool maymod = File.Exists(path); |  | ||||||
|                      |  | ||||||
|                     rdata.initXmlReader(); |  | ||||||
|                     XmlReader xml = rdata.reader; |  | ||||||
| 
 |  | ||||||
|                     if (!xml.ReadToFollowing("File")) |  | ||||||
|                     { |  | ||||||
|                         Rest.Log.DebugFormat("{0} Invalid request data: <{1}>", MsgId, rdata.path); |  | ||||||
|                         rdata.Fail(Rest.HttpStatusCodeBadRequest,"invalid request data"); |  | ||||||
|                     } |  | ||||||
| 
 |  | ||||||
|                     Byte[] data = Convert.FromBase64String(xml.ReadElementContentAsString("File", "")); |  | ||||||
| 
 |  | ||||||
|                     File.WriteAllBytes(path,data); |  | ||||||
|                     modified =   maymod; |  | ||||||
|                     created  = ! maymod; |  | ||||||
|                 } |  | ||||||
|                 catch (Exception e) |  | ||||||
|                 { |  | ||||||
|                     Rest.Log.DebugFormat("{0} Exception during file processing : {1}", MsgId,  |  | ||||||
|                           e.Message); |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
|             else |  | ||||||
|             { |  | ||||||
|                 Rest.Log.DebugFormat("{0} Invalid parameters: <{1}>", MsgId, rdata.path); |  | ||||||
|                 rdata.Fail(Rest.HttpStatusCodeNotFound, "invalid parameters"); |  | ||||||
|             } |  | ||||||
| 
 |  | ||||||
|             if (created) |  | ||||||
|             { |  | ||||||
|                 rdata.appendStatus(String.Format("<p> Created file {0} <p>", path)); |  | ||||||
|                 rdata.Complete(Rest.HttpStatusCodeCreated); |  | ||||||
|             } |  | ||||||
|             else |  | ||||||
|             { |  | ||||||
|                 if (modified) |  | ||||||
|                 { |  | ||||||
|                     rdata.appendStatus(String.Format("<p> Modified file {0} <p>", path)); |  | ||||||
|                     rdata.Complete(Rest.HttpStatusCodeOK); |  | ||||||
|                 } |  | ||||||
|                 else |  | ||||||
|                 { |  | ||||||
|                     rdata.Complete(Rest.HttpStatusCodeNoContent); |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
| 
 |  | ||||||
|             rdata.Respond(String.Format("File {0} : Normal completion", rdata.method)); |  | ||||||
| 
 |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         /// <summary> |  | ||||||
|         /// CREATE new item, replace if it exists. URI identifies the context for the item in question. |  | ||||||
|         /// No parameters are required for POST, just thepayload. |  | ||||||
|         /// </summary> |  | ||||||
| 
 |  | ||||||
|         private void DoPost(FileRequestData rdata) |  | ||||||
|         { |  | ||||||
| 
 |  | ||||||
|             bool modified = false; |  | ||||||
|             bool created  = false; |  | ||||||
|             string path   = String.Empty; |  | ||||||
| 
 |  | ||||||
|             Rest.Log.DebugFormat("{0} REST File handler, Method = <{1}> ENTRY", MsgId, rdata.method); |  | ||||||
| 
 |  | ||||||
|             if (rdata.Parameters.Length > 1) |  | ||||||
|             { |  | ||||||
|                 try |  | ||||||
|                 { |  | ||||||
|                     path = rdata.path.Substring(rdata.Parameters[0].Length+qPrefix.Length+2); |  | ||||||
|                     bool maymod = File.Exists(path); |  | ||||||
|                      |  | ||||||
|                     rdata.initXmlReader(); |  | ||||||
|                     XmlReader xml = rdata.reader; |  | ||||||
| 
 |  | ||||||
|                     if (!xml.ReadToFollowing("File")) |  | ||||||
|                     { |  | ||||||
|                         Rest.Log.DebugFormat("{0} Invalid request data: <{1}>", MsgId, rdata.path); |  | ||||||
|                         rdata.Fail(Rest.HttpStatusCodeBadRequest,"invalid request data"); |  | ||||||
|                     } |  | ||||||
| 
 |  | ||||||
|                     Byte[] data = Convert.FromBase64String(xml.ReadElementContentAsString("File", "")); |  | ||||||
| 
 |  | ||||||
|                     File.WriteAllBytes(path,data); |  | ||||||
|                     modified =   maymod; |  | ||||||
|                     created  = ! maymod; |  | ||||||
|                 } |  | ||||||
|                 catch (Exception e) |  | ||||||
|                 { |  | ||||||
|                     Rest.Log.DebugFormat("{0} Exception during file processing : {1}", MsgId,  |  | ||||||
|                           e.Message); |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
|             else |  | ||||||
|             { |  | ||||||
|                 Rest.Log.DebugFormat("{0} Invalid parameters: <{1}>", MsgId, rdata.path); |  | ||||||
|                 rdata.Fail(Rest.HttpStatusCodeNotFound, "invalid parameters"); |  | ||||||
|             } |  | ||||||
| 
 |  | ||||||
|             if (created) |  | ||||||
|             { |  | ||||||
|                 rdata.appendStatus(String.Format("<p> Created file {0} <p>", path)); |  | ||||||
|                 rdata.Complete(Rest.HttpStatusCodeCreated); |  | ||||||
|             } |  | ||||||
|             else |  | ||||||
|             { |  | ||||||
|                 if (modified) |  | ||||||
|                 { |  | ||||||
|                     rdata.appendStatus(String.Format("<p> Modified file {0} <p>", path)); |  | ||||||
|                     rdata.Complete(Rest.HttpStatusCodeOK); |  | ||||||
|                 } |  | ||||||
|                 else |  | ||||||
|                 { |  | ||||||
|                     rdata.Complete(Rest.HttpStatusCodeNoContent); |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
| 
 |  | ||||||
|             rdata.Respond(String.Format("File {0} : Normal completion", rdata.method)); |  | ||||||
| 
 |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         /// <summary> |  | ||||||
|         /// CREATE new item, replace if it exists. URI identifies the context for the item in question. |  | ||||||
|         /// No parameters are required for POST, just thepayload. |  | ||||||
|         /// </summary> |  | ||||||
| 
 |  | ||||||
|         private void DoDelete(FileRequestData rdata) |  | ||||||
|         { |  | ||||||
| 
 |  | ||||||
|             bool modified = false; |  | ||||||
|             bool created  = false; |  | ||||||
|             string path   = String.Empty; |  | ||||||
| 
 |  | ||||||
|             Rest.Log.DebugFormat("{0} REST File handler, Method = <{1}> ENTRY", MsgId, rdata.method); |  | ||||||
| 
 |  | ||||||
|             if (rdata.Parameters.Length > 1) |  | ||||||
|             { |  | ||||||
|                 try |  | ||||||
|                 { |  | ||||||
|                     path = rdata.path.Substring(rdata.Parameters[0].Length+qPrefix.Length+2); |  | ||||||
| 
 |  | ||||||
|                     if (File.Exists(path)) |  | ||||||
|                     { |  | ||||||
|                         File.Delete(path); |  | ||||||
|                     } |  | ||||||
|                 } |  | ||||||
|                 catch (Exception e) |  | ||||||
|                 { |  | ||||||
|                     Rest.Log.DebugFormat("{0} Exception during file processing : {1}", MsgId,  |  | ||||||
|                           e.Message); |  | ||||||
|                     rdata.Fail(Rest.HttpStatusCodeNotFound, String.Format("invalid parameters : {0} {1}", |  | ||||||
|                           path, e.Message)); |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
|             else |  | ||||||
|             { |  | ||||||
|                 Rest.Log.DebugFormat("{0} Invalid parameters: <{1}>", MsgId, rdata.path); |  | ||||||
|                 rdata.Fail(Rest.HttpStatusCodeNotFound, "invalid parameters"); |  | ||||||
|             } |  | ||||||
| 
 |  | ||||||
|             if (created) |  | ||||||
|             { |  | ||||||
|                 rdata.appendStatus(String.Format("<p> Created file {0} <p>", path)); |  | ||||||
|                 rdata.Complete(Rest.HttpStatusCodeCreated); |  | ||||||
|             } |  | ||||||
|             else |  | ||||||
|             { |  | ||||||
|                 if (modified) |  | ||||||
|                 { |  | ||||||
|                     rdata.appendStatus(String.Format("<p> Modified file {0} <p>", path)); |  | ||||||
|                     rdata.Complete(Rest.HttpStatusCodeOK); |  | ||||||
|                 } |  | ||||||
|                 else |  | ||||||
|                 { |  | ||||||
|                     rdata.Complete(Rest.HttpStatusCodeNoContent); |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
| 
 |  | ||||||
|             rdata.Respond(String.Format("File {0} : Normal completion", rdata.method)); |  | ||||||
| 
 |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         /// <summary> |  | ||||||
|         /// File processing has no special data area requirements. |  | ||||||
|         /// </summary> |  | ||||||
| 
 |  | ||||||
|         internal class FileRequestData : RequestData |  | ||||||
|         { |  | ||||||
|             internal FileRequestData(OSHttpRequest request, OSHttpResponse response, string prefix) |  | ||||||
|                 : base(request, response, prefix) |  | ||||||
|             { |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| } |  | ||||||
|  | @ -1,662 +0,0 @@ | ||||||
| /* |  | ||||||
|  * Copyright (c) Contributors, http://opensimulator.org/ |  | ||||||
|  * See CONTRIBUTORS.TXT for a full list of copyright holders. |  | ||||||
|  * |  | ||||||
|  * Redistribution and use in source and binary forms, with or without |  | ||||||
|  * modification, are permitted provided that the following conditions are met: |  | ||||||
|  *     * Redistributions of source code must retain the above copyright |  | ||||||
|  *       notice, this list of conditions and the following disclaimer. |  | ||||||
|  *     * Redistributions in binary form must reproduce the above copyright |  | ||||||
|  *       notice, this list of conditions and the following disclaimer in the |  | ||||||
|  *       documentation and/or other materials provided with the distribution. |  | ||||||
|  *     * Neither the name of the OpenSimulator Project nor the |  | ||||||
|  *       names of its contributors may be used to endorse or promote products |  | ||||||
|  *       derived from this software without specific prior written permission. |  | ||||||
|  * |  | ||||||
|  * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY |  | ||||||
|  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |  | ||||||
|  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |  | ||||||
|  * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY |  | ||||||
|  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |  | ||||||
|  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |  | ||||||
|  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |  | ||||||
|  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |  | ||||||
|  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |  | ||||||
|  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |  | ||||||
|  */ |  | ||||||
| 
 |  | ||||||
| using System; |  | ||||||
| using System.Collections.Generic; |  | ||||||
| using System.Reflection; |  | ||||||
| using OpenSim.Framework.Servers; |  | ||||||
| using OpenSim.Framework.Servers.HttpServer; |  | ||||||
| 
 |  | ||||||
| namespace OpenSim.ApplicationPlugins.Rest.Inventory |  | ||||||
| { |  | ||||||
|     /// <remarks> |  | ||||||
|     /// The class signature reveals the roles that RestHandler plays. |  | ||||||
|     /// |  | ||||||
|     /// [1] It is a sub-class of RestPlugin. It inherits and extends |  | ||||||
|     ///     the functionality of this class, constraining it to the |  | ||||||
|     ///     specific needs of this REST implementation. This relates |  | ||||||
|     ///     to the plug-in mechanism supported by OpenSim, the specifics |  | ||||||
|     ///     of which are mostly hidden by RestPlugin. |  | ||||||
|     /// [2] IRestHandler describes the interface that this class |  | ||||||
|     ///     exports to service implementations. This is the services |  | ||||||
|     ///     management interface. |  | ||||||
|     /// [3] IHttpAgentHandler describes the interface that is exported |  | ||||||
|     ///     to the BaseHttpServer in support of this particular HTTP |  | ||||||
|     ///     processing model. This is the request interface of the |  | ||||||
|     ///     handler. |  | ||||||
|     /// </remarks> |  | ||||||
| 
 |  | ||||||
|     public class RestHandler : RestPlugin, IRestHandler, IHttpAgentHandler |  | ||||||
|     { |  | ||||||
|         // Handler tables: both stream and REST are supported. The path handlers and their |  | ||||||
|         // respective allocators are stored in separate tables. |  | ||||||
| 
 |  | ||||||
|         internal Dictionary<string,RestMethodHandler>   pathHandlers   = new Dictionary<string,RestMethodHandler>(); |  | ||||||
|         internal Dictionary<string,RestMethodAllocator> pathAllocators = new Dictionary<string,RestMethodAllocator>(); |  | ||||||
|         internal Dictionary<string,RestStreamHandler>   streamHandlers = new Dictionary<string,RestStreamHandler>(); |  | ||||||
| 
 |  | ||||||
|         #region local static state |  | ||||||
| 
 |  | ||||||
|         private static bool  handlersLoaded = false; |  | ||||||
|         private static List<Type>  classes  = new List<Type>(); |  | ||||||
|         private static List<IRest> handlers = new List<IRest>(); |  | ||||||
|         private static Type[]         parms = new Type[0]; |  | ||||||
|         private static Object[]       args  = new Object[0]; |  | ||||||
| 
 |  | ||||||
|         /// <summary> |  | ||||||
|         /// This static initializer scans the ASSEMBLY for classes that |  | ||||||
|         /// export the IRest interface and builds a list of them. These |  | ||||||
|         /// are later activated by the handler. To add a new handler it |  | ||||||
|         /// is only necessary to create a new services class that implements |  | ||||||
|         /// the IRest interface, and recompile the handler. This gives |  | ||||||
|         /// all of the build-time flexibility of a modular approach |  | ||||||
|         /// while not introducing yet-another module loader. Note that |  | ||||||
|         /// multiple assembles can still be built, each with its own set |  | ||||||
|         /// of handlers. Examples of services classes are RestInventoryServices |  | ||||||
|         /// and RestSkeleton. |  | ||||||
|         /// </summary> |  | ||||||
| 
 |  | ||||||
|         static RestHandler() |  | ||||||
|         { |  | ||||||
|             Module[] mods = Assembly.GetExecutingAssembly().GetModules(); |  | ||||||
| 
 |  | ||||||
|             foreach (Module m in mods) |  | ||||||
|             { |  | ||||||
|                 Type[] types = m.GetTypes(); |  | ||||||
|                 foreach (Type t in types) |  | ||||||
|                 { |  | ||||||
|                     try |  | ||||||
|                     { |  | ||||||
|                         if (t.GetInterface("IRest") != null) |  | ||||||
|                         { |  | ||||||
|                             classes.Add(t); |  | ||||||
|                         } |  | ||||||
|                     } |  | ||||||
|                     catch (Exception) |  | ||||||
|                     { |  | ||||||
|                         Rest.Log.WarnFormat("[STATIC-HANDLER]: #0 Error scanning {1}", t); |  | ||||||
|                         Rest.Log.InfoFormat("[STATIC-HANDLER]: #0 {1} is not included", t); |  | ||||||
|                     } |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         #endregion local static state |  | ||||||
| 
 |  | ||||||
|         #region local instance state |  | ||||||
| 
 |  | ||||||
|         /// <summary> |  | ||||||
|         /// This routine loads all of the handlers discovered during |  | ||||||
|         /// instance initialization. |  | ||||||
|         /// A table of all loaded and successfully constructed handlers |  | ||||||
|         /// is built, and this table is then used by the constructor to |  | ||||||
|         /// initialize each of the handlers in turn. |  | ||||||
|         /// NOTE: The loading process does not automatically imply that |  | ||||||
|         /// the handler has registered any kind of an interface, that |  | ||||||
|         /// may be (optionally) done by the handler either during |  | ||||||
|         /// construction, or during initialization. |  | ||||||
|         /// |  | ||||||
|         /// I was not able to make this code work within a constructor |  | ||||||
|         /// so it is isolated within this method. |  | ||||||
|         /// </summary> |  | ||||||
| 
 |  | ||||||
|         private void LoadHandlers() |  | ||||||
|         { |  | ||||||
|             lock (handlers) |  | ||||||
|             { |  | ||||||
|                 if (!handlersLoaded) |  | ||||||
|                 { |  | ||||||
|                     ConstructorInfo ci; |  | ||||||
|                     Object          ht; |  | ||||||
| 
 |  | ||||||
|                     foreach (Type t in classes) |  | ||||||
|                     { |  | ||||||
|                         try |  | ||||||
|                         { |  | ||||||
|                             ci = t.GetConstructor(parms); |  | ||||||
|                             ht = ci.Invoke(args); |  | ||||||
|                             handlers.Add((IRest)ht); |  | ||||||
|                         } |  | ||||||
|                         catch (Exception e) |  | ||||||
|                         { |  | ||||||
|                             Rest.Log.WarnFormat("{0} Unable to load {1} : {2}", MsgId, t, e.Message); |  | ||||||
|                         } |  | ||||||
|                     } |  | ||||||
|                     handlersLoaded = true; |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         #endregion local instance state |  | ||||||
| 
 |  | ||||||
|         #region overriding properties |  | ||||||
| 
 |  | ||||||
|         // These properties override definitions |  | ||||||
|         // in the base class. |  | ||||||
| 
 |  | ||||||
|         // Name is used to differentiate the message header. |  | ||||||
| 
 |  | ||||||
|         public override string Name |  | ||||||
|         { |  | ||||||
|             get { return "HANDLER"; } |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         // Used to partition the .ini configuration space. |  | ||||||
| 
 |  | ||||||
|         public override string ConfigName |  | ||||||
|         { |  | ||||||
|             get { return "RestHandler"; } |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         // We have to rename these because we want |  | ||||||
|         // to be able to share the values with other |  | ||||||
|         // classes in our assembly and the base |  | ||||||
|         // names are protected. |  | ||||||
| 
 |  | ||||||
|         public string MsgId |  | ||||||
|         { |  | ||||||
|             get { return base.MsgID; } |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         public string RequestId |  | ||||||
|         { |  | ||||||
|             get { return base.RequestID; } |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         #endregion overriding properties |  | ||||||
| 
 |  | ||||||
|         #region overriding methods |  | ||||||
| 
 |  | ||||||
|         /// <summary> |  | ||||||
|         /// This method is called by OpenSimMain immediately after loading the |  | ||||||
|         /// plugin and after basic server setup,  but before running any server commands. |  | ||||||
|         /// </summary> |  | ||||||
|         /// <remarks> |  | ||||||
|         /// Note that entries MUST be added to the active configuration files before |  | ||||||
|         /// the plugin can be enabled. |  | ||||||
|         /// </remarks> |  | ||||||
| 
 |  | ||||||
|         public override void Initialise(OpenSimBase openSim) |  | ||||||
|         { |  | ||||||
|             try |  | ||||||
|             { |  | ||||||
|                 // This plugin will only be enabled if the broader |  | ||||||
|                 // REST plugin mechanism is enabled. |  | ||||||
| 
 |  | ||||||
|                 //Rest.Log.InfoFormat("{0}  Plugin is initializing", MsgId); |  | ||||||
| 
 |  | ||||||
|                 base.Initialise(openSim); |  | ||||||
| 
 |  | ||||||
|                 // IsEnabled is implemented by the base class and |  | ||||||
|                 // reflects an overall RestPlugin status |  | ||||||
| 
 |  | ||||||
|                 if (!IsEnabled) |  | ||||||
|                 { |  | ||||||
|                     //Rest.Log.WarnFormat("{0} Plugins are disabled", MsgId); |  | ||||||
|                     return; |  | ||||||
|                 } |  | ||||||
| 
 |  | ||||||
|                 Rest.Log.InfoFormat("{0} Rest <{1}> plugin will be enabled", MsgId, Name); |  | ||||||
|                 Rest.Log.InfoFormat("{0} Configuration parameters read from <{1}>", MsgId, ConfigName); |  | ||||||
| 
 |  | ||||||
|                 // These are stored in static variables to make |  | ||||||
|                 // them easy to reach from anywhere in the assembly. |  | ||||||
| 
 |  | ||||||
|                 Rest.main              = openSim; |  | ||||||
|                 if (Rest.main == null) |  | ||||||
|                     throw new Exception("OpenSim base pointer is null"); |  | ||||||
| 
 |  | ||||||
|                 Rest.Plugin            = this; |  | ||||||
|                 Rest.Config            = Config; |  | ||||||
|                 Rest.Prefix            = Prefix; |  | ||||||
|                 Rest.GodKey            = GodKey; |  | ||||||
|                 Rest.Authenticate      = Rest.Config.GetBoolean("authenticate", Rest.Authenticate); |  | ||||||
|                 Rest.Scheme            = Rest.Config.GetString("auth-scheme", Rest.Scheme); |  | ||||||
|                 Rest.Secure            = Rest.Config.GetBoolean("secured", Rest.Secure); |  | ||||||
|                 Rest.ExtendedEscape    = Rest.Config.GetBoolean("extended-escape", Rest.ExtendedEscape); |  | ||||||
|                 Rest.Realm             = Rest.Config.GetString("realm", Rest.Realm); |  | ||||||
|                 Rest.DumpAsset         = Rest.Config.GetBoolean("dump-asset", Rest.DumpAsset); |  | ||||||
|                 Rest.Fill              = Rest.Config.GetBoolean("path-fill", Rest.Fill); |  | ||||||
|                 Rest.DumpLineSize      = Rest.Config.GetInt("dump-line-size", Rest.DumpLineSize); |  | ||||||
|                 Rest.FlushEnabled      = Rest.Config.GetBoolean("flush-on-error", Rest.FlushEnabled); |  | ||||||
| 
 |  | ||||||
|                 // Note: Odd spacing is required in the following strings |  | ||||||
| 
 |  | ||||||
|                 Rest.Log.InfoFormat("{0} Authentication is {1}required", MsgId, |  | ||||||
|                                     (Rest.Authenticate ? "" : "not ")); |  | ||||||
| 
 |  | ||||||
|                 Rest.Log.InfoFormat("{0} Security is {1}enabled", MsgId, |  | ||||||
|                                     (Rest.Secure ? "" : "not ")); |  | ||||||
| 
 |  | ||||||
|                 Rest.Log.InfoFormat("{0} Extended URI escape processing is {1}enabled", MsgId, |  | ||||||
|                                     (Rest.ExtendedEscape ? "" : "not ")); |  | ||||||
| 
 |  | ||||||
|                 Rest.Log.InfoFormat("{0} Dumping of asset data is {1}enabled", MsgId, |  | ||||||
|                                     (Rest.DumpAsset ? "" : "not ")); |  | ||||||
| 
 |  | ||||||
|                 // The supplied prefix MUST be absolute |  | ||||||
| 
 |  | ||||||
|                 if (Rest.Prefix.Substring(0,1) != Rest.UrlPathSeparator) |  | ||||||
|                 { |  | ||||||
|                     Rest.Log.WarnFormat("{0} Prefix <{1}> is not absolute and must be", MsgId, Rest.Prefix); |  | ||||||
|                     Rest.Log.InfoFormat("{0} Prefix changed to </{1}>", MsgId, Rest.Prefix); |  | ||||||
|                     Rest.Prefix = String.Format("{0}{1}", Rest.UrlPathSeparator, Rest.Prefix); |  | ||||||
|                 } |  | ||||||
| 
 |  | ||||||
|                 // If data dumping is requested, report on the chosen line |  | ||||||
|                 // length. |  | ||||||
| 
 |  | ||||||
|                 if (Rest.DumpAsset) |  | ||||||
|                 { |  | ||||||
|                     Rest.Log.InfoFormat("{0} Dump {1} bytes per line", MsgId, Rest.DumpLineSize); |  | ||||||
|                 } |  | ||||||
| 
 |  | ||||||
|                 // Load all of the handlers present in the |  | ||||||
|                 // assembly |  | ||||||
| 
 |  | ||||||
|                 // In principle, as we're an application plug-in, |  | ||||||
|                 // most of what needs to be done could be done using |  | ||||||
|                 // static resources, however the Open Sim plug-in |  | ||||||
|                 // model makes this an instance, so that's what we |  | ||||||
|                 // need to be. |  | ||||||
|                 // There is only one Communications manager per |  | ||||||
|                 // server, and by inference, only one each of the |  | ||||||
|                 // user, asset, and inventory servers. So we can cache |  | ||||||
|                 // those using a static initializer. |  | ||||||
|                 // We move all of this processing off to another |  | ||||||
|                 // services class to minimize overlap between function |  | ||||||
|                 // and infrastructure. |  | ||||||
| 
 |  | ||||||
|                 LoadHandlers(); |  | ||||||
| 
 |  | ||||||
|                 // The intention of a post construction initializer |  | ||||||
|                 // is to allow for setup that is dependent upon other |  | ||||||
|                 // activities outside of the agency. |  | ||||||
| 
 |  | ||||||
|                 foreach (IRest handler in handlers) |  | ||||||
|                 { |  | ||||||
|                     try |  | ||||||
|                     { |  | ||||||
|                         handler.Initialize(); |  | ||||||
|                     } |  | ||||||
|                     catch (Exception e) |  | ||||||
|                     { |  | ||||||
|                         Rest.Log.ErrorFormat("{0} initialization error: {1}", MsgId, e.Message); |  | ||||||
|                     } |  | ||||||
|                 } |  | ||||||
| 
 |  | ||||||
|                 // Now that everything is setup we can proceed to |  | ||||||
|                 // add THIS agent to the HTTP server's handler list |  | ||||||
| 
 |  | ||||||
|                 // FIXME: If this code is ever to be re-enabled (most of it is disabled already) then this will |  | ||||||
|                 // have to be handled through the AddHttpHandler interface. |  | ||||||
| //                if (!AddAgentHandler(Rest.Name,this)) |  | ||||||
| //                { |  | ||||||
| //                    Rest.Log.ErrorFormat("{0} Unable to activate handler interface", MsgId); |  | ||||||
| //                    foreach (IRest handler in handlers) |  | ||||||
| //                    { |  | ||||||
| //                        handler.Close(); |  | ||||||
| //                    } |  | ||||||
| //                } |  | ||||||
| 
 |  | ||||||
|             } |  | ||||||
|             catch (Exception e) |  | ||||||
|             { |  | ||||||
|                 Rest.Log.ErrorFormat("{0} Plugin initialization has failed: {1}", MsgId, e.Message); |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         /// <summary> |  | ||||||
|         /// In the interests of efficiency, and because we cannot determine whether |  | ||||||
|         /// or not this instance will actually be harvested, we clobber the only |  | ||||||
|         /// anchoring reference to the working state for this plug-in. What the |  | ||||||
|         /// call to close does is irrelevant to this class beyond knowing that it |  | ||||||
|         /// can nullify the reference when it returns. |  | ||||||
|         /// To make sure everything is copacetic we make sure the primary interface |  | ||||||
|         /// is disabled by deleting the handler from the HTTP server tables. |  | ||||||
|         /// </summary> |  | ||||||
| 
 |  | ||||||
|         public override void Close() |  | ||||||
|         { |  | ||||||
|             Rest.Log.InfoFormat("{0} Plugin is terminating", MsgId); |  | ||||||
| 
 |  | ||||||
|             // FIXME: If this code is ever to be re-enabled (most of it is disabled already) then this will |  | ||||||
|             // have to be handled through the AddHttpHandler interface. |  | ||||||
| //            try |  | ||||||
| //            { |  | ||||||
| //                RemoveAgentHandler(Rest.Name, this); |  | ||||||
| //            } |  | ||||||
| //            catch (KeyNotFoundException){} |  | ||||||
| 
 |  | ||||||
|             foreach (IRest handler in handlers) |  | ||||||
|             { |  | ||||||
|                 handler.Close(); |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         #endregion overriding methods |  | ||||||
| 
 |  | ||||||
|         #region interface methods |  | ||||||
| 
 |  | ||||||
|         /// <summary> |  | ||||||
|         /// This method is called by the HTTP server to match an incoming |  | ||||||
|         /// request. It scans all of the strings registered by the |  | ||||||
|         /// underlying handlers and looks for the best match. It returns |  | ||||||
|         /// true if a match is found. |  | ||||||
|         /// The matching process could be made arbitrarily complex. |  | ||||||
|         /// Note: The match is case-insensitive. |  | ||||||
|         /// </summary> |  | ||||||
| 
 |  | ||||||
|         public bool Match(OSHttpRequest request, OSHttpResponse response) |  | ||||||
|         { |  | ||||||
| 
 |  | ||||||
|             string path = request.RawUrl.ToLower(); |  | ||||||
| 
 |  | ||||||
|             // Rest.Log.DebugFormat("{0} Match ENTRY", MsgId); |  | ||||||
| 
 |  | ||||||
|             try |  | ||||||
|             { |  | ||||||
|                 foreach (string key in pathHandlers.Keys) |  | ||||||
|                 { |  | ||||||
|                     // Rest.Log.DebugFormat("{0} Match testing {1} against agent prefix <{2}>", MsgId, path, key); |  | ||||||
| 
 |  | ||||||
|                     // Note that Match will not necessarily find the handler that will |  | ||||||
|                     // actually be used - it does no test for the "closest" fit. It |  | ||||||
|                     // simply reflects that at least one possible handler exists. |  | ||||||
| 
 |  | ||||||
|                     if (path.StartsWith(key)) |  | ||||||
|                     { |  | ||||||
|                         // Rest.Log.DebugFormat("{0} Matched prefix <{1}>", MsgId, key); |  | ||||||
| 
 |  | ||||||
|                         // This apparently odd evaluation is needed to prevent a match |  | ||||||
|                         // on anything other than a URI token boundary. Otherwise we |  | ||||||
|                         // may match on URL's that were not intended for this handler. |  | ||||||
| 
 |  | ||||||
|                         return (path.Length == key.Length || |  | ||||||
|                                 path.Substring(key.Length, 1) == Rest.UrlPathSeparator); |  | ||||||
|                     } |  | ||||||
|                 } |  | ||||||
| 
 |  | ||||||
|                 path = String.Format("{0}{1}{2}", request.HttpMethod, Rest.UrlMethodSeparator, path); |  | ||||||
| 
 |  | ||||||
|                 foreach (string key in streamHandlers.Keys) |  | ||||||
|                 { |  | ||||||
|                     // Rest.Log.DebugFormat("{0} Match testing {1} against stream prefix <{2}>", MsgId, path, key); |  | ||||||
| 
 |  | ||||||
|                     // Note that Match will not necessarily find the handler that will |  | ||||||
|                     // actually be used - it does no test for the "closest" fit. It |  | ||||||
|                     // simply reflects that at least one possible handler exists. |  | ||||||
| 
 |  | ||||||
|                     if (path.StartsWith(key)) |  | ||||||
|                     { |  | ||||||
|                         // Rest.Log.DebugFormat("{0} Matched prefix <{1}>", MsgId, key); |  | ||||||
| 
 |  | ||||||
|                         // This apparently odd evaluation is needed to prevent a match |  | ||||||
|                         // on anything other than a URI token boundary. Otherwise we |  | ||||||
|                         // may match on URL's that were not intended for this handler. |  | ||||||
| 
 |  | ||||||
|                         return (path.Length == key.Length || |  | ||||||
|                                 path.Substring(key.Length, 1) == Rest.UrlPathSeparator); |  | ||||||
|                     } |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
|             catch (Exception e) |  | ||||||
|             { |  | ||||||
|                 Rest.Log.ErrorFormat("{0} matching exception for path <{1}> : {2}", MsgId, path, e.Message); |  | ||||||
|             } |  | ||||||
| 
 |  | ||||||
|             return false; |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         /// <summary> |  | ||||||
|         /// This is called by the HTTP server once the handler has indicated |  | ||||||
|         /// that it is able to handle the request. |  | ||||||
|         /// Preconditions: |  | ||||||
|         ///  [1] request  != null and is a valid request object |  | ||||||
|         ///  [2] response != null and is a valid response object |  | ||||||
|         /// Behavior is undefined if preconditions are not satisfied. |  | ||||||
|         /// </summary> |  | ||||||
| 
 |  | ||||||
|         public bool Handle(OSHttpRequest request, OSHttpResponse response) |  | ||||||
|         { |  | ||||||
|             bool handled; |  | ||||||
|             base.MsgID = base.RequestID; |  | ||||||
| 
 |  | ||||||
|             // Debug only |  | ||||||
| 
 |  | ||||||
|             if (Rest.DEBUG) |  | ||||||
|             { |  | ||||||
|                 Rest.Log.DebugFormat("{0} ENTRY", MsgId); |  | ||||||
|                 Rest.Log.DebugFormat("{0}  Agent: {1}", MsgId, request.UserAgent); |  | ||||||
|                 Rest.Log.DebugFormat("{0} Method: {1}", MsgId, request.HttpMethod); |  | ||||||
| 
 |  | ||||||
|                 for (int i = 0; i < request.Headers.Count; i++) |  | ||||||
|                 { |  | ||||||
|                     Rest.Log.DebugFormat("{0} Header [{1}] : <{2}> = <{3}>", |  | ||||||
|                                          MsgId, i, request.Headers.GetKey(i), request.Headers.Get(i)); |  | ||||||
|                 } |  | ||||||
|                 Rest.Log.DebugFormat("{0}    URI: {1}", MsgId, request.RawUrl); |  | ||||||
|             } |  | ||||||
| 
 |  | ||||||
|             // If a path handler worked we're done, otherwise try any |  | ||||||
|             // available stream handlers too. |  | ||||||
| 
 |  | ||||||
|             try |  | ||||||
|             { |  | ||||||
|                 handled = (FindPathHandler(request, response) || |  | ||||||
|                     FindStreamHandler(request, response)); |  | ||||||
|             } |  | ||||||
|             catch (Exception e) |  | ||||||
|             { |  | ||||||
|                 // A raw exception indicates that something we weren't expecting has |  | ||||||
|                 // happened. This should always reflect a shortcoming in the plugin, |  | ||||||
|                 // or a failure to satisfy the preconditions. It should not reflect |  | ||||||
|                 // an error in the request itself. Under such circumstances the state |  | ||||||
|                 // of the request cannot be determined and we are obliged to mark it |  | ||||||
|                 // as 'handled'. |  | ||||||
| 
 |  | ||||||
|                 Rest.Log.ErrorFormat("{0} Plugin error: {1}", MsgId, e.Message); |  | ||||||
|                 handled = true; |  | ||||||
|             } |  | ||||||
| 
 |  | ||||||
|             Rest.Log.DebugFormat("{0} EXIT", MsgId); |  | ||||||
| 
 |  | ||||||
|             return handled; |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         #endregion interface methods |  | ||||||
| 
 |  | ||||||
|         /// <summary> |  | ||||||
|         /// If there is a stream handler registered that can handle the |  | ||||||
|         /// request, then fine. If the request is not matched, do |  | ||||||
|         /// nothing. |  | ||||||
|         /// Note: The selection is case-insensitive |  | ||||||
|         /// </summary> |  | ||||||
| 
 |  | ||||||
|         private bool FindStreamHandler(OSHttpRequest request, OSHttpResponse response) |  | ||||||
|         { |  | ||||||
|             RequestData rdata = new RequestData(request, response, String.Empty); |  | ||||||
| 
 |  | ||||||
|             string bestMatch = String.Empty; |  | ||||||
|             string path      = String.Format("{0}:{1}", rdata.method, rdata.path).ToLower(); |  | ||||||
| 
 |  | ||||||
|             Rest.Log.DebugFormat("{0} Checking for stream handler for <{1}>", MsgId, path); |  | ||||||
| 
 |  | ||||||
|             if (!IsEnabled) |  | ||||||
|             { |  | ||||||
|                 return false; |  | ||||||
|             } |  | ||||||
| 
 |  | ||||||
|             foreach (string pattern in streamHandlers.Keys) |  | ||||||
|             { |  | ||||||
|                 if (path.StartsWith(pattern)) |  | ||||||
|                 { |  | ||||||
|                     if (pattern.Length > bestMatch.Length) |  | ||||||
|                     { |  | ||||||
|                         bestMatch = pattern; |  | ||||||
|                     } |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
| 
 |  | ||||||
|             // Handle using the best match available |  | ||||||
| 
 |  | ||||||
|             if (bestMatch.Length > 0) |  | ||||||
|             { |  | ||||||
|                 Rest.Log.DebugFormat("{0} Stream-based handler matched with <{1}>", MsgId, bestMatch); |  | ||||||
|                 RestStreamHandler handler = streamHandlers[bestMatch]; |  | ||||||
|                 rdata.buffer = handler.Handle(rdata.path, rdata.request.InputStream, rdata.request, rdata.response); |  | ||||||
|                 rdata.AddHeader(rdata.response.ContentType,handler.ContentType); |  | ||||||
|                 rdata.Respond("FindStreamHandler Completion"); |  | ||||||
|             } |  | ||||||
| 
 |  | ||||||
|             return rdata.handled; |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         /// <summary> |  | ||||||
|         /// Add a stream handler for the designated HTTP method and path prefix. |  | ||||||
|         /// If the handler is not enabled, the request is ignored. If the path |  | ||||||
|         /// does not start with the REST prefix, it is added. If method-qualified |  | ||||||
|         /// path has not already been registered, the method is added to the active |  | ||||||
|         /// handler table. |  | ||||||
|         /// </summary> |  | ||||||
|         public void AddStreamHandler(string httpMethod, string path, RestMethod method) |  | ||||||
|         { |  | ||||||
|             if (!IsEnabled) |  | ||||||
|             { |  | ||||||
|                 return; |  | ||||||
|             } |  | ||||||
| 
 |  | ||||||
|             if (!path.StartsWith(Rest.Prefix)) |  | ||||||
|             { |  | ||||||
|                 path = String.Format("{0}{1}", Rest.Prefix, path); |  | ||||||
|             } |  | ||||||
| 
 |  | ||||||
|             path = String.Format("{0}{1}{2}", httpMethod, Rest.UrlMethodSeparator, path); |  | ||||||
| 
 |  | ||||||
|             // Conditionally add to the list |  | ||||||
| 
 |  | ||||||
|             if (!streamHandlers.ContainsKey(path)) |  | ||||||
|             { |  | ||||||
|                 streamHandlers.Add(path, new RestStreamHandler(httpMethod, path, method)); |  | ||||||
|                 Rest.Log.DebugFormat("{0} Added handler for {1}", MsgId, path); |  | ||||||
|             } |  | ||||||
|             else |  | ||||||
|             { |  | ||||||
|                 Rest.Log.WarnFormat("{0} Ignoring duplicate handler for {1}", MsgId, path); |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         /// <summary> |  | ||||||
|         /// Given the supplied request/response, if the handler is enabled, the inbound |  | ||||||
|         /// information is used to match an entry in the active path handler tables, using |  | ||||||
|         /// the method-qualified path information. If a match is found, then the handler is |  | ||||||
|         /// invoked. The result is the boolean result of the handler, or false if no |  | ||||||
|         /// handler was located. The boolean indicates whether or not the request has been |  | ||||||
|         /// handled, not whether or not the request was successful - that information is in |  | ||||||
|         /// the response. |  | ||||||
|         /// Note: The selection process is case-insensitive |  | ||||||
|         /// </summary> |  | ||||||
| 
 |  | ||||||
|         internal bool FindPathHandler(OSHttpRequest request, OSHttpResponse response) |  | ||||||
|         { |  | ||||||
|             RequestData rdata = null; |  | ||||||
|             string bestMatch = null; |  | ||||||
| 
 |  | ||||||
|             if (!IsEnabled) |  | ||||||
|             { |  | ||||||
|                 return false; |  | ||||||
|             } |  | ||||||
| 
 |  | ||||||
|             // Conditionally add to the list |  | ||||||
| 
 |  | ||||||
|             Rest.Log.DebugFormat("{0} Checking for path handler for <{1}>", MsgId, request.RawUrl); |  | ||||||
| 
 |  | ||||||
|             foreach (string pattern in pathHandlers.Keys) |  | ||||||
|             { |  | ||||||
|                 if (request.RawUrl.ToLower().StartsWith(pattern)) |  | ||||||
|                 { |  | ||||||
|                     if (String.IsNullOrEmpty(bestMatch) || pattern.Length > bestMatch.Length) |  | ||||||
|                     { |  | ||||||
|                         bestMatch = pattern; |  | ||||||
|                     } |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
| 
 |  | ||||||
|             if (!String.IsNullOrEmpty(bestMatch)) |  | ||||||
|             { |  | ||||||
|                 rdata = pathAllocators[bestMatch](request, response, bestMatch); |  | ||||||
| 
 |  | ||||||
|                 Rest.Log.DebugFormat("{0} Path based REST handler matched with <{1}>", MsgId, bestMatch); |  | ||||||
| 
 |  | ||||||
|                 try |  | ||||||
|                 { |  | ||||||
|                     pathHandlers[bestMatch](rdata); |  | ||||||
|                 } |  | ||||||
| 
 |  | ||||||
|                 // A plugin generated error indicates a request-related error |  | ||||||
|                 // that has been handled by the plugin. |  | ||||||
| 
 |  | ||||||
|                 catch (RestException r) |  | ||||||
|                 { |  | ||||||
|                     Rest.Log.WarnFormat("{0} Request failed: {1}", MsgId, r.Message); |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
| 
 |  | ||||||
|             return (rdata == null) ? false : rdata.handled; |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         /// <summary> |  | ||||||
|         /// A method handler and a request allocator are stored using the designated |  | ||||||
|         /// path as a key. If an entry already exists, it is replaced by the new one. |  | ||||||
|         /// </summary> |  | ||||||
| 
 |  | ||||||
|         public void AddPathHandler(RestMethodHandler mh, string path, RestMethodAllocator ra) |  | ||||||
|         { |  | ||||||
|             if (!IsEnabled) |  | ||||||
|             { |  | ||||||
|                 return; |  | ||||||
|             } |  | ||||||
| 
 |  | ||||||
|             if (pathHandlers.ContainsKey(path)) |  | ||||||
|             { |  | ||||||
|                 Rest.Log.DebugFormat("{0} Replacing handler for <${1}>", MsgId, path); |  | ||||||
|                 pathHandlers.Remove(path); |  | ||||||
|             } |  | ||||||
| 
 |  | ||||||
|             if (pathAllocators.ContainsKey(path)) |  | ||||||
|             { |  | ||||||
|                 Rest.Log.DebugFormat("{0} Replacing allocator for <${1}>", MsgId, path); |  | ||||||
|                 pathAllocators.Remove(path); |  | ||||||
|             } |  | ||||||
| 
 |  | ||||||
|             Rest.Log.DebugFormat("{0} Adding path handler for {1}", MsgId, path); |  | ||||||
| 
 |  | ||||||
|             pathHandlers.Add(path, mh); |  | ||||||
|             pathAllocators.Add(path, ra); |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| } |  | ||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							|  | @ -1,246 +0,0 @@ | ||||||
| /* |  | ||||||
|  * Copyright (c) Contributors, http://opensimulator.org/ |  | ||||||
|  * See CONTRIBUTORS.TXT for a full list of copyright holders. |  | ||||||
|  * |  | ||||||
|  * Redistribution and use in source and binary forms, with or without |  | ||||||
|  * modification, are permitted provided that the following conditions are met: |  | ||||||
|  *     * Redistributions of source code must retain the above copyright |  | ||||||
|  *       notice, this list of conditions and the following disclaimer. |  | ||||||
|  *     * Redistributions in binary form must reproduce the above copyright |  | ||||||
|  *       notice, this list of conditions and the following disclaimer in the |  | ||||||
|  *       documentation and/or other materials provided with the distribution. |  | ||||||
|  *     * Neither the name of the OpenSimulator Project nor the |  | ||||||
|  *       names of its contributors may be used to endorse or promote products |  | ||||||
|  *       derived from this software without specific prior written permission. |  | ||||||
|  * |  | ||||||
|  * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY |  | ||||||
|  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |  | ||||||
|  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |  | ||||||
|  * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY |  | ||||||
|  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |  | ||||||
|  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |  | ||||||
|  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |  | ||||||
|  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |  | ||||||
|  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |  | ||||||
|  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |  | ||||||
|  *  |  | ||||||
|  */ |  | ||||||
| 
 |  | ||||||
| using System; |  | ||||||
| using System.Collections.Generic; |  | ||||||
| using System.Reflection; |  | ||||||
| using OpenSim.Framework.Servers; |  | ||||||
| using OpenSim.Framework.Servers.HttpServer; |  | ||||||
| 
 |  | ||||||
| namespace OpenSim.ApplicationPlugins.Rest.Inventory |  | ||||||
| { |  | ||||||
|     public class RestTestServices : IRest |  | ||||||
|     { |  | ||||||
|         private bool    enabled = false; |  | ||||||
|         private string  qPrefix = "test"; |  | ||||||
| 
 |  | ||||||
|         // A simple constructor is used to handle any once-only |  | ||||||
|         // initialization of working classes. |  | ||||||
| 
 |  | ||||||
|         public RestTestServices() |  | ||||||
|         { |  | ||||||
|             Rest.Log.InfoFormat("{0} Test services initializing", MsgId); |  | ||||||
|             Rest.Log.InfoFormat("{0} Using REST Implementation Version {1}", MsgId, Rest.Version); |  | ||||||
| 
 |  | ||||||
|             // If a relative path was specified, make it absolute by adding |  | ||||||
|             // the standard prefix, e.g. /admin |  | ||||||
| 
 |  | ||||||
|             if (!qPrefix.StartsWith(Rest.UrlPathSeparator)) |  | ||||||
|             { |  | ||||||
|                 Rest.Log.InfoFormat("{0} Domain is relative, adding absolute prefix", MsgId); |  | ||||||
|                 qPrefix = String.Format("{0}{1}{2}", Rest.Prefix, Rest.UrlPathSeparator, qPrefix); |  | ||||||
|                 Rest.Log.InfoFormat("{0} Domain is now <{1}>", MsgId, qPrefix); |  | ||||||
|             } |  | ||||||
| 
 |  | ||||||
|             // Load test cases |  | ||||||
| 
 |  | ||||||
|             loadTests(); |  | ||||||
|             foreach (ITest test in tests) |  | ||||||
|             { |  | ||||||
|                 test.Initialize(); |  | ||||||
|             } |  | ||||||
| 
 |  | ||||||
|             // Register interface |  | ||||||
| 
 |  | ||||||
|             Rest.Plugin.AddPathHandler(DoTests,qPrefix,Allocate); |  | ||||||
| 
 |  | ||||||
|             // Activate |  | ||||||
| 
 |  | ||||||
|             enabled = true; |  | ||||||
| 
 |  | ||||||
|             Rest.Log.InfoFormat("{0} Test services initialization complete", MsgId); |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         // Post-construction, pre-enabled initialization opportunity |  | ||||||
|         // Not currently exploited. |  | ||||||
| 
 |  | ||||||
|         public void Initialize() |  | ||||||
|         { |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         // Called by the plug-in to halt REST processing. Local processing is |  | ||||||
|         // disabled, and control blocks until all current processing has  |  | ||||||
|         // completed. No new processing will be started |  | ||||||
| 
 |  | ||||||
|         public void Close() |  | ||||||
|         { |  | ||||||
|             enabled = false; |  | ||||||
|             foreach (ITest test in tests) |  | ||||||
|             { |  | ||||||
|                 test.Close(); |  | ||||||
|             } |  | ||||||
|             Rest.Log.InfoFormat("{0} Test services closing down", MsgId); |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         // Properties |  | ||||||
| 
 |  | ||||||
|         internal string MsgId |  | ||||||
|         { |  | ||||||
|             get { return Rest.MsgId; } |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         #region Interface |  | ||||||
| 
 |  | ||||||
|         private RequestData Allocate(OSHttpRequest request, OSHttpResponse response, string prefix) |  | ||||||
|         { |  | ||||||
|             return new RequestData(request, response, prefix); |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         // Inventory Handler |  | ||||||
| 
 |  | ||||||
|         private void DoTests(RequestData rdata) |  | ||||||
|         { |  | ||||||
|             if (!enabled) |  | ||||||
|                 return; |  | ||||||
| 
 |  | ||||||
|             // Now that we know this is a serious attempt to  |  | ||||||
|             // access inventory data, we should find out who |  | ||||||
|             // is asking, and make sure they are authorized |  | ||||||
|             // to do so. We need to validate the caller's |  | ||||||
|             // identity before revealing anything about the |  | ||||||
|             // status quo. Authenticate throws an exception |  | ||||||
|             // via Fail if no identity information is present. |  | ||||||
|             // |  | ||||||
|             // With the present HTTP server we can't use the |  | ||||||
|             // builtin authentication mechanisms because they |  | ||||||
|             // would be enforced for all in-bound requests. |  | ||||||
|             // Instead we look at the headers ourselves and  |  | ||||||
|             // handle authentication directly. |  | ||||||
|   |  | ||||||
|             try |  | ||||||
|             { |  | ||||||
|                 if (!rdata.IsAuthenticated) |  | ||||||
|                 { |  | ||||||
|                     rdata.Fail(Rest.HttpStatusCodeNotAuthorized,  |  | ||||||
|                           String.Format("user \"{0}\" could not be authenticated", rdata.userName)); |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
|             catch (RestException e) |  | ||||||
|             { |  | ||||||
|                 if (e.statusCode == Rest.HttpStatusCodeNotAuthorized) |  | ||||||
|                 { |  | ||||||
|                     Rest.Log.WarnFormat("{0} User not authenticated", MsgId); |  | ||||||
|                     Rest.Log.DebugFormat("{0} Authorization header: {1}", MsgId, rdata.request.Headers.Get("Authorization")); |  | ||||||
|                 } |  | ||||||
|                 else |  | ||||||
|                 { |  | ||||||
|                     Rest.Log.ErrorFormat("{0} User authentication failed", MsgId); |  | ||||||
|                     Rest.Log.DebugFormat("{0} Authorization header: {1}", MsgId, rdata.request.Headers.Get("Authorization")); |  | ||||||
|                 } |  | ||||||
|                 throw (e); |  | ||||||
|             } |  | ||||||
| 
 |  | ||||||
|             // Check that a test was specified |  | ||||||
| 
 |  | ||||||
|             if (rdata.Parameters.Length < 1) |  | ||||||
|             { |  | ||||||
|                 Rest.Log.DebugFormat("{0} Insufficient parameters", MsgId); |  | ||||||
|                 rdata.Fail(Rest.HttpStatusCodeBadRequest, "not enough parameters"); |  | ||||||
|             } |  | ||||||
| 
 |  | ||||||
|             // Select the test |  | ||||||
| 
 |  | ||||||
|             foreach (ITest test in tests) |  | ||||||
|             { |  | ||||||
|                 if (!rdata.handled) |  | ||||||
|                     test.Execute(rdata); |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         #endregion Interface |  | ||||||
| 
 |  | ||||||
|         private static bool    testsLoaded = false; |  | ||||||
|         private static List<Type> classes  = new List<Type>(); |  | ||||||
|         private static List<ITest>   tests = new List<ITest>(); |  | ||||||
|         private static Type[]        parms = new Type[0]; |  | ||||||
|         private static Object[]      args  = new Object[0]; |  | ||||||
| 
 |  | ||||||
|         static RestTestServices() |  | ||||||
|         { |  | ||||||
|             Module[] mods = Assembly.GetExecutingAssembly().GetModules(); |  | ||||||
|             foreach (Module m in mods) |  | ||||||
|             { |  | ||||||
|                 Type[] types = m.GetTypes(); |  | ||||||
|                 foreach (Type t in types)  |  | ||||||
|                 { |  | ||||||
|                     try |  | ||||||
|                     { |  | ||||||
|                         if (t.GetInterface("ITest") != null) |  | ||||||
|                         { |  | ||||||
|                             classes.Add(t); |  | ||||||
|                         } |  | ||||||
|                     } |  | ||||||
|                     catch (Exception e) |  | ||||||
|                     { |  | ||||||
|                         Rest.Log.WarnFormat("[STATIC-TEST] Unable to include test {0} : {1}", t, e.Message); |  | ||||||
|                     } |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         /// <summary> |  | ||||||
|         /// This routine loads all of the handlers discovered during |  | ||||||
|         /// instance initialization. Each handler is responsible for |  | ||||||
|         /// registering itself with this handler. |  | ||||||
|         /// I was not able to make this code work in a constructor. |  | ||||||
|         /// </summary> |  | ||||||
| 
 |  | ||||||
|         private void loadTests() |  | ||||||
|         { |  | ||||||
|             lock (tests) |  | ||||||
|             { |  | ||||||
|                 if (!testsLoaded) |  | ||||||
|                 { |  | ||||||
| 
 |  | ||||||
|                     ConstructorInfo ci; |  | ||||||
|                     Object          ht; |  | ||||||
| 
 |  | ||||||
|                     foreach (Type t in classes) |  | ||||||
|                     { |  | ||||||
|                         try |  | ||||||
|                         { |  | ||||||
|                             if (t.GetInterface("ITest") != null) |  | ||||||
|                             { |  | ||||||
|                                 ci = t.GetConstructor(parms); |  | ||||||
|                                 ht = ci.Invoke(args); |  | ||||||
|                                 tests.Add((ITest)ht); |  | ||||||
|                                 Rest.Log.InfoFormat("{0} Test {1} added", MsgId, t); |  | ||||||
|                             } |  | ||||||
|                         } |  | ||||||
|                         catch (Exception e) |  | ||||||
|                         { |  | ||||||
|                             Rest.Log.WarnFormat("{0} Unable to load test {1} : {2}", MsgId, t, e.Message); |  | ||||||
|                         } |  | ||||||
|                     } |  | ||||||
|                     testsLoaded = true; |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|     } |  | ||||||
| } |  | ||||||
|  | @ -1,46 +0,0 @@ | ||||||
| /* |  | ||||||
| * Copyright (c) Contributors, http://opensimulator.org/ |  | ||||||
| * See CONTRIBUTORS.TXT for a full list of copyright holders. |  | ||||||
| * |  | ||||||
| * Redistribution and use in source and binary forms, with or without |  | ||||||
| * modification, are permitted provided that the following conditions are met: |  | ||||||
| *     * Redistributions of source code must retain the above copyright |  | ||||||
| *       notice, this list of conditions and the following disclaimer. |  | ||||||
| *     * Redistributions in binary form must reproduce the above copyright |  | ||||||
| *       notice, this list of conditions and the following disclaimer in the |  | ||||||
| *       documentation and/or other materials provided with the distribution. |  | ||||||
| *     * Neither the name of the OpenSimulator Project nor the |  | ||||||
| *       names of its contributors may be used to endorse or promote products |  | ||||||
| *       derived from this software without specific prior written permission. |  | ||||||
| * |  | ||||||
| * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY |  | ||||||
| * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |  | ||||||
| * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |  | ||||||
| * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY |  | ||||||
| * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |  | ||||||
| * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |  | ||||||
| * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |  | ||||||
| * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |  | ||||||
| * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |  | ||||||
| * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |  | ||||||
| *  |  | ||||||
| */ |  | ||||||
| 
 |  | ||||||
| namespace OpenSim.ApplicationPlugins.Rest.Inventory |  | ||||||
| { |  | ||||||
| 
 |  | ||||||
|     /// <summary> |  | ||||||
|     /// This interface represents the boundary between the general purpose |  | ||||||
|     /// REST plugin handling, and the functionally specific handlers. The |  | ||||||
|     /// handler knows only to initialzie and terminate all such handlers  |  | ||||||
|     /// that it finds. |  | ||||||
|     /// </summary> |  | ||||||
| 
 |  | ||||||
|     internal interface ITest |  | ||||||
|     { |  | ||||||
|         void Initialize(); |  | ||||||
|         void Execute(RequestData rdata); |  | ||||||
|         void Close(); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
| } |  | ||||||
|  | @ -1,204 +0,0 @@ | ||||||
| /* |  | ||||||
|  * Copyright (c) Contributors, http://opensimulator.org/ |  | ||||||
|  * See CONTRIBUTORS.TXT for a full list of copyright holders. |  | ||||||
|  * |  | ||||||
|  * Redistribution and use in source and binary forms, with or without |  | ||||||
|  * modification, are permitted provided that the following conditions are met: |  | ||||||
|  *     * Redistributions of source code must retain the above copyright |  | ||||||
|  *       notice, this list of conditions and the following disclaimer. |  | ||||||
|  *     * Redistributions in binary form must reproduce the above copyright |  | ||||||
|  *       notice, this list of conditions and the following disclaimer in the |  | ||||||
|  *       documentation and/or other materials provided with the distribution. |  | ||||||
|  *     * Neither the name of the OpenSimulator Project nor the |  | ||||||
|  *       names of its contributors may be used to endorse or promote products |  | ||||||
|  *       derived from this software without specific prior written permission. |  | ||||||
|  * |  | ||||||
|  * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY |  | ||||||
|  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |  | ||||||
|  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |  | ||||||
|  * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY |  | ||||||
|  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |  | ||||||
|  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |  | ||||||
|  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |  | ||||||
|  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |  | ||||||
|  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |  | ||||||
|  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |  | ||||||
|  */ |  | ||||||
| 
 |  | ||||||
| using System; |  | ||||||
| using OpenMetaverse; |  | ||||||
| using OpenSim.Region.Framework.Scenes; |  | ||||||
| 
 |  | ||||||
| namespace OpenSim.ApplicationPlugins.Rest.Inventory.Tests |  | ||||||
| { |  | ||||||
|     public class Remote : ITest |  | ||||||
|     { |  | ||||||
|         private static readonly int PARM_TESTID      = 0; |  | ||||||
|         private static readonly int PARM_COMMAND     = 1; |  | ||||||
| 
 |  | ||||||
|         private static readonly int PARM_MOVE_AVATAR = 2; |  | ||||||
|         private static readonly int PARM_MOVE_X      = 3; |  | ||||||
|         private static readonly int PARM_MOVE_Y      = 4; |  | ||||||
|         private static readonly int PARM_MOVE_Z      = 5; |  | ||||||
| 
 |  | ||||||
|         private bool    enabled = false; |  | ||||||
| 
 |  | ||||||
|         // No constructor code is required. |  | ||||||
| 
 |  | ||||||
|         public Remote() |  | ||||||
|         { |  | ||||||
|             Rest.Log.InfoFormat("{0} Remote services constructor", MsgId); |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         // Post-construction, pre-enabled initialization opportunity |  | ||||||
|         // Not currently exploited. |  | ||||||
| 
 |  | ||||||
|         public void Initialize() |  | ||||||
|         { |  | ||||||
|             enabled = true; |  | ||||||
|             Rest.Log.InfoFormat("{0} Remote services initialized", MsgId); |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         // Called by the plug-in to halt REST processing. Local processing is |  | ||||||
|         // disabled, and control blocks until all current processing has |  | ||||||
|         // completed. No new processing will be started |  | ||||||
| 
 |  | ||||||
|         public void Close() |  | ||||||
|         { |  | ||||||
|             enabled = false; |  | ||||||
|             Rest.Log.InfoFormat("{0} Remote services closing down", MsgId); |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         // Properties |  | ||||||
| 
 |  | ||||||
|         internal string MsgId |  | ||||||
|         { |  | ||||||
|             get { return Rest.MsgId; } |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         // Remote Handler |  | ||||||
|         // Key information of interest here is the Parameters array, each |  | ||||||
|         // entry represents an element of the URI, with element zero being |  | ||||||
|         // the |  | ||||||
| 
 |  | ||||||
|         public void Execute(RequestData rdata) |  | ||||||
|         { |  | ||||||
|             if (!enabled) return; |  | ||||||
| 
 |  | ||||||
|             // If we can't relate to what's there, leave it for others. |  | ||||||
| 
 |  | ||||||
|             if (rdata.Parameters.Length == 0 || rdata.Parameters[PARM_TESTID] != "remote") |  | ||||||
|                 return; |  | ||||||
| 
 |  | ||||||
|             Rest.Log.DebugFormat("{0} REST Remote handler ENTRY", MsgId); |  | ||||||
| 
 |  | ||||||
|             // Remove the prefix and what's left are the parameters. If we don't have |  | ||||||
|             // the parameters we need, fail the request. Parameters do NOT include |  | ||||||
|             // any supplied query values. |  | ||||||
| 
 |  | ||||||
|             if (rdata.Parameters.Length > 1) |  | ||||||
|             { |  | ||||||
|                 switch (rdata.Parameters[PARM_COMMAND].ToLower()) |  | ||||||
|                 { |  | ||||||
|                     case "move" : |  | ||||||
|                         DoMove(rdata); |  | ||||||
|                         break; |  | ||||||
|                     default : |  | ||||||
|                         DoHelp(rdata); |  | ||||||
|                         break; |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
|             else |  | ||||||
|             { |  | ||||||
|                 DoHelp(rdata); |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         private void DoHelp(RequestData rdata) |  | ||||||
|         { |  | ||||||
|             rdata.body = Help; |  | ||||||
|             rdata.Complete(); |  | ||||||
|             rdata.Respond("Help"); |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         private void DoMove(RequestData rdata) |  | ||||||
|         { |  | ||||||
|             if (rdata.Parameters.Length < 6) |  | ||||||
|             { |  | ||||||
|                 Rest.Log.WarnFormat("{0} Move: No movement information provided", MsgId); |  | ||||||
|                 rdata.Fail(Rest.HttpStatusCodeBadRequest, "no movement information provided"); |  | ||||||
|             } |  | ||||||
|             else |  | ||||||
|             { |  | ||||||
|                 string[] names = rdata.Parameters[PARM_MOVE_AVATAR].Split(Rest.CA_SPACE); |  | ||||||
|                 ScenePresence presence = null; |  | ||||||
|                 Scene scene = null; |  | ||||||
| 
 |  | ||||||
|                 if (names.Length != 2) |  | ||||||
|                 { |  | ||||||
|                     rdata.Fail(Rest.HttpStatusCodeBadRequest, |  | ||||||
|                         String.Format("invalid avatar name: <{0}>",rdata.Parameters[PARM_MOVE_AVATAR])); |  | ||||||
|                 } |  | ||||||
| 
 |  | ||||||
|                 Rest.Log.WarnFormat("{0} '{1}' command received for {2} {3}", |  | ||||||
|                             MsgId, rdata.Parameters[0], names[0], names[1]); |  | ||||||
| 
 |  | ||||||
|                 // The first parameter should be an avatar name, look for the |  | ||||||
|                 // avatar in the known regions first. |  | ||||||
| 
 |  | ||||||
|                 Rest.main.SceneManager.ForEachScene(delegate(Scene s) |  | ||||||
|                 { |  | ||||||
|                     s.ForEachRootScenePresence(delegate(ScenePresence sp) |  | ||||||
|                     { |  | ||||||
|                         if (sp.Firstname == names[0] && sp.Lastname == names[1]) |  | ||||||
|                         { |  | ||||||
|                             scene = s; |  | ||||||
|                             presence = sp; |  | ||||||
|                         } |  | ||||||
|                     }); |  | ||||||
|                 }); |  | ||||||
| 
 |  | ||||||
|                 if (presence != null) |  | ||||||
|                 { |  | ||||||
|                     Rest.Log.DebugFormat("{0} Move : Avatar {1} located in region {2}", |  | ||||||
|                                 MsgId, rdata.Parameters[PARM_MOVE_AVATAR], scene.RegionInfo.RegionName); |  | ||||||
| 
 |  | ||||||
|                     try |  | ||||||
|                     { |  | ||||||
|                         float x = Convert.ToSingle(rdata.Parameters[PARM_MOVE_X]); |  | ||||||
|                         float y = Convert.ToSingle(rdata.Parameters[PARM_MOVE_Y]); |  | ||||||
|                         float z = Convert.ToSingle(rdata.Parameters[PARM_MOVE_Z]); |  | ||||||
|                         Vector3 vector = new Vector3(x, y, z); |  | ||||||
|                         presence.MoveToTarget(vector, false, false); |  | ||||||
|                     } |  | ||||||
|                     catch (Exception e) |  | ||||||
|                     { |  | ||||||
|                         rdata.Fail(Rest.HttpStatusCodeBadRequest, |  | ||||||
|                                    String.Format("invalid parameters: {0}", e.Message)); |  | ||||||
|                     } |  | ||||||
|                 } |  | ||||||
|                 else |  | ||||||
|                 { |  | ||||||
|                     rdata.Fail(Rest.HttpStatusCodeBadRequest, |  | ||||||
|                             String.Format("avatar {0} not present", rdata.Parameters[PARM_MOVE_AVATAR])); |  | ||||||
|                 } |  | ||||||
| 
 |  | ||||||
|                 rdata.Complete(); |  | ||||||
|                 rdata.Respond("OK"); |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         private static readonly string Help = |  | ||||||
|                 "<html>" |  | ||||||
|               + "<head><title>Remote Command Usage</title></head>" |  | ||||||
|               + "<body>" |  | ||||||
|               + "<p>Supported commands are:</p>" |  | ||||||
|               + "<dl>" |  | ||||||
|               + "<dt>move/avatar-name/x/y/z</dt>" |  | ||||||
|               + "<dd>moves the specified avatar to another location</dd>" |  | ||||||
|               + "</dl>" |  | ||||||
|               + "</body>" |  | ||||||
|               + "</html>" |  | ||||||
|         ; |  | ||||||
|     } |  | ||||||
| } |  | ||||||
|  | @ -1,228 +0,0 @@ | ||||||
| /* |  | ||||||
|  * Copyright (c) Contributors, http://opensimulator.org/ |  | ||||||
|  * See CONTRIBUTORS.TXT for a full list of copyright holders. |  | ||||||
|  * |  | ||||||
|  * Redistribution and use in source and binary forms, with or without |  | ||||||
|  * modification, are permitted provided that the following conditions are met: |  | ||||||
|  *     * Redistributions of source code must retain the above copyright |  | ||||||
|  *       notice, this list of conditions and the following disclaimer. |  | ||||||
|  *     * Redistributions in binary form must reproduce the above copyright |  | ||||||
|  *       notice, this list of conditions and the following disclaimer in the |  | ||||||
|  *       documentation and/or other materials provided with the distribution. |  | ||||||
|  *     * Neither the name of the OpenSimulator Project nor the |  | ||||||
|  *       names of its contributors may be used to endorse or promote products |  | ||||||
|  *       derived from this software without specific prior written permission. |  | ||||||
|  * |  | ||||||
|  * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY |  | ||||||
|  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |  | ||||||
|  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |  | ||||||
|  * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY |  | ||||||
|  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |  | ||||||
|  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |  | ||||||
|  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |  | ||||||
|  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |  | ||||||
|  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |  | ||||||
|  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |  | ||||||
|  */ |  | ||||||
| 
 |  | ||||||
| using System; |  | ||||||
| using System.IO; |  | ||||||
| using System.Xml.Serialization; |  | ||||||
| using OpenMetaverse; |  | ||||||
| using OpenSim.Framework; |  | ||||||
| using OpenSim.Framework.Servers; |  | ||||||
| using OpenSim.Framework.Servers.HttpServer; |  | ||||||
| using OpenSim.Region.Framework.Interfaces; |  | ||||||
| using OpenSim.Region.Framework.Scenes; |  | ||||||
| 
 |  | ||||||
| namespace OpenSim.ApplicationPlugins.Rest.Regions |  | ||||||
| { |  | ||||||
|     public partial class RestRegionPlugin : RestPlugin |  | ||||||
|     { |  | ||||||
|         #region GET methods |  | ||||||
|         public string GetHandler(string request, string path, string param, |  | ||||||
|                                  IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) |  | ||||||
|         { |  | ||||||
|             // foreach (string h in httpRequest.Headers.AllKeys) |  | ||||||
|             //     foreach (string v in httpRequest.Headers.GetValues(h)) |  | ||||||
|             //         m_log.DebugFormat("{0} IsGod: {1} -> {2}", MsgID, h, v); |  | ||||||
| 
 |  | ||||||
|             MsgID = RequestID; |  | ||||||
|             m_log.DebugFormat("{0} GET path {1} param {2}", MsgID, path, param); |  | ||||||
| 
 |  | ||||||
|             try |  | ||||||
|             { |  | ||||||
|                 // param empty: regions list |  | ||||||
|                 if (String.IsNullOrEmpty(param)) return GetHandlerRegions(httpResponse); |  | ||||||
| 
 |  | ||||||
|                 // param not empty: specific region |  | ||||||
|                 return GetHandlerRegion(httpResponse, param); |  | ||||||
|             } |  | ||||||
|             catch (Exception e) |  | ||||||
|             { |  | ||||||
|                 return Failure(httpResponse, OSHttpStatusCode.ServerErrorInternalError, "GET", e); |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         public string GetHandlerRegions(IOSHttpResponse httpResponse) |  | ||||||
|         { |  | ||||||
|             RestXmlWriter rxw = new RestXmlWriter(new StringWriter()); |  | ||||||
| 
 |  | ||||||
|             rxw.WriteStartElement(String.Empty, "regions", String.Empty); |  | ||||||
|             foreach (Scene s in App.SceneManager.Scenes) |  | ||||||
|             { |  | ||||||
|                 rxw.WriteStartElement(String.Empty, "uuid", String.Empty); |  | ||||||
|                 rxw.WriteString(s.RegionInfo.RegionID.ToString()); |  | ||||||
|                 rxw.WriteEndElement(); |  | ||||||
|             } |  | ||||||
|             rxw.WriteEndElement(); |  | ||||||
| 
 |  | ||||||
|             return rxw.ToString(); |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         protected string ShortRegionInfo(string key, string value) |  | ||||||
|         { |  | ||||||
|             RestXmlWriter rxw = new RestXmlWriter(new StringWriter()); |  | ||||||
| 
 |  | ||||||
|             if (String.IsNullOrEmpty(value) || |  | ||||||
|                 String.IsNullOrEmpty(key)) return null; |  | ||||||
| 
 |  | ||||||
|             rxw.WriteStartElement(String.Empty, "region", String.Empty); |  | ||||||
|             rxw.WriteStartElement(String.Empty, key, String.Empty); |  | ||||||
|             rxw.WriteString(value); |  | ||||||
|             rxw.WriteEndDocument(); |  | ||||||
| 
 |  | ||||||
|             return rxw.ToString(); |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         public string GetHandlerRegion(IOSHttpResponse httpResponse, string param) |  | ||||||
|         { |  | ||||||
|             // be resilient and don't get confused by a terminating '/' |  | ||||||
|             param = param.TrimEnd(new char[]{'/'}); |  | ||||||
|             string[] comps = param.Split('/'); |  | ||||||
|             UUID regionID = (UUID)comps[0]; |  | ||||||
| 
 |  | ||||||
|             m_log.DebugFormat("{0} GET region UUID {1}", MsgID, regionID.ToString()); |  | ||||||
| 
 |  | ||||||
|             if (UUID.Zero == regionID) throw new Exception("missing region ID"); |  | ||||||
| 
 |  | ||||||
|             Scene scene = null; |  | ||||||
|             App.SceneManager.TryGetScene(regionID, out scene); |  | ||||||
|             if (null == scene) return Failure(httpResponse, OSHttpStatusCode.ClientErrorNotFound, |  | ||||||
|                                               "GET", "cannot find region {0}", regionID.ToString()); |  | ||||||
| 
 |  | ||||||
|             RegionDetails details = new RegionDetails(scene.RegionInfo); |  | ||||||
| 
 |  | ||||||
|             // m_log.DebugFormat("{0} GET comps {1}", MsgID, comps.Length); |  | ||||||
|             // for (int i = 0; i < comps.Length; i++)  m_log.DebugFormat("{0} GET comps[{1}] >{2}<", MsgID, i, comps[i]); |  | ||||||
| 
 |  | ||||||
|             if (1 == comps.Length) |  | ||||||
|             { |  | ||||||
|                 // complete region details requested |  | ||||||
|                 RestXmlWriter rxw = new RestXmlWriter(new StringWriter()); |  | ||||||
|                 XmlSerializer xs = new XmlSerializer(typeof(RegionDetails)); |  | ||||||
|                 xs.Serialize(rxw, details, _xmlNs); |  | ||||||
|                 return rxw.ToString(); |  | ||||||
|             } |  | ||||||
| 
 |  | ||||||
|             if (2 == comps.Length) |  | ||||||
|             { |  | ||||||
|                 string resp = ShortRegionInfo(comps[1], details[comps[1]]); |  | ||||||
|                 if (null != resp) return resp; |  | ||||||
| 
 |  | ||||||
|                 // m_log.DebugFormat("{0} GET comps advanced: >{1}<", MsgID, comps[1]); |  | ||||||
| 
 |  | ||||||
|                 // check for {terrain,stats,prims} |  | ||||||
|                 switch (comps[1].ToLower()) |  | ||||||
|                 { |  | ||||||
|                 case "terrain": |  | ||||||
|                     return RegionTerrain(httpResponse, scene); |  | ||||||
| 
 |  | ||||||
|                 case "stats": |  | ||||||
|                     return RegionStats(httpResponse, scene); |  | ||||||
| 
 |  | ||||||
|                 case "prims": |  | ||||||
|                     return RegionPrims(httpResponse, scene, Vector3.Zero, Vector3.Zero); |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
| 
 |  | ||||||
|             if (3 == comps.Length) |  | ||||||
|             { |  | ||||||
|                 switch (comps[1].ToLower()) |  | ||||||
|                 { |  | ||||||
|                 case "prims": |  | ||||||
|                     string[] subregion = comps[2].Split(','); |  | ||||||
|                     if (subregion.Length == 6) |  | ||||||
|                     { |  | ||||||
|                         Vector3 min, max; |  | ||||||
|                         try |  | ||||||
|                         { |  | ||||||
|                             min = new Vector3((float)Double.Parse(subregion[0], Culture.NumberFormatInfo), (float)Double.Parse(subregion[1], Culture.NumberFormatInfo), (float)Double.Parse(subregion[2], Culture.NumberFormatInfo)); |  | ||||||
|                             max = new Vector3((float)Double.Parse(subregion[3], Culture.NumberFormatInfo), (float)Double.Parse(subregion[4], Culture.NumberFormatInfo), (float)Double.Parse(subregion[5], Culture.NumberFormatInfo)); |  | ||||||
|                         } |  | ||||||
|                         catch (Exception) |  | ||||||
|                         { |  | ||||||
|                             return Failure(httpResponse, OSHttpStatusCode.ClientErrorBadRequest, |  | ||||||
|                                            "GET", "invalid subregion parameter"); |  | ||||||
|                         } |  | ||||||
|                         return RegionPrims(httpResponse, scene, min, max); |  | ||||||
|                     } |  | ||||||
|                     else |  | ||||||
|                     { |  | ||||||
|                         return Failure(httpResponse, OSHttpStatusCode.ClientErrorBadRequest, |  | ||||||
|                                        "GET", "invalid subregion parameter"); |  | ||||||
|                     } |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
| 
 |  | ||||||
|             return Failure(httpResponse, OSHttpStatusCode.ClientErrorBadRequest, |  | ||||||
|                            "GET", "too many parameters {0}", param); |  | ||||||
|         } |  | ||||||
|         #endregion GET methods |  | ||||||
| 
 |  | ||||||
|         protected string RegionTerrain(IOSHttpResponse httpResponse, Scene scene) |  | ||||||
|         { |  | ||||||
|             httpResponse.SendChunked = true; |  | ||||||
|             httpResponse.ContentType = "text/xml"; |  | ||||||
| 
 |  | ||||||
|             return scene.Heightmap.SaveToXmlString(); |  | ||||||
|             //return Failure(httpResponse, OSHttpStatusCode.ServerErrorNotImplemented, |  | ||||||
|             //               "GET", "terrain not implemented"); |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         protected string RegionStats(IOSHttpResponse httpResponse, Scene scene) |  | ||||||
|         { |  | ||||||
|             int users = scene.GetRootAgentCount(); |  | ||||||
|             int objects = scene.Entities.Count - users; |  | ||||||
| 
 |  | ||||||
|             RestXmlWriter rxw = new RestXmlWriter(new StringWriter()); |  | ||||||
| 
 |  | ||||||
|             rxw.WriteStartElement(String.Empty, "region", String.Empty); |  | ||||||
|             rxw.WriteStartElement(String.Empty, "stats", String.Empty); |  | ||||||
| 
 |  | ||||||
|             rxw.WriteStartElement(String.Empty, "users", String.Empty); |  | ||||||
|             rxw.WriteString(users.ToString()); |  | ||||||
|             rxw.WriteEndElement(); |  | ||||||
| 
 |  | ||||||
|             rxw.WriteStartElement(String.Empty, "objects", String.Empty); |  | ||||||
|             rxw.WriteString(objects.ToString()); |  | ||||||
|             rxw.WriteEndElement(); |  | ||||||
| 
 |  | ||||||
|             rxw.WriteEndDocument(); |  | ||||||
| 
 |  | ||||||
|             return rxw.ToString(); |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         protected string RegionPrims(IOSHttpResponse httpResponse, Scene scene, Vector3 min, Vector3 max) |  | ||||||
|         { |  | ||||||
|             httpResponse.SendChunked = true; |  | ||||||
|             httpResponse.ContentType = "text/xml"; |  | ||||||
|              |  | ||||||
|             IRegionSerialiserModule serialiser = scene.RequestModuleInterface<IRegionSerialiserModule>(); |  | ||||||
|             if (serialiser != null) |  | ||||||
|                 serialiser.SavePrimsToXml2(scene, new StreamWriter(httpResponse.OutputStream), min, max); |  | ||||||
|              |  | ||||||
|             return ""; |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| } |  | ||||||
|  | @ -1,136 +0,0 @@ | ||||||
| /* |  | ||||||
|  * Copyright (c) Contributors, http://opensimulator.org/ |  | ||||||
|  * See CONTRIBUTORS.TXT for a full list of copyright holders. |  | ||||||
|  * |  | ||||||
|  * Redistribution and use in source and binary forms, with or without |  | ||||||
|  * modification, are permitted provided that the following conditions are met: |  | ||||||
|  *     * Redistributions of source code must retain the above copyright |  | ||||||
|  *       notice, this list of conditions and the following disclaimer. |  | ||||||
|  *     * Redistributions in binary form must reproduce the above copyright |  | ||||||
|  *       notice, this list of conditions and the following disclaimer in the |  | ||||||
|  *       documentation and/or other materials provided with the distribution. |  | ||||||
|  *     * Neither the name of the OpenSimulator Project nor the |  | ||||||
|  *       names of its contributors may be used to endorse or promote products |  | ||||||
|  *       derived from this software without specific prior written permission. |  | ||||||
|  * |  | ||||||
|  * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY |  | ||||||
|  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |  | ||||||
|  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |  | ||||||
|  * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY |  | ||||||
|  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |  | ||||||
|  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |  | ||||||
|  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |  | ||||||
|  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |  | ||||||
|  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |  | ||||||
|  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |  | ||||||
|  */ |  | ||||||
| 
 |  | ||||||
| using System; |  | ||||||
| using System.IO; |  | ||||||
| using System.Xml.Serialization; |  | ||||||
| using OpenMetaverse; |  | ||||||
| using OpenSim.Framework.Servers; |  | ||||||
| using OpenSim.Framework.Servers.HttpServer; |  | ||||||
| using OpenSim.Region.Framework.Interfaces; |  | ||||||
| using OpenSim.Region.Framework.Scenes; |  | ||||||
| 
 |  | ||||||
| namespace OpenSim.ApplicationPlugins.Rest.Regions |  | ||||||
| { |  | ||||||
|     public partial class RestRegionPlugin : RestPlugin |  | ||||||
|     { |  | ||||||
|         #region GET methods |  | ||||||
|         public string GetRegionInfoHandler(string request, string path, string param, |  | ||||||
|                                            IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) |  | ||||||
|         { |  | ||||||
|             // foreach (string h in httpRequest.Headers.AllKeys) |  | ||||||
|             //     foreach (string v in httpRequest.Headers.GetValues(h)) |  | ||||||
|             //         m_log.DebugFormat("{0} IsGod: {1} -> {2}", MsgID, h, v); |  | ||||||
| 
 |  | ||||||
|             MsgID = RequestID; |  | ||||||
|             m_log.DebugFormat("{0} GET path {1} param {2}", MsgID, path, param); |  | ||||||
| 
 |  | ||||||
|             try |  | ||||||
|             { |  | ||||||
|                 // param empty: regions list |  | ||||||
|                 // if (String.IsNullOrEmpty(param))  |  | ||||||
|                 return GetRegionInfoHandlerRegions(httpResponse); |  | ||||||
|                      |  | ||||||
|                 // // param not empty: specific region |  | ||||||
|                 // return GetRegionInfoHandlerRegion(httpResponse, param); |  | ||||||
|             } |  | ||||||
|             catch (Exception e) |  | ||||||
|             { |  | ||||||
|                 return Failure(httpResponse, OSHttpStatusCode.ServerErrorInternalError, "GET", e); |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         public string GetRegionInfoHandlerRegions(IOSHttpResponse httpResponse) |  | ||||||
|         { |  | ||||||
|             RestXmlWriter rxw = new RestXmlWriter(new StringWriter()); |  | ||||||
| 
 |  | ||||||
|             // regions info |  | ||||||
|             rxw.WriteStartElement(String.Empty, "regions", String.Empty); |  | ||||||
|             { |  | ||||||
|                 // regions info: number of regions |  | ||||||
|                 rxw.WriteStartAttribute(String.Empty, "number", String.Empty); |  | ||||||
|                 rxw.WriteValue(App.SceneManager.Scenes.Count); |  | ||||||
|                 rxw.WriteEndAttribute(); |  | ||||||
| 
 |  | ||||||
|                 // regions info: max number of regions |  | ||||||
|                 rxw.WriteStartAttribute(String.Empty, "max", String.Empty); |  | ||||||
|                 if (App.ConfigSource.Source.Configs["RemoteAdmin"] != null) |  | ||||||
|                 { |  | ||||||
|                     rxw.WriteValue(App.ConfigSource.Source.Configs["RemoteAdmin"].GetInt("region_limit", -1)); |  | ||||||
|                 } |  | ||||||
|                 else |  | ||||||
|                 { |  | ||||||
|                     rxw.WriteValue(-1); |  | ||||||
|                 } |  | ||||||
|                 rxw.WriteEndAttribute(); |  | ||||||
|                  |  | ||||||
|                 // regions info: region |  | ||||||
|                 foreach (Scene s in App.SceneManager.Scenes) |  | ||||||
|                 { |  | ||||||
|                     rxw.WriteStartElement(String.Empty, "region", String.Empty); |  | ||||||
|                      |  | ||||||
|                     rxw.WriteStartAttribute(String.Empty, "uuid", String.Empty); |  | ||||||
|                     rxw.WriteString(s.RegionInfo.RegionID.ToString()); |  | ||||||
|                     rxw.WriteEndAttribute(); |  | ||||||
|                      |  | ||||||
|                     rxw.WriteStartAttribute(String.Empty, "name", String.Empty); |  | ||||||
|                     rxw.WriteString(s.RegionInfo.RegionName); |  | ||||||
|                     rxw.WriteEndAttribute(); |  | ||||||
|                      |  | ||||||
|                     rxw.WriteStartAttribute(String.Empty, "x", String.Empty); |  | ||||||
|                     rxw.WriteValue(s.RegionInfo.RegionLocX); |  | ||||||
|                     rxw.WriteEndAttribute(); |  | ||||||
|                      |  | ||||||
|                     rxw.WriteStartAttribute(String.Empty, "y", String.Empty); |  | ||||||
|                     rxw.WriteValue(s.RegionInfo.RegionLocY); |  | ||||||
|                     rxw.WriteEndAttribute(); |  | ||||||
|                      |  | ||||||
|                     rxw.WriteStartAttribute(String.Empty, "external_hostname", String.Empty); |  | ||||||
|                     rxw.WriteString(s.RegionInfo.ExternalHostName); |  | ||||||
|                     rxw.WriteEndAttribute(); |  | ||||||
|                      |  | ||||||
|                     rxw.WriteStartAttribute(String.Empty, "ip", String.Empty); |  | ||||||
|                     rxw.WriteString(s.RegionInfo.InternalEndPoint.ToString()); |  | ||||||
|                     rxw.WriteEndAttribute(); |  | ||||||
|                      |  | ||||||
|                     int users = s.GetRootAgentCount(); |  | ||||||
|                     rxw.WriteStartAttribute(String.Empty, "avatars", String.Empty); |  | ||||||
|                     rxw.WriteValue(users); |  | ||||||
|                     rxw.WriteEndAttribute(); |  | ||||||
|                      |  | ||||||
|                     rxw.WriteStartAttribute(String.Empty, "objects", String.Empty); |  | ||||||
|                     rxw.WriteValue(s.Entities.Count - users); |  | ||||||
|                     rxw.WriteEndAttribute(); |  | ||||||
|                      |  | ||||||
|                     rxw.WriteEndElement(); |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
|             return rxw.ToString(); |  | ||||||
|         } |  | ||||||
|         #endregion GET methods |  | ||||||
|     } |  | ||||||
| } |  | ||||||
|  | @ -1,122 +0,0 @@ | ||||||
| /* |  | ||||||
|  * Copyright (c) Contributors, http://opensimulator.org/ |  | ||||||
|  * See CONTRIBUTORS.TXT for a full list of copyright holders. |  | ||||||
|  * |  | ||||||
|  * Redistribution and use in source and binary forms, with or without |  | ||||||
|  * modification, are permitted provided that the following conditions are met: |  | ||||||
|  *     * Redistributions of source code must retain the above copyright |  | ||||||
|  *       notice, this list of conditions and the following disclaimer. |  | ||||||
|  *     * Redistributions in binary form must reproduce the above copyright |  | ||||||
|  *       notice, this list of conditions and the following disclaimer in the |  | ||||||
|  *       documentation and/or other materials provided with the distribution. |  | ||||||
|  *     * Neither the name of the OpenSimulator Project nor the |  | ||||||
|  *       names of its contributors may be used to endorse or promote products |  | ||||||
|  *       derived from this software without specific prior written permission. |  | ||||||
|  * |  | ||||||
|  * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY |  | ||||||
|  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |  | ||||||
|  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |  | ||||||
|  * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY |  | ||||||
|  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |  | ||||||
|  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |  | ||||||
|  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |  | ||||||
|  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |  | ||||||
|  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |  | ||||||
|  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |  | ||||||
|  */ |  | ||||||
| 
 |  | ||||||
| using System; |  | ||||||
| using System.IO; |  | ||||||
| using OpenMetaverse; |  | ||||||
| using OpenSim.Framework.Servers; |  | ||||||
| using OpenSim.Framework.Servers.HttpServer; |  | ||||||
| using OpenSim.Region.Framework.Interfaces; |  | ||||||
| using OpenSim.Region.Framework.Scenes; |  | ||||||
| 
 |  | ||||||
| namespace OpenSim.ApplicationPlugins.Rest.Regions |  | ||||||
| { |  | ||||||
|     public partial class RestRegionPlugin : RestPlugin |  | ||||||
|     { |  | ||||||
|         #region POST methods |  | ||||||
| 
 |  | ||||||
|         public string PostHandler(string request, string path, string param, |  | ||||||
|                                   IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) |  | ||||||
|         { |  | ||||||
|             // foreach (string h in httpRequest.Headers.AllKeys) |  | ||||||
|             //     foreach (string v in httpRequest.Headers.GetValues(h)) |  | ||||||
|             //         m_log.DebugFormat("{0} IsGod: {1} -> {2}", MsgID, h, v); |  | ||||||
| 
 |  | ||||||
|             MsgID = RequestID; |  | ||||||
|             m_log.DebugFormat("{0} POST path {1} param {2}", MsgID, path, param); |  | ||||||
| 
 |  | ||||||
|             try |  | ||||||
|             { |  | ||||||
|                 // param empty: new region post |  | ||||||
|                 if (!IsGod(httpRequest)) |  | ||||||
|                     // XXX: this needs to be turned into a FailureUnauthorized(...) |  | ||||||
|                     return Failure(httpResponse, OSHttpStatusCode.ClientErrorUnauthorized, |  | ||||||
|                                    "GET", "you are not god"); |  | ||||||
| 
 |  | ||||||
|                 if (String.IsNullOrEmpty(param)) return CreateRegion(httpRequest, httpResponse); |  | ||||||
| 
 |  | ||||||
|                 // Parse region ID and other parameters |  | ||||||
|                 param = param.TrimEnd(new char[] {'/'}); |  | ||||||
|                 string[] comps = param.Split('/'); |  | ||||||
|                 UUID regionID = (UUID) comps[0]; |  | ||||||
| 
 |  | ||||||
|                 m_log.DebugFormat("{0} POST region UUID {1}", MsgID, regionID.ToString()); |  | ||||||
|                 if (UUID.Zero == regionID) throw new Exception("missing region ID"); |  | ||||||
| 
 |  | ||||||
|                 Scene scene = null; |  | ||||||
|                 App.SceneManager.TryGetScene(regionID, out scene); |  | ||||||
|                 if (null == scene) |  | ||||||
|                     return Failure(httpResponse, OSHttpStatusCode.ClientErrorNotFound, |  | ||||||
|                                    "POST", "cannot find region {0}", regionID.ToString()); |  | ||||||
| 
 |  | ||||||
|                 if (2 == comps.Length) |  | ||||||
|                 { |  | ||||||
|                     // check for {prims} |  | ||||||
|                     switch (comps[1].ToLower()) |  | ||||||
|                     { |  | ||||||
|                         case "prims": |  | ||||||
|                             return LoadPrims(request, httpRequest, httpResponse, scene); |  | ||||||
|                     } |  | ||||||
|                 } |  | ||||||
| 
 |  | ||||||
|                 return Failure(httpResponse, OSHttpStatusCode.ClientErrorNotFound, |  | ||||||
|                                "POST", "url {0} not supported", param); |  | ||||||
|             } |  | ||||||
|             catch (Exception e) |  | ||||||
|             { |  | ||||||
|                 return Failure(httpResponse, OSHttpStatusCode.ServerErrorInternalError, "POST", e); |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         public string CreateRegion(IOSHttpRequest request, IOSHttpResponse response) |  | ||||||
|         { |  | ||||||
|             RestXmlWriter rxw = new RestXmlWriter(new StringWriter()); |  | ||||||
| 
 |  | ||||||
|             rxw.WriteStartElement(String.Empty, "regions", String.Empty); |  | ||||||
|             foreach (Scene s in App.SceneManager.Scenes) |  | ||||||
|             { |  | ||||||
|                 rxw.WriteStartElement(String.Empty, "uuid", String.Empty); |  | ||||||
|                 rxw.WriteString(s.RegionInfo.RegionID.ToString()); |  | ||||||
|                 rxw.WriteEndElement(); |  | ||||||
|             } |  | ||||||
|             rxw.WriteEndElement(); |  | ||||||
| 
 |  | ||||||
|             return rxw.ToString(); |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         public string LoadPrims(string requestBody, IOSHttpRequest request, IOSHttpResponse response, Scene scene) |  | ||||||
|         { |  | ||||||
|             IRegionSerialiserModule serialiser = scene.RequestModuleInterface<IRegionSerialiserModule>(); |  | ||||||
|             if (serialiser != null) |  | ||||||
|                 serialiser.LoadPrimsFromXml2(scene, new StringReader(requestBody), true); |  | ||||||
| 
 |  | ||||||
|             return ""; |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         #endregion POST methods |  | ||||||
|     } |  | ||||||
| } |  | ||||||
|  | @ -1,98 +0,0 @@ | ||||||
| /* |  | ||||||
|  * Copyright (c) Contributors, http://opensimulator.org/ |  | ||||||
|  * See CONTRIBUTORS.TXT for a full list of copyright holders. |  | ||||||
|  * |  | ||||||
|  * Redistribution and use in source and binary forms, with or without |  | ||||||
|  * modification, are permitted provided that the following conditions are met: |  | ||||||
|  *     * Redistributions of source code must retain the above copyright |  | ||||||
|  *       notice, this list of conditions and the following disclaimer. |  | ||||||
|  *     * Redistributions in binary form must reproduce the above copyright |  | ||||||
|  *       notice, this list of conditions and the following disclaimer in the |  | ||||||
|  *       documentation and/or other materials provided with the distribution. |  | ||||||
|  *     * Neither the name of the OpenSimulator Project nor the |  | ||||||
|  *       names of its contributors may be used to endorse or promote products |  | ||||||
|  *       derived from this software without specific prior written permission. |  | ||||||
|  * |  | ||||||
|  * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY |  | ||||||
|  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |  | ||||||
|  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |  | ||||||
|  * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY |  | ||||||
|  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |  | ||||||
|  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |  | ||||||
|  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |  | ||||||
|  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |  | ||||||
|  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |  | ||||||
|  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |  | ||||||
|  */ |  | ||||||
| 
 |  | ||||||
| using System; |  | ||||||
| using System.Xml.Serialization; |  | ||||||
| using OpenMetaverse; |  | ||||||
| using OpenSim.Framework; |  | ||||||
| 
 |  | ||||||
| namespace OpenSim.ApplicationPlugins.Rest.Regions |  | ||||||
| { |  | ||||||
|     [XmlRoot(ElementName="region", IsNullable = false)] |  | ||||||
|     public class RegionDetails |  | ||||||
|     { |  | ||||||
|         public string region_name; |  | ||||||
|         public string region_id; |  | ||||||
|         public uint region_x; |  | ||||||
|         public uint region_y; |  | ||||||
|         public string region_owner; |  | ||||||
|         public string region_owner_id; |  | ||||||
|         public uint region_http_port; |  | ||||||
|         public uint region_port; |  | ||||||
|         public string region_server_uri; |  | ||||||
|         public string region_external_hostname; |  | ||||||
| 
 |  | ||||||
|         public RegionDetails() |  | ||||||
|         { |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         public RegionDetails(RegionInfo regInfo) |  | ||||||
|         { |  | ||||||
|             region_name = regInfo.RegionName; |  | ||||||
|             region_id = regInfo.RegionID.ToString(); |  | ||||||
|             region_x = regInfo.RegionLocX; |  | ||||||
|             region_y = regInfo.RegionLocY; |  | ||||||
|             region_owner_id = regInfo.EstateSettings.EstateOwner.ToString(); |  | ||||||
|             region_http_port = regInfo.HttpPort; |  | ||||||
|             region_server_uri = regInfo.ServerURI; |  | ||||||
|             region_external_hostname = regInfo.ExternalHostName; |  | ||||||
| 
 |  | ||||||
|             Uri uri = new Uri(region_server_uri); |  | ||||||
|             region_port = (uint)uri.Port; |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         public string this[string idx] |  | ||||||
|         { |  | ||||||
|             get |  | ||||||
|             { |  | ||||||
|                 switch (idx.ToLower()) |  | ||||||
|                 { |  | ||||||
|                 case "name": |  | ||||||
|                     return region_name; |  | ||||||
|                 case "id": |  | ||||||
|                     return region_id; |  | ||||||
|                 case "location": |  | ||||||
|                     return String.Format("<x>{0}</x><y>{1}</y>", region_x, region_y); |  | ||||||
|                 case "owner": |  | ||||||
|                     return region_owner; |  | ||||||
|                 case "owner_id": |  | ||||||
|                     return region_owner_id; |  | ||||||
|                 case "http_port": |  | ||||||
|                     return region_http_port.ToString(); |  | ||||||
|                 case "server_uri": |  | ||||||
|                     return region_server_uri; |  | ||||||
|                 case "external_hostname": |  | ||||||
|                 case "hostname": |  | ||||||
|                     return region_external_hostname; |  | ||||||
| 
 |  | ||||||
|                 default: |  | ||||||
|                     return null; |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| } |  | ||||||
|  | @ -1,11 +0,0 @@ | ||||||
| <Addin id="OpenSim.ApplicationPlugins.Rest.Regions" version="0.1"> |  | ||||||
|     <Runtime> |  | ||||||
|         <Import assembly="OpenSim.ApplicationPlugins.Rest.Regions.dll"/> |  | ||||||
|     </Runtime> |  | ||||||
|     <Dependencies> |  | ||||||
|         <Addin id="OpenSim" version="0.5" /> |  | ||||||
|     </Dependencies> |  | ||||||
|     <Extension path = "/OpenSim/Startup"> |  | ||||||
|         <Plugin id="RestRegions" type="OpenSim.ApplicationPlugins.Rest.Regions.RestRegionPlugin" /> |  | ||||||
|     </Extension> |  | ||||||
| </Addin> |  | ||||||
|  | @ -1,94 +0,0 @@ | ||||||
| /* |  | ||||||
|  * Copyright (c) Contributors, http://opensimulator.org/ |  | ||||||
|  * See CONTRIBUTORS.TXT for a full list of copyright holders. |  | ||||||
|  * |  | ||||||
|  * Redistribution and use in source and binary forms, with or without |  | ||||||
|  * modification, are permitted provided that the following conditions are met: |  | ||||||
|  *     * Redistributions of source code must retain the above copyright |  | ||||||
|  *       notice, this list of conditions and the following disclaimer. |  | ||||||
|  *     * Redistributions in binary form must reproduce the above copyright |  | ||||||
|  *       notice, this list of conditions and the following disclaimer in the |  | ||||||
|  *       documentation and/or other materials provided with the distribution. |  | ||||||
|  *     * Neither the name of the OpenSimulator Project nor the |  | ||||||
|  *       names of its contributors may be used to endorse or promote products |  | ||||||
|  *       derived from this software without specific prior written permission. |  | ||||||
|  * |  | ||||||
|  * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY |  | ||||||
|  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |  | ||||||
|  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |  | ||||||
|  * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY |  | ||||||
|  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |  | ||||||
|  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |  | ||||||
|  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |  | ||||||
|  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |  | ||||||
|  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |  | ||||||
|  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |  | ||||||
|  */ |  | ||||||
| 
 |  | ||||||
| using System; |  | ||||||
| using System.Xml.Serialization; |  | ||||||
| 
 |  | ||||||
| namespace OpenSim.ApplicationPlugins.Rest.Regions |  | ||||||
| { |  | ||||||
|     public partial class RestRegionPlugin : RestPlugin |  | ||||||
|     { |  | ||||||
|         private static XmlSerializerNamespaces _xmlNs; |  | ||||||
| 
 |  | ||||||
|         static RestRegionPlugin() |  | ||||||
|         { |  | ||||||
|             _xmlNs = new XmlSerializerNamespaces(); |  | ||||||
|             _xmlNs.Add(String.Empty, String.Empty); |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         #region overriding properties |  | ||||||
|         public override string Name |  | ||||||
|         { |  | ||||||
|             get { return "REGION"; } |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         public override string ConfigName |  | ||||||
|         { |  | ||||||
|             get { return "RestRegionPlugin"; } |  | ||||||
|         } |  | ||||||
|         #endregion overriding properties |  | ||||||
| 
 |  | ||||||
|         #region overriding methods |  | ||||||
|         /// <summary> |  | ||||||
|         /// This method is called by OpenSimMain immediately after loading the |  | ||||||
|         /// plugin and after basic server setup,  but before running any server commands. |  | ||||||
|         /// </summary> |  | ||||||
|         /// <remarks> |  | ||||||
|         /// Note that entries MUST be added to the active configuration files before |  | ||||||
|         /// the plugin can be enabled. |  | ||||||
|         /// </remarks> |  | ||||||
|         public override void Initialise(OpenSimBase openSim) |  | ||||||
|         { |  | ||||||
|             try |  | ||||||
|             { |  | ||||||
|                 base.Initialise(openSim); |  | ||||||
|                 if (!IsEnabled) |  | ||||||
|                 { |  | ||||||
|                     //m_log.WarnFormat("{0} Rest Plugins are disabled", MsgID); |  | ||||||
|                     return; |  | ||||||
|                 } |  | ||||||
|                  |  | ||||||
|                 m_log.InfoFormat("{0} REST region plugin enabled", MsgID); |  | ||||||
| 
 |  | ||||||
|                 // add REST method handlers |  | ||||||
|                 AddRestStreamHandler("GET", "/regions/", GetHandler); |  | ||||||
|                 AddRestStreamHandler("POST", "/regions/", PostHandler); |  | ||||||
|                 AddRestStreamHandler("GET", "/regioninfo/", GetRegionInfoHandler); |  | ||||||
|             } |  | ||||||
|             catch (Exception e) |  | ||||||
|             { |  | ||||||
|                 m_log.WarnFormat("{0} Initialization failed: {1}", MsgID, e.Message); |  | ||||||
|                 m_log.DebugFormat("{0} Initialization failed: {1}", MsgID, e.ToString()); |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         public override void Close() |  | ||||||
|         { |  | ||||||
|         } |  | ||||||
|         #endregion overriding methods |  | ||||||
|     } |  | ||||||
| } |  | ||||||
|  | @ -1,417 +0,0 @@ | ||||||
| /* |  | ||||||
|  * Copyright (c) Contributors, http://opensimulator.org/ |  | ||||||
|  * See CONTRIBUTORS.TXT for a full list of copyright holders. |  | ||||||
|  * |  | ||||||
|  * Redistribution and use in source and binary forms, with or without |  | ||||||
|  * modification, are permitted provided that the following conditions are met: |  | ||||||
|  *     * Redistributions of source code must retain the above copyright |  | ||||||
|  *       notice, this list of conditions and the following disclaimer. |  | ||||||
|  *     * Redistributions in binary form must reproduce the above copyright |  | ||||||
|  *       notice, this list of conditions and the following disclaimer in the |  | ||||||
|  *       documentation and/or other materials provided with the distribution. |  | ||||||
|  *     * Neither the name of the OpenSimulator Project nor the |  | ||||||
|  *       names of its contributors may be used to endorse or promote products |  | ||||||
|  *       derived from this software without specific prior written permission. |  | ||||||
|  * |  | ||||||
|  * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY |  | ||||||
|  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |  | ||||||
|  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |  | ||||||
|  * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY |  | ||||||
|  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |  | ||||||
|  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |  | ||||||
|  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |  | ||||||
|  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |  | ||||||
|  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |  | ||||||
|  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |  | ||||||
|  */ |  | ||||||
| 
 |  | ||||||
| using System; |  | ||||||
| using System.Collections.Generic; |  | ||||||
| using System.IO; |  | ||||||
| using System.Reflection; |  | ||||||
| using System.Xml; |  | ||||||
| using log4net; |  | ||||||
| using Nini.Config; |  | ||||||
| using OpenMetaverse; |  | ||||||
| using OpenSim.Framework; |  | ||||||
| using OpenSim.Framework.Servers; |  | ||||||
| using OpenSim.Framework.Servers.HttpServer; |  | ||||||
| 
 |  | ||||||
| namespace OpenSim.ApplicationPlugins.Rest |  | ||||||
| { |  | ||||||
|     public abstract class RestPlugin : IApplicationPlugin |  | ||||||
|     { |  | ||||||
|         #region properties |  | ||||||
| 
 |  | ||||||
|         protected static readonly ILog m_log = |  | ||||||
|             LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); |  | ||||||
| 
 |  | ||||||
|         private IConfig _config; // Configuration source: Rest Plugins |  | ||||||
|         private IConfig _pluginConfig; // Configuration source: Plugin specific |  | ||||||
|         private OpenSimBase _app; // The 'server' |  | ||||||
|         private BaseHttpServer _httpd; // The server's RPC interface |  | ||||||
|         private string _prefix; // URL prefix below |  | ||||||
|         // which all REST URLs |  | ||||||
|         // are living |  | ||||||
|         // private StringWriter _sw = null; |  | ||||||
|         // private RestXmlWriter _xw = null; |  | ||||||
| 
 |  | ||||||
|         private string _godkey; |  | ||||||
|         private int _reqk; |  | ||||||
| 
 |  | ||||||
|         [ThreadStatic] |  | ||||||
|         private static string  _threadRequestID = String.Empty; |  | ||||||
| 
 |  | ||||||
|         /// <summary> |  | ||||||
|         /// Return an ever increasing request ID for logging |  | ||||||
|         /// </summary> |  | ||||||
|         protected string RequestID |  | ||||||
|         { |  | ||||||
|             get { return _reqk++.ToString(); } |  | ||||||
|             set { _reqk = Convert.ToInt32(value); } |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         /// <summary> |  | ||||||
|         /// Thread-constant message IDs for logging. |  | ||||||
|         /// </summary> |  | ||||||
|         protected string MsgID |  | ||||||
|         { |  | ||||||
|             get { return String.Format("[REST-{0}] #{1}", Name, _threadRequestID); } |  | ||||||
|             set { _threadRequestID = value; } |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         /// <summary> |  | ||||||
|         /// Returns true if Rest Plugins are enabled. |  | ||||||
|         /// </summary> |  | ||||||
|         public bool PluginsAreEnabled |  | ||||||
|         { |  | ||||||
|             get { return null != _config; } |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         /// <summary> |  | ||||||
|         /// Returns true if specific Rest Plugin is enabled. |  | ||||||
|         /// </summary> |  | ||||||
|         public bool IsEnabled |  | ||||||
|         { |  | ||||||
|             get |  | ||||||
|             { |  | ||||||
|                 return (null != _pluginConfig) && _pluginConfig.GetBoolean("enabled", false); |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         /// <summary> |  | ||||||
|         /// OpenSimMain application |  | ||||||
|         /// </summary> |  | ||||||
|         public OpenSimBase App |  | ||||||
|         { |  | ||||||
|             get { return _app; } |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         /// <summary> |  | ||||||
|         /// RPC server |  | ||||||
|         /// </summary> |  | ||||||
|         public BaseHttpServer HttpServer |  | ||||||
|         { |  | ||||||
|             get { return _httpd; } |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         /// <summary> |  | ||||||
|         /// URL prefix to use for all REST handlers |  | ||||||
|         /// </summary> |  | ||||||
|         public string Prefix |  | ||||||
|         { |  | ||||||
|             get { return _prefix; } |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         /// <summary> |  | ||||||
|         /// Access to GOD password string |  | ||||||
|         /// </summary> |  | ||||||
|         protected string GodKey |  | ||||||
|         { |  | ||||||
|             get { return _godkey; } |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         /// <summary> |  | ||||||
|         /// Configuration of the plugin |  | ||||||
|         /// </summary> |  | ||||||
|         public IConfig Config |  | ||||||
|         { |  | ||||||
|             get { return _pluginConfig; } |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         /// <summary> |  | ||||||
|         /// Name of the plugin |  | ||||||
|         /// </summary> |  | ||||||
|         public abstract string Name { get; } |  | ||||||
| 
 |  | ||||||
|         /// <summary> |  | ||||||
|         /// Return the config section name |  | ||||||
|         /// </summary> |  | ||||||
|         public abstract string ConfigName { get; } |  | ||||||
| 
 |  | ||||||
|         // public XmlTextWriter XmlWriter |  | ||||||
|         // { |  | ||||||
|         //     get |  | ||||||
|         //     { |  | ||||||
|         //         if (null == _xw) |  | ||||||
|         //         { |  | ||||||
|         //             _sw = new StringWriter(); |  | ||||||
|         //             _xw = new RestXmlWriter(_sw); |  | ||||||
|         //             _xw.Formatting = Formatting.Indented; |  | ||||||
|         //         } |  | ||||||
|         //         return _xw; |  | ||||||
|         //     } |  | ||||||
|         // } |  | ||||||
| 
 |  | ||||||
|         // public string XmlWriterResult |  | ||||||
|         // { |  | ||||||
|         //     get |  | ||||||
|         //     { |  | ||||||
|         //         _xw.Flush(); |  | ||||||
|         //         _xw.Close(); |  | ||||||
|         //         _xw = null; |  | ||||||
| 
 |  | ||||||
|         //         return _sw.ToString(); |  | ||||||
|         //     } |  | ||||||
|         // } |  | ||||||
| 
 |  | ||||||
|         #endregion properties |  | ||||||
| 
 |  | ||||||
|         #region methods |  | ||||||
| 
 |  | ||||||
|         // TODO: required by IPlugin, but likely not at all right |  | ||||||
|         private string m_version = "0.0"; |  | ||||||
| 
 |  | ||||||
|         public string Version |  | ||||||
|         { |  | ||||||
|             get { return m_version; } |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         public void Initialise() |  | ||||||
|         { |  | ||||||
|             m_log.Info("[RESTPLUGIN]: " + Name + " cannot be default-initialized!"); |  | ||||||
|             throw new PluginNotInitialisedException(Name); |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         /// <summary> |  | ||||||
|         /// This method is called by OpenSimMain immediately after loading the |  | ||||||
|         /// plugin and after basic server setup,  but before running any server commands. |  | ||||||
|         /// </summary> |  | ||||||
|         /// <remarks> |  | ||||||
|         /// Note that entries MUST be added to the active configuration files before |  | ||||||
|         /// the plugin can be enabled. |  | ||||||
|         /// </remarks> |  | ||||||
|         public virtual void Initialise(OpenSimBase openSim) |  | ||||||
|         { |  | ||||||
|             RequestID = "0"; |  | ||||||
|             MsgID = RequestID; |  | ||||||
| 
 |  | ||||||
|             try |  | ||||||
|             { |  | ||||||
|                 if ((_config = openSim.ConfigSource.Source.Configs["RestPlugins"]) == null) |  | ||||||
|                 { |  | ||||||
|                     m_log.WarnFormat("{0} Rest Plugins not configured", MsgID); |  | ||||||
|                     return; |  | ||||||
|                 } |  | ||||||
| 
 |  | ||||||
|                 if (!_config.GetBoolean("enabled", false)) |  | ||||||
|                 { |  | ||||||
|                     //m_log.WarnFormat("{0} Rest Plugins are disabled", MsgID); |  | ||||||
|                     return; |  | ||||||
|                 } |  | ||||||
| 
 |  | ||||||
|                 _app = openSim; |  | ||||||
|                 _httpd = openSim.HttpServer; |  | ||||||
| 
 |  | ||||||
|                 // Retrieve GOD key value, if any. |  | ||||||
|                 _godkey = _config.GetString("god_key", String.Empty); |  | ||||||
| 
 |  | ||||||
|                 // Retrive prefix if any. |  | ||||||
|                 _prefix = _config.GetString("prefix", "/admin"); |  | ||||||
| 
 |  | ||||||
|                 // Get plugin specific config |  | ||||||
|                 _pluginConfig = openSim.ConfigSource.Source.Configs[ConfigName]; |  | ||||||
| 
 |  | ||||||
|                 m_log.InfoFormat("{0} Rest Plugins Enabled", MsgID); |  | ||||||
|             } |  | ||||||
|             catch (Exception e) |  | ||||||
|             { |  | ||||||
|                 // we can safely ignore this, as it just means that |  | ||||||
|                 // the key lookup in Configs failed, which signals to |  | ||||||
|                 // us that noone is interested in our services...they |  | ||||||
|                 // don't know what they are missing out on... |  | ||||||
|                 // NOTE: Under the present OpenSimulator implementation it is |  | ||||||
|                 // not possible for the openSimulator pointer to be null. However |  | ||||||
|                 // were the implementation to be changed, this could |  | ||||||
|                 // result in a silent initialization failure. Harmless |  | ||||||
|                 // except for lack of function and lack of any |  | ||||||
|                 // diagnostic indication as to why. The same is true if |  | ||||||
|                 // the HTTP server reference is bad. |  | ||||||
|                 // We should at least issue a message... |  | ||||||
|                 m_log.WarnFormat("{0} Initialization failed: {1}", MsgID, e.Message); |  | ||||||
|                 m_log.DebugFormat("{0} Initialization failed: {1}", MsgID, e.ToString()); |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         public virtual void PostInitialise() |  | ||||||
|         { |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         private List<RestStreamHandler> _handlers = new List<RestStreamHandler>(); |  | ||||||
|         private Dictionary<string, IHttpAgentHandler> _agents = new Dictionary<string, IHttpAgentHandler>(); |  | ||||||
| 
 |  | ||||||
|         /// <summary> |  | ||||||
|         /// Add a REST stream handler to the underlying HTTP server. |  | ||||||
|         /// </summary> |  | ||||||
|         /// <param name="httpMethod">GET/PUT/POST/DELETE or |  | ||||||
|         /// similar</param> |  | ||||||
|         /// <param name="path">URL prefix</param> |  | ||||||
|         /// <param name="method">RestMethod handler doing the actual work</param> |  | ||||||
|         public virtual void AddRestStreamHandler(string httpMethod, string path, RestMethod method) |  | ||||||
|         { |  | ||||||
|             if (!IsEnabled) return; |  | ||||||
| 
 |  | ||||||
|             if (!path.StartsWith(_prefix)) |  | ||||||
|             { |  | ||||||
|                 path = String.Format("{0}{1}", _prefix, path); |  | ||||||
|             } |  | ||||||
| 
 |  | ||||||
|             RestStreamHandler h = new RestStreamHandler(httpMethod, path, method); |  | ||||||
|             _httpd.AddStreamHandler(h); |  | ||||||
|             _handlers.Add(h); |  | ||||||
| 
 |  | ||||||
|             m_log.DebugFormat("{0} Added REST handler {1} {2}", MsgID, httpMethod, path); |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         /// <summary> |  | ||||||
|         /// Add a powerful Agent handler to the underlying HTTP |  | ||||||
|         /// server. |  | ||||||
|         /// </summary> |  | ||||||
|         /// <param name="agentName">name of agent handler</param> |  | ||||||
|         /// <param name="handler">agent handler method</param> |  | ||||||
|         /// <returns>false when the plugin is disabled or the agent |  | ||||||
|         /// handler could not be added. Any generated exceptions are |  | ||||||
|         /// allowed to drop through to the caller, i.e. ArgumentException. |  | ||||||
|         /// </returns> |  | ||||||
|         public bool AddAgentHandler(string agentName, IHttpAgentHandler handler) |  | ||||||
|         { |  | ||||||
|             if (!IsEnabled) return false; |  | ||||||
|             _agents.Add(agentName, handler); |  | ||||||
| //            return _httpd.AddAgentHandler(agentName, handler); |  | ||||||
|              |  | ||||||
|             return false; |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         /// <summary> |  | ||||||
|         /// Remove a powerful Agent handler from the underlying HTTP |  | ||||||
|         /// server. |  | ||||||
|         /// </summary> |  | ||||||
|         /// <param name="agentName">name of agent handler</param> |  | ||||||
|         /// <param name="handler">agent handler method</param> |  | ||||||
|         /// <returns>false when the plugin is disabled or the agent |  | ||||||
|         /// handler could not be removed. Any generated exceptions are |  | ||||||
|         /// allowed to drop through to the caller, i.e. KeyNotFound. |  | ||||||
|         /// </returns> |  | ||||||
|         public bool RemoveAgentHandler(string agentName, IHttpAgentHandler handler) |  | ||||||
|         { |  | ||||||
|             if (!IsEnabled) return false; |  | ||||||
|             if (_agents[agentName] == handler) |  | ||||||
|             { |  | ||||||
|                 _agents.Remove(agentName); |  | ||||||
| //                return _httpd.RemoveAgentHandler(agentName, handler); |  | ||||||
|             } |  | ||||||
|             return false; |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         /// <summary> |  | ||||||
|         /// Check whether the HTTP request came from god; that is, is |  | ||||||
|         /// the god_key as configured in the config section supplied |  | ||||||
|         /// via X-OpenSim-Godkey? |  | ||||||
|         /// </summary> |  | ||||||
|         /// <param name="request">HTTP request header</param> |  | ||||||
|         /// <returns>true when the HTTP request came from god.</returns> |  | ||||||
|         protected bool IsGod(IOSHttpRequest request) |  | ||||||
|         { |  | ||||||
|             string[] keys = request.Headers.GetValues("X-OpenSim-Godkey"); |  | ||||||
|             if (null == keys) return false; |  | ||||||
| 
 |  | ||||||
|             // we take the last key supplied |  | ||||||
|             return keys[keys.Length - 1] == _godkey; |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         /// <summary> |  | ||||||
|         /// Checks wether the X-OpenSim-Password value provided in the |  | ||||||
|         /// HTTP header is indeed the password on file for the avatar |  | ||||||
|         /// specified by the UUID |  | ||||||
|         /// </summary> |  | ||||||
|         protected bool IsVerifiedUser(IOSHttpRequest request, UUID uuid) |  | ||||||
|         { |  | ||||||
|             // XXX under construction |  | ||||||
|             return false; |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         /// <summary> |  | ||||||
|         /// Clean up and remove all handlers that were added earlier. |  | ||||||
|         /// </summary> |  | ||||||
|         public virtual void Close() |  | ||||||
|         { |  | ||||||
|             foreach (RestStreamHandler h in _handlers) |  | ||||||
|             { |  | ||||||
|                 _httpd.RemoveStreamHandler(h.HttpMethod, h.Path); |  | ||||||
|             } |  | ||||||
|             _handlers = null; |  | ||||||
| //            foreach (KeyValuePair<string, IHttpAgentHandler> h in _agents) |  | ||||||
| //            { |  | ||||||
| //                _httpd.RemoveAgentHandler(h.Key, h.Value); |  | ||||||
| //            } |  | ||||||
|             _agents = null; |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         public virtual void Dispose() |  | ||||||
|         { |  | ||||||
|             Close(); |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         /// <summary> |  | ||||||
|         /// Return a failure message. |  | ||||||
|         /// </summary> |  | ||||||
|         /// <param name="method">origin of the failure message</param> |  | ||||||
|         /// <param name="message">failure message</param> |  | ||||||
|         /// <remarks>This should probably set a return code as |  | ||||||
|         /// well. (?)</remarks> |  | ||||||
|         protected string Failure(IOSHttpResponse response, OSHttpStatusCode status, |  | ||||||
|                                  string method, string format, params string[] msg) |  | ||||||
|         { |  | ||||||
|             string m = String.Format(format, msg); |  | ||||||
| 
 |  | ||||||
|             response.StatusCode = (int) status; |  | ||||||
|             response.StatusDescription = m; |  | ||||||
| 
 |  | ||||||
|             m_log.ErrorFormat("{0} {1} failed: {2}", MsgID, method, m); |  | ||||||
|             return String.Format("<error>{0}</error>", m); |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         /// <summary> |  | ||||||
|         /// Return a failure message. |  | ||||||
|         /// </summary> |  | ||||||
|         /// <param name="method">origin of the failure message</param> |  | ||||||
|         /// <param name="e">exception causing the failure message</param> |  | ||||||
|         /// <remarks>This should probably set a return code as |  | ||||||
|         /// well. (?)</remarks> |  | ||||||
|         public string Failure(IOSHttpResponse response, OSHttpStatusCode status, |  | ||||||
|                               string method, Exception e) |  | ||||||
|         { |  | ||||||
|             string m = String.Format("exception occurred: {0}", e.Message); |  | ||||||
| 
 |  | ||||||
|             response.StatusCode = (int) status; |  | ||||||
|             response.StatusDescription = m; |  | ||||||
| 
 |  | ||||||
|             m_log.DebugFormat("{0} {1} failed: {2}", MsgID, method, e.ToString()); |  | ||||||
|             m_log.ErrorFormat("{0} {1} failed: {2}", MsgID, method, e.Message); |  | ||||||
| 
 |  | ||||||
|             return String.Format("<error>{0}</error>", e.Message); |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         #endregion methods |  | ||||||
|     } |  | ||||||
| } |  | ||||||
|  | @ -1,72 +0,0 @@ | ||||||
| /* |  | ||||||
|  * Copyright (c) Contributors, http://opensimulator.org/ |  | ||||||
|  * See CONTRIBUTORS.TXT for a full list of copyright holders. |  | ||||||
|  * |  | ||||||
|  * Redistribution and use in source and binary forms, with or without |  | ||||||
|  * modification, are permitted provided that the following conditions are met: |  | ||||||
|  *     * Redistributions of source code must retain the above copyright |  | ||||||
|  *       notice, this list of conditions and the following disclaimer. |  | ||||||
|  *     * Redistributions in binary form must reproduce the above copyright |  | ||||||
|  *       notice, this list of conditions and the following disclaimer in the |  | ||||||
|  *       documentation and/or other materials provided with the distribution. |  | ||||||
|  *     * Neither the name of the OpenSimulator Project nor the |  | ||||||
|  *       names of its contributors may be used to endorse or promote products |  | ||||||
|  *       derived from this software without specific prior written permission. |  | ||||||
|  * |  | ||||||
|  * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY |  | ||||||
|  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |  | ||||||
|  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |  | ||||||
|  * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY |  | ||||||
|  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |  | ||||||
|  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |  | ||||||
|  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |  | ||||||
|  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |  | ||||||
|  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |  | ||||||
|  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |  | ||||||
|  */ |  | ||||||
| 
 |  | ||||||
| using System.IO; |  | ||||||
| using System.Text; |  | ||||||
| using System.Xml; |  | ||||||
| 
 |  | ||||||
| namespace OpenSim.ApplicationPlugins.Rest |  | ||||||
| { |  | ||||||
|     public class RestXmlWriter: XmlTextWriter |  | ||||||
|     { |  | ||||||
|         private StringWriter m_sw = null; |  | ||||||
| 
 |  | ||||||
|         public RestXmlWriter(StringWriter sw) : base(sw) |  | ||||||
|         { |  | ||||||
|             m_sw = sw; |  | ||||||
|             Formatting = Formatting.Indented; |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         public RestXmlWriter(TextWriter textWriter) : base(textWriter) |  | ||||||
|         { |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         public RestXmlWriter(Stream stream) |  | ||||||
|             : this(stream, Encoding.UTF8) |  | ||||||
|         { |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         public RestXmlWriter(Stream stream, Encoding enc) : base(stream, enc) |  | ||||||
|         { |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         public override void WriteStartDocument() |  | ||||||
|         { |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         public override void WriteStartDocument(bool standalone) |  | ||||||
|         { |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         public override string ToString() |  | ||||||
|         { |  | ||||||
|             Flush(); |  | ||||||
|             Close(); |  | ||||||
|             return m_sw.ToString(); |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| } |  | ||||||
|  | @ -1,276 +0,0 @@ | ||||||
| <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"> |  | ||||||
| 
 |  | ||||||
| 	<xsd:annotation> |  | ||||||
| 		<xsd:documentation xml:lang="en"> |  | ||||||
| 		Open Simulator Export/Import XML schema |  | ||||||
| 		August 2008 |  | ||||||
| 		</xsd:documentation> |  | ||||||
| 	</xsd:annotation> |  | ||||||
| 
 |  | ||||||
|     <!-- WARNING!!! |  | ||||||
| 		 This is currently a draft, it does not reflect |  | ||||||
| 		 what is exported, nor what will be understood |  | ||||||
| 		 on import. It is included as a working document |  | ||||||
| 		 and this comment will be removed at such time as |  | ||||||
| 		 the schema corresponds to reality. |  | ||||||
| 	 --> |  | ||||||
| 
 |  | ||||||
| 	<!-- |  | ||||||
| 		REST-related information |  | ||||||
| 		Inventory data is always framed by an  |  | ||||||
| 		inventory element. Consists of zero or |  | ||||||
| 		more elements representing either folders |  | ||||||
| 		or items within those folders. The inventory |  | ||||||
| 		element represents the "real" root folder. |  | ||||||
| 	 --> |  | ||||||
| 
 |  | ||||||
| 	<xsd:element name="inventory" type="inventory_ct" /> |  | ||||||
| 
 |  | ||||||
|     <!-- |  | ||||||
|          The inventory complex type is just an arbitrary |  | ||||||
|          sequence of folders and items. In reality it is |  | ||||||
|          typically just folders. Both item and folder  |  | ||||||
|          have corresponding complex types. It is distinct |  | ||||||
|          from folders insofar as it has no other defining |  | ||||||
|          attributes. |  | ||||||
|      --> |  | ||||||
| 
 |  | ||||||
| 	<xsd:complexType name="inventory_ct"> |  | ||||||
| 		<xsd:element name="folder" type="folder_ct" maxOccurs="unbounded"/> |  | ||||||
| 		<xsd:element name="item"   type="item_ct" maxOccurs="unbounded" /> |  | ||||||
| 	</xsd:complexType> |  | ||||||
|   |  | ||||||
| 	<xsd:complexType name="folder_ct"> |  | ||||||
| 		<xsd:attribute name="UUID"         type="uuid_st" /> |  | ||||||
| 		<xsd:attribute name="name"         type="name_st" /> |  | ||||||
| 		<xsd:attribute name="type"         type="folder_type_st" /> |  | ||||||
| 		<xsd:attribute name="description"  type="xsd:string" />	<!-- added --> |  | ||||||
| 		<xsd:attribute name="version" 	   type="unsignedShort" /> |  | ||||||
| 		<xsd:attribute name="owner"        type="uuid_st" /> |  | ||||||
| 
 |  | ||||||
| 		<xsd:attribute name="creator" 	   type="uuid_st" /> <!-- added --> |  | ||||||
| 		<xsd:attribute name="creationdate" type="date_st" /> <!-- added --> |  | ||||||
| 
 |  | ||||||
| 		<xsd:attribute name="parent"  	   type="uuid_st" /> |  | ||||||
| 
 |  | ||||||
| 		<xsd:element   name="permissions"  type="permissions_ct" maxOccurs="unbounded" />	<!-- added --> |  | ||||||
| 		<xsd:element   name="folder"       type="folder_ct"      maxOccurs="unbounded" /> |  | ||||||
| 		<xsd:element   name="item"         type="item_ct"        maxOccurs="unbounded" /> |  | ||||||
| 	</xsd:complexType> |  | ||||||
| 
 |  | ||||||
| 	<xsd:complexType name="item_ct"> |  | ||||||
| 		<xsd:attribute name="UUID"         type="uuid_st" /> |  | ||||||
| 		<xsd:attribute name="name"         type="name_st" /> |  | ||||||
| 		<xsd:attribute name="type"         type="inventory_type_st" /> |  | ||||||
| 		<xsd:attribute name="description"  type="xsd:string" /> |  | ||||||
| 		<xsd:attribute name="version" 	   type="unsignedShort" />	<!-- added --> |  | ||||||
| 		<xsd:attribute name="owner"        type="uuid_st" /> |  | ||||||
| 
 |  | ||||||
| 		<xsd:attribute name="creator" 	   type="uuid_st" /> |  | ||||||
| 		<xsd:attribute name="creationdate" type="date_st" /> |  | ||||||
| 
 |  | ||||||
| 		<xsd:attribute name="folder"  	   type="uuid_st" /> |  | ||||||
| 		<xsd:attribute name="groupid" 	   type="uuid_st" /> |  | ||||||
| 		<xsd:attribute name="groupowned"   type="xsd:boolean" /> |  | ||||||
| 		<xsd:attribute name="saletype"     type="sale_st" /> |  | ||||||
| 		<xsd:attribute name="saleprice"    type="xsd:decimal" /> |  | ||||||
| 
 |  | ||||||
| 		<xsd:element   name="permissions"  type="permissions_ct" maxOccurs="unbounded" /> |  | ||||||
| 	</xsd:complexType> |  | ||||||
| 
 |  | ||||||
| 	<xsd:complexType name="asset_ct"> |  | ||||||
| 		<xsd:attribute name="UUID"         type="uuid_st" /> |  | ||||||
| 		<xsd:attribute name="name"         type="name_st" /> |  | ||||||
| 		<xsd:attribute name="type"         type="asset_type_st" /> |  | ||||||
| 		<xsd:attribute name="description"  type="xsd:string" /> |  | ||||||
| 		<xsd:attribute name="version" 	   type="unsignedShort" />	<!-- added --> |  | ||||||
| 		<xsd:attribute name="owner"        type="uuid_st" /> |  | ||||||
| 
 |  | ||||||
| 		<xsd:attribute name="creator" 	   type="uuid_st" /> |  | ||||||
| 		<xsd:attribute name="creationdate" type="date_st" /> |  | ||||||
| 
 |  | ||||||
| 		<xsd:attribute name="temporary"    type="xsd:boolean" /> |  | ||||||
| 		<xsd:attribute name="local"        type="xsd:boolean" /> |  | ||||||
| 		<xsd:attribute name="inline"       type="xsd:boolean" /> |  | ||||||
| 	</xsd:complexType> |  | ||||||
| 
 |  | ||||||
| 	<!-- Constrained Simple Data types --> |  | ||||||
| 
 |  | ||||||
|     <!-- |  | ||||||
|          We need to specify name as a simple type because on |  | ||||||
|          some platforms it is constrained by a certain length |  | ||||||
|          limitation. For completeness we indicate that whitespace |  | ||||||
|          should be preserved exactly as specified. |  | ||||||
|      --> |  | ||||||
| 
 |  | ||||||
| 	<xsd:simpleType name="name_st"> |  | ||||||
| 		<xsd:restriction base="xsd:string"> |  | ||||||
| 		    <whiteSpace value="preserve" /> |  | ||||||
|             <minLength value="0" /> |  | ||||||
|             <maxLength value="64" /> |  | ||||||
| 		</xsd:restriction> |  | ||||||
| 	</xsd:simpleType> |  | ||||||
| 
 |  | ||||||
|     <!-- |  | ||||||
|          Type information in the folder is meant to indicate |  | ||||||
|          the preferred asset type for this folder. As such, that |  | ||||||
|          currently corresponds to the type values allowed for |  | ||||||
|          assets, however that is not mandated, so for |  | ||||||
|          now at least I'll represent this as a distinct  |  | ||||||
|          enumeration. |  | ||||||
|          This seems inappropriate; it seems like the folder's |  | ||||||
|          content should reflect the InventoryType classifications |  | ||||||
|          rather than the asset types. |  | ||||||
|      --> |  | ||||||
| 
 |  | ||||||
| 	<xsd:simpleType name="folder_type_st"> |  | ||||||
| 		<xsd:restriction base="xsd:string"> |  | ||||||
| 			<xsd:enumeration value="Texture" /> |  | ||||||
| 			<xsd:enumeration value="Sound" /> |  | ||||||
| 			<xsd:enumeration value="CallingCard" /> |  | ||||||
| 			<xsd:enumeration value="Landmark" /> |  | ||||||
| 			<xsd:enumeration value="Script" /> |  | ||||||
| 			<xsd:enumeration value="Clothing" /> |  | ||||||
| 			<xsd:enumeration value="Object" /> |  | ||||||
| 			<xsd:enumeration value="Notecard" /> |  | ||||||
| 			<xsd:enumeration value="LSLText" /> |  | ||||||
| 			<xsd:enumeration value="LSLByteCode" /> |  | ||||||
| 			<xsd:enumeration value="TextureTGA" /> |  | ||||||
| 			<xsd:enumeration value="BodyPart" /> |  | ||||||
| 			<xsd:enumeration value="SoundWAV" /> |  | ||||||
| 			<xsd:enumeration value="ImageTGA" /> |  | ||||||
| 			<xsd:enumeration value="ImageJPEG" /> |  | ||||||
| 			<xsd:enumeration value="Animation" /> |  | ||||||
| 			<xsd:enumeration value="Gesture" /> |  | ||||||
| 			<xsd:enumeration value="Simstate" /> |  | ||||||
| 			<xsd:enumeration value="Unknown" /> |  | ||||||
| 			<xsd:enumeration value="LostAndFoundFolder" /> |  | ||||||
| 			<xsd:enumeration value="SnapshotFolder" /> |  | ||||||
| 			<xsd:enumeration value="TrashFolder" /> |  | ||||||
| 			<xsd:enumeration value="Folder" /> |  | ||||||
| 			<xsd:enumeration value="RootFolder" /> |  | ||||||
| 		</xsd:restriction> |  | ||||||
| 	</xsd:simpleType> |  | ||||||
| 
 |  | ||||||
|     <!-- |  | ||||||
|          Inventory item type designates an asset class, rather |  | ||||||
|          than a specific asset type. For example, "SnapShot" |  | ||||||
|          might include a number of asset types such as JPEG,  |  | ||||||
|          TGA, etc.. This is not a consistent interpretation, |  | ||||||
|          classifications such as LostAndFound are meta-types |  | ||||||
|          relative to asset classes.  |  | ||||||
| 
 |  | ||||||
|          These types should be abstract and not be tied to a  |  | ||||||
|          specific platform. A world's import facility should be |  | ||||||
|          responsible for mapping these to meaningful internal |  | ||||||
|          representations. |  | ||||||
| 
 |  | ||||||
|          These types were based on information in: |  | ||||||
|              libsecondlife/InventoryManager.cs |  | ||||||
|      --> |  | ||||||
| 
 |  | ||||||
| 	<xsd:simpleType name="inventory_type_st"> |  | ||||||
| 		<xsd:restriction base="xsd:string"> |  | ||||||
| 			<xsd:enumeration value="Texture" /> |  | ||||||
| 			<xsd:enumeration value="Sound" /> |  | ||||||
| 			<xsd:enumeration value="CallingCard" /> |  | ||||||
| 			<xsd:enumeration value="Landmark" /> |  | ||||||
| 			<xsd:enumeration value="Script" /> |  | ||||||
| 			<xsd:enumeration value="Clothing" /> |  | ||||||
| 			<xsd:enumeration value="Object" /> |  | ||||||
| 			<xsd:enumeration value="Notecard" /> |  | ||||||
| 			<xsd:enumeration value="LSL" /> |  | ||||||
| 			<xsd:enumeration value="LSLBytecode" /> |  | ||||||
| 			<xsd:enumeration value="TextureTGA" /> |  | ||||||
| 			<xsd:enumeration value="BodyPart" /> |  | ||||||
| 			<xsd:enumeration value="Snapshot" /> |  | ||||||
| 			<xsd:enumeration value="Attachment" /> |  | ||||||
| 			<xsd:enumeration value="Wearable" /> |  | ||||||
| 			<xsd:enumeration value="Animation" /> |  | ||||||
| 			<xsd:enumeration value="Gesture" /> |  | ||||||
| 			<xsd:enumeration value="Folder" /> |  | ||||||
| 			<xsd:enumeration value="Unknown" /> |  | ||||||
| 			<xsd:enumeration value="LostAndFound" /> |  | ||||||
| 			<xsd:enumeration value="Trash" /> |  | ||||||
| 			<xsd:enumeration value="Root" /> |  | ||||||
| 		</xsd:restriction> |  | ||||||
| 	</xsd:simpleType> |  | ||||||
| 
 |  | ||||||
|     <!-- |  | ||||||
|          The asset types seem to be even more disarrayed than |  | ||||||
|          the inventory types. It seems to be little more than |  | ||||||
|          a reiteration of the inventory type information, |  | ||||||
|          which adds little or nothing to the overall data |  | ||||||
|          model. |  | ||||||
| 
 |  | ||||||
|          Of course, given that these are drawn from the |  | ||||||
|          libsecondlife definitions, we aren't at liberty to |  | ||||||
|          simply redefine them in place. But the XML definitions |  | ||||||
|          here could be made more useful. |  | ||||||
| 
 |  | ||||||
|          These types were based on information in: |  | ||||||
|              libsecondlife/AssetManager.cs |  | ||||||
|      --> |  | ||||||
| 
 |  | ||||||
| 	<xsd:simpleType name="asset_type_st"> |  | ||||||
| 		<xsd:restriction base="xsd:string"> |  | ||||||
| 			<xsd:enumeration value="Texture" /> |  | ||||||
| 			<xsd:enumeration value="Sound" /> |  | ||||||
| 			<xsd:enumeration value="CallingCard" /> |  | ||||||
| 			<xsd:enumeration value="Landmark" /> |  | ||||||
| 			<xsd:enumeration value="Script" /> |  | ||||||
| 			<xsd:enumeration value="Clothing" /> |  | ||||||
| 			<xsd:enumeration value="Object" /> |  | ||||||
| 			<xsd:enumeration value="Notecard" /> |  | ||||||
| 			<xsd:enumeration value="LSLText" /> |  | ||||||
| 			<xsd:enumeration value="LSLByteCode" /> |  | ||||||
| 			<xsd:enumeration value="TextureTGA" /> |  | ||||||
| 			<xsd:enumeration value="BodyPart" /> |  | ||||||
| 			<xsd:enumeration value="SoundWAV" /> |  | ||||||
| 			<xsd:enumeration value="ImageTGA" /> |  | ||||||
| 			<xsd:enumeration value="ImageJPEG" /> |  | ||||||
| 			<xsd:enumeration value="Animation" /> |  | ||||||
| 			<xsd:enumeration value="Gesture" /> |  | ||||||
| 			<xsd:enumeration value="Simstate" /> |  | ||||||
| 			<xsd:enumeration value="Unknown" /> |  | ||||||
| 			<xsd:enumeration value="LostAndFoundFolder" /> |  | ||||||
| 			<xsd:enumeration value="SnapshotFolder" /> |  | ||||||
| 			<xsd:enumeration value="TrashFolder" /> |  | ||||||
| 			<xsd:enumeration value="Folder" /> |  | ||||||
| 			<xsd:enumeration value="RootFolder" /> |  | ||||||
| 		</xsd:restriction> |  | ||||||
| 	</xsd:simpleType> |  | ||||||
| 
 |  | ||||||
|     <!-- This is describing the apparent form of a UUID. If |  | ||||||
|          we ever want a more metaphysical definition we'll  |  | ||||||
|          need to add to it. |  | ||||||
|      --> |  | ||||||
| 
 |  | ||||||
| 	<xsd:simpleType name="uuid_st"> |  | ||||||
| 		<xsd:restriction base="xsd:string"> |  | ||||||
| 		    <xsd:pattern value="[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}"/> |  | ||||||
| 		</xsd:restriction> |  | ||||||
| 	</xsd:simpleType> |  | ||||||
| 
 |  | ||||||
|     <!-- This constrains the date representation. Currently |  | ||||||
|          it is simply an integer representing the elapsed |  | ||||||
| 		 ?? since ??. |  | ||||||
|      --> |  | ||||||
| 
 |  | ||||||
| 	<xsd:simpleType name="date_st"> |  | ||||||
| 		<xsd:restriction base="xsd:positiveInteger"> |  | ||||||
| 		</xsd:restriction> |  | ||||||
| 	</xsd:simpleType> |  | ||||||
| 
 |  | ||||||
|     <!-- This constrains the representation of sale price. |  | ||||||
| 		 Currently it is a simple decimal with no unit |  | ||||||
| 		 specified.  |  | ||||||
|          Issues: interoperability. |  | ||||||
|      --> |  | ||||||
| 
 |  | ||||||
| 	<xsd:simpleType name="sale_st"> |  | ||||||
| 		<xsd:restriction base="xsd:decimal"> |  | ||||||
| 		</xsd:restriction> |  | ||||||
| 	</xsd:simpleType> |  | ||||||
| 
 |  | ||||||
| </xsd:schema> |  | ||||||
|  | @ -487,7 +487,9 @@ namespace OpenSim.Framework.Servers.HttpServer | ||||||
|             { |             { | ||||||
|                 try |                 try | ||||||
|                 { |                 { | ||||||
|                     SendHTML500(response); |                     byte[] buffer500 = SendHTML500(response); | ||||||
|  |                     response.Body.Write(buffer500,0,buffer500.Length); | ||||||
|  |                     response.Body.Close(); | ||||||
|                 } |                 } | ||||||
|                 catch |                 catch | ||||||
|                 { |                 { | ||||||
|  | @ -720,7 +722,15 @@ namespace OpenSim.Framework.Servers.HttpServer | ||||||
|             catch (Exception e) |             catch (Exception e) | ||||||
|             { |             { | ||||||
|                 m_log.Error(String.Format("[BASE HTTP SERVER]: HandleRequest() threw {0} ", e.StackTrace), e); |                 m_log.Error(String.Format("[BASE HTTP SERVER]: HandleRequest() threw {0} ", e.StackTrace), e); | ||||||
|                 SendHTML500(response); |                 try | ||||||
|  |                 { | ||||||
|  |                     byte[] buffer500 = SendHTML500(response); | ||||||
|  |                     response.Body.Write(buffer500, 0, buffer500.Length); | ||||||
|  |                     response.Body.Close(); | ||||||
|  |                 } | ||||||
|  |                 catch | ||||||
|  |                 { | ||||||
|  |                 } | ||||||
|             } |             } | ||||||
|             finally |             finally | ||||||
|             { |             { | ||||||
|  | @ -1792,7 +1802,8 @@ namespace OpenSim.Framework.Servers.HttpServer | ||||||
|             response.SendChunked = false; |             response.SendChunked = false; | ||||||
|             response.ContentLength64 = buffer.Length; |             response.ContentLength64 = buffer.Length; | ||||||
|             response.ContentEncoding = Encoding.UTF8; |             response.ContentEncoding = Encoding.UTF8; | ||||||
| 
 |              | ||||||
|  |                  | ||||||
|             return buffer; |             return buffer; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -143,7 +143,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin | ||||||
|         { |         { | ||||||
|             enableAngularVerticalAttraction = true; |             enableAngularVerticalAttraction = true; | ||||||
|             enableAngularDeflection = false; |             enableAngularDeflection = false; | ||||||
|             enableAngularBanking = false; |             enableAngularBanking = true; | ||||||
|             if (BSParam.VehicleDebuggingEnabled) |             if (BSParam.VehicleDebuggingEnabled) | ||||||
|             { |             { | ||||||
|                 enableAngularVerticalAttraction = true; |                 enableAngularVerticalAttraction = true; | ||||||
|  | @ -1280,11 +1280,11 @@ namespace OpenSim.Region.Physics.BulletSPlugin | ||||||
|             // That is, NO_DEFLECTION_UP says angular motion should not add any pitch or roll movement |             // That is, NO_DEFLECTION_UP says angular motion should not add any pitch or roll movement | ||||||
|             // TODO: This is here because this is where ODE put it but documentation says it |             // TODO: This is here because this is where ODE put it but documentation says it | ||||||
|             //    is a linear effect. Where should this check go? |             //    is a linear effect. Where should this check go? | ||||||
|             if ((m_flags & (VehicleFlag.NO_DEFLECTION_UP)) != 0) |             //if ((m_flags & (VehicleFlag.NO_DEFLECTION_UP)) != 0) | ||||||
|             { |            // { | ||||||
|                 angularMotorContributionV.X = 0f; |             //    angularMotorContributionV.X = 0f; | ||||||
|                 angularMotorContributionV.Y = 0f; |             //    angularMotorContributionV.Y = 0f; | ||||||
|             } |           //  } | ||||||
| 
 | 
 | ||||||
|             VehicleRotationalVelocity += angularMotorContributionV * VehicleOrientation; |             VehicleRotationalVelocity += angularMotorContributionV * VehicleOrientation; | ||||||
|             VDetailLog("{0},  MoveAngular,angularTurning,angularMotorContrib={1}", Prim.LocalID, angularMotorContributionV); |             VDetailLog("{0},  MoveAngular,angularTurning,angularMotorContrib={1}", Prim.LocalID, angularMotorContributionV); | ||||||
|  | @ -1437,24 +1437,25 @@ namespace OpenSim.Region.Physics.BulletSPlugin | ||||||
|                 // As the vehicle rolls to the right or left, the Y value will increase from |                 // As the vehicle rolls to the right or left, the Y value will increase from | ||||||
|                 //     zero (straight up) to 1 or -1 (full tilt right  or left) |                 //     zero (straight up) to 1 or -1 (full tilt right  or left) | ||||||
|                 Vector3 rollComponents = Vector3.UnitZ * VehicleOrientation; |                 Vector3 rollComponents = Vector3.UnitZ * VehicleOrientation; | ||||||
|                  |  | ||||||
|                 // Figure out the yaw value for this much roll. |  | ||||||
|                 // Squared because that seems to give a good value |  | ||||||
|                 float yawAngle = (float)Math.Asin(rollComponents.Y * rollComponents.Y) * m_bankingEfficiency; |  | ||||||
| 
 | 
 | ||||||
|  |                 // Figure out the yaw value for this much roll. | ||||||
|  |                 float yawAngle = m_angularMotorDirection.X * m_bankingEfficiency; | ||||||
|                 //        actual error  =       static turn error            +           dynamic turn error |                 //        actual error  =       static turn error            +           dynamic turn error | ||||||
|                 float mixedYawAngle = yawAngle * (1f - m_bankingMix) + yawAngle * m_bankingMix * VehicleForwardSpeed; |                 float mixedYawAngle =(yawAngle * (1f - m_bankingMix)) + ((yawAngle * m_bankingMix) * VehicleForwardSpeed); | ||||||
| 
 | 
 | ||||||
|                 // TODO: the banking effect should not go to infinity but what to limit it to? |                 // TODO: the banking effect should not go to infinity but what to limit it to? | ||||||
|                 mixedYawAngle = ClampInRange(-20f, mixedYawAngle, 20f); |                 //     And what should happen when this is being added to a user defined yaw that is already PI*4? | ||||||
|  |                 mixedYawAngle = ClampInRange(-12, mixedYawAngle, 12); | ||||||
| 
 | 
 | ||||||
|                 // Build the force vector to change rotation from what it is to what it should be |                 // Build the force vector to change rotation from what it is to what it should be | ||||||
|                 bankingContributionV.Z = -mixedYawAngle; |                 bankingContributionV.Z = -mixedYawAngle; | ||||||
| 
 | 
 | ||||||
|                 // Don't do it all at once. |                 // Don't do it all at once. Fudge because 1 second is too fast with most user defined roll as PI*4. | ||||||
|                 bankingContributionV /= m_bankingTimescale; |                 bankingContributionV /= m_bankingTimescale * BSParam.VehicleAngularBankingTimescaleFudge; | ||||||
| 
 | 
 | ||||||
|                 VehicleRotationalVelocity += bankingContributionV * VehicleOrientation; |                 //VehicleRotationalVelocity += bankingContributionV * VehicleOrientation; | ||||||
|  |                 VehicleRotationalVelocity += bankingContributionV; | ||||||
|  |                  | ||||||
| 
 | 
 | ||||||
|                 VDetailLog("{0},  MoveAngular,Banking,rollComp={1},speed={2},rollComp={3},yAng={4},mYAng={5},ret={6}", |                 VDetailLog("{0},  MoveAngular,Banking,rollComp={1},speed={2},rollComp={3},yAng={4},mYAng={5},ret={6}", | ||||||
|                             Prim.LocalID, rollComponents, VehicleForwardSpeed, rollComponents, yawAngle, mixedYawAngle, bankingContributionV); |                             Prim.LocalID, rollComponents, VehicleForwardSpeed, rollComponents, yawAngle, mixedYawAngle, bankingContributionV); | ||||||
|  |  | ||||||
|  | @ -123,6 +123,7 @@ public static class BSParam | ||||||
|     public static Vector3 VehicleLinearFactor { get; private set; } |     public static Vector3 VehicleLinearFactor { get; private set; } | ||||||
|     public static Vector3 VehicleAngularFactor { get; private set; } |     public static Vector3 VehicleAngularFactor { get; private set; } | ||||||
|     public static float VehicleGroundGravityFudge { get; private set; } |     public static float VehicleGroundGravityFudge { get; private set; } | ||||||
|  |     public static float VehicleAngularBankingTimescaleFudge { get; private set; } | ||||||
|     public static bool VehicleDebuggingEnabled { get; private set; } |     public static bool VehicleDebuggingEnabled { get; private set; } | ||||||
| 
 | 
 | ||||||
|     // Linkset implementation parameters |     // Linkset implementation parameters | ||||||
|  | @ -543,10 +544,14 @@ public static class BSParam | ||||||
|             0.0f, |             0.0f, | ||||||
|             (s) => { return VehicleRestitution; }, |             (s) => { return VehicleRestitution; }, | ||||||
|             (s,v) => { VehicleRestitution = v; } ), |             (s,v) => { VehicleRestitution = v; } ), | ||||||
|         new ParameterDefn<float>("VehicleGroundGravityFudge", "Factor to multiple gravity if a ground vehicle is probably on the ground (0.0 - 1.0)", |         new ParameterDefn<float>("VehicleGroundGravityFudge", "Factor to multiply gravity if a ground vehicle is probably on the ground (0.0 - 1.0)", | ||||||
|             0.2f, |             0.2f, | ||||||
|             (s) => { return VehicleGroundGravityFudge; }, |             (s) => { return VehicleGroundGravityFudge; }, | ||||||
|             (s,v) => { VehicleGroundGravityFudge = v; } ), |             (s,v) => { VehicleGroundGravityFudge = v; } ), | ||||||
|  |         new ParameterDefn<float>("VehicleAngularBankingTimescaleFudge", "Factor to multiple angular banking timescale. Tune to increase realism.", | ||||||
|  |             60.0f, | ||||||
|  |             (s) => { return VehicleAngularBankingTimescaleFudge; }, | ||||||
|  |             (s,v) => { VehicleAngularBankingTimescaleFudge = v; } ), | ||||||
|         new ParameterDefn<bool>("VehicleDebuggingEnable", "Turn on/off vehicle debugging", |         new ParameterDefn<bool>("VehicleDebuggingEnable", "Turn on/off vehicle debugging", | ||||||
|             false, |             false, | ||||||
|             (s) => { return VehicleDebuggingEnabled; }, |             (s) => { return VehicleDebuggingEnabled; }, | ||||||
|  |  | ||||||
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							|  | @ -1669,6 +1669,65 @@ | ||||||
|             A header have been received. |             A header have been received. | ||||||
|             </summary> |             </summary> | ||||||
|         </member> |         </member> | ||||||
|  |         <member name="T:HttpServer.LocklessQueue`1"> | ||||||
|  |             <summary> | ||||||
|  |             A thread-safe lockless queue that supports multiple readers and  | ||||||
|  |             multiple writers | ||||||
|  |             </summary> | ||||||
|  |         </member> | ||||||
|  |         <member name="F:HttpServer.LocklessQueue`1.head"> | ||||||
|  |             <summary>Queue head</summary> | ||||||
|  |         </member> | ||||||
|  |         <member name="F:HttpServer.LocklessQueue`1.tail"> | ||||||
|  |             <summary>Queue tail</summary> | ||||||
|  |         </member> | ||||||
|  |         <member name="F:HttpServer.LocklessQueue`1.count"> | ||||||
|  |             <summary>Queue item count</summary> | ||||||
|  |         </member> | ||||||
|  |         <member name="M:HttpServer.LocklessQueue`1.#ctor"> | ||||||
|  |             <summary> | ||||||
|  |             Constructor | ||||||
|  |             </summary> | ||||||
|  |         </member> | ||||||
|  |         <member name="M:HttpServer.LocklessQueue`1.Enqueue(`0)"> | ||||||
|  |             <summary> | ||||||
|  |             Enqueue an item | ||||||
|  |             </summary> | ||||||
|  |             <param name="item">Item to enqeue</param> | ||||||
|  |         </member> | ||||||
|  |         <member name="M:HttpServer.LocklessQueue`1.TryDequeue(`0@)"> | ||||||
|  |             <summary> | ||||||
|  |             Try to dequeue an item | ||||||
|  |             </summary> | ||||||
|  |             <param name="item">Dequeued item if the dequeue was successful</param> | ||||||
|  |             <returns>True if an item was successfully deqeued, otherwise false</returns> | ||||||
|  |         </member> | ||||||
|  |         <member name="P:HttpServer.LocklessQueue`1.Count"> | ||||||
|  |             <summary>Gets the current number of items in the queue. Since this | ||||||
|  |             is a lockless collection this value should be treated as a close | ||||||
|  |             estimate</summary> | ||||||
|  |         </member> | ||||||
|  |         <member name="T:HttpServer.LocklessQueue`1.SingleLinkNode"> | ||||||
|  |             <summary> | ||||||
|  |             Provides a node container for data in a singly linked list | ||||||
|  |             </summary> | ||||||
|  |         </member> | ||||||
|  |         <member name="F:HttpServer.LocklessQueue`1.SingleLinkNode.Next"> | ||||||
|  |             <summary>Pointer to the next node in list</summary> | ||||||
|  |         </member> | ||||||
|  |         <member name="F:HttpServer.LocklessQueue`1.SingleLinkNode.Item"> | ||||||
|  |             <summary>The data contained by the node</summary> | ||||||
|  |         </member> | ||||||
|  |         <member name="M:HttpServer.LocklessQueue`1.SingleLinkNode.#ctor"> | ||||||
|  |             <summary> | ||||||
|  |             Constructor | ||||||
|  |             </summary> | ||||||
|  |         </member> | ||||||
|  |         <member name="M:HttpServer.LocklessQueue`1.SingleLinkNode.#ctor(`0)"> | ||||||
|  |             <summary> | ||||||
|  |             Constructor | ||||||
|  |             </summary> | ||||||
|  |         </member> | ||||||
|         <member name="T:HttpServer.IHttpRequest"> |         <member name="T:HttpServer.IHttpRequest"> | ||||||
|             <summary> |             <summary> | ||||||
|             Contains server side HTTP request information. |             Contains server side HTTP request information. | ||||||
|  | @ -2825,6 +2884,11 @@ | ||||||
|             <param name="protocol">Kind of HTTPS protocol. Usually TLS or SSL.</param> |             <param name="protocol">Kind of HTTPS protocol. Usually TLS or SSL.</param> | ||||||
|             <returns>A created <see cref="T:HttpServer.IHttpClientContext"/>.</returns> |             <returns>A created <see cref="T:HttpServer.IHttpClientContext"/>.</returns> | ||||||
|         </member> |         </member> | ||||||
|  |         <member name="M:HttpServer.IHttpContextFactory.Shutdown"> | ||||||
|  |             <summary> | ||||||
|  |             Server is shutting down so shut down the factory | ||||||
|  |             </summary> | ||||||
|  |         </member> | ||||||
|         <member name="E:HttpServer.IHttpContextFactory.RequestReceived"> |         <member name="E:HttpServer.IHttpContextFactory.RequestReceived"> | ||||||
|             <summary> |             <summary> | ||||||
|             A request have been received from one of the contexts. |             A request have been received from one of the contexts. | ||||||
|  | @ -2876,6 +2940,11 @@ | ||||||
|             A creates <see cref="T:HttpServer.IHttpClientContext"/>. |             A creates <see cref="T:HttpServer.IHttpClientContext"/>. | ||||||
|             </returns> |             </returns> | ||||||
|         </member> |         </member> | ||||||
|  |         <member name="M:HttpServer.HttpContextFactory.Shutdown"> | ||||||
|  |             <summary> | ||||||
|  |             Server is shutting down so shut down the factory | ||||||
|  |             </summary> | ||||||
|  |         </member> | ||||||
|         <member name="P:HttpServer.HttpContextFactory.UseTraceLogs"> |         <member name="P:HttpServer.HttpContextFactory.UseTraceLogs"> | ||||||
|             <summary> |             <summary> | ||||||
|              True if detailed trace logs should be written. |              True if detailed trace logs should be written. | ||||||
|  | @ -4315,6 +4384,58 @@ | ||||||
|             </summary> |             </summary> | ||||||
|             <param name="message">message describing the error</param> |             <param name="message">message describing the error</param> | ||||||
|         </member> |         </member> | ||||||
|  |         <member name="T:HttpServer.ContextTimeoutManager"> | ||||||
|  |             <summary> | ||||||
|  |             Timeout Manager.   Checks for dead clients.  Clients with open connections that are not doing anything.   Closes sessions opened with keepalive. | ||||||
|  |             </summary> | ||||||
|  |         </member> | ||||||
|  |         <member name="M:HttpServer.ContextTimeoutManager.ProcessContextTimeouts"> | ||||||
|  |             <summary> | ||||||
|  |             Causes the watcher to immediately check the connections.  | ||||||
|  |             </summary> | ||||||
|  |         </member> | ||||||
|  |         <member name="M:HttpServer.ContextTimeoutManager.EnvironmentTickCount"> | ||||||
|  |             <summary> | ||||||
|  |             Environment.TickCount is an int but it counts all 32 bits so it goes positive | ||||||
|  |             and negative every 24.9 days. This trims down TickCount so it doesn't wrap | ||||||
|  |             for the callers.  | ||||||
|  |             This trims it to a 12 day interval so don't let your frame time get too long. | ||||||
|  |             </summary> | ||||||
|  |             <returns></returns> | ||||||
|  |         </member> | ||||||
|  |         <member name="M:HttpServer.ContextTimeoutManager.EnvironmentTickCountSubtract(System.Int32,System.Int32)"> | ||||||
|  |             <summary> | ||||||
|  |             Environment.TickCount is an int but it counts all 32 bits so it goes positive | ||||||
|  |             and negative every 24.9 days. Subtracts the passed value (previously fetched by | ||||||
|  |             'EnvironmentTickCount()') and accounts for any wrapping. | ||||||
|  |             </summary> | ||||||
|  |             <param name="newValue"></param> | ||||||
|  |             <param name="prevValue"></param> | ||||||
|  |             <returns>subtraction of passed prevValue from current Environment.TickCount</returns> | ||||||
|  |         </member> | ||||||
|  |         <member name="M:HttpServer.ContextTimeoutManager.EnvironmentTickCountAdd(System.Int32,System.Int32)"> | ||||||
|  |             <summary> | ||||||
|  |             Environment.TickCount is an int but it counts all 32 bits so it goes positive | ||||||
|  |             and negative every 24.9 days. Subtracts the passed value (previously fetched by | ||||||
|  |             'EnvironmentTickCount()') and accounts for any wrapping. | ||||||
|  |             </summary> | ||||||
|  |             <param name="newValue"></param> | ||||||
|  |             <param name="prevValue"></param> | ||||||
|  |             <returns>subtraction of passed prevValue from current Environment.TickCount</returns> | ||||||
|  |         </member> | ||||||
|  |         <member name="M:HttpServer.ContextTimeoutManager.EnvironmentTickCountSubtract(System.Int32)"> | ||||||
|  |             <summary> | ||||||
|  |             Environment.TickCount is an int but it counts all 32 bits so it goes positive | ||||||
|  |             and negative every 24.9 days. Subtracts the passed value (previously fetched by | ||||||
|  |             'EnvironmentTickCount()') and accounts for any wrapping. | ||||||
|  |             </summary> | ||||||
|  |             <returns>subtraction of passed prevValue from current Environment.TickCount</returns> | ||||||
|  |         </member> | ||||||
|  |         <member name="T:HttpServer.ContextTimeoutManager.MonitorType"> | ||||||
|  |             <summary> | ||||||
|  |             Use a Thread or a Timer to monitor the ugly | ||||||
|  |             </summary> | ||||||
|  |         </member> | ||||||
|         <member name="T:HttpServer.Sessions.MemorySessionStore"> |         <member name="T:HttpServer.Sessions.MemorySessionStore"> | ||||||
|             <summary> |             <summary> | ||||||
|             Session store using memory for each session. |             Session store using memory for each session. | ||||||
|  |  | ||||||
							
								
								
									
										115
									
								
								prebuild.xml
								
								
								
								
							
							
						
						
									
										115
									
								
								prebuild.xml
								
								
								
								
							|  | @ -2039,121 +2039,6 @@ | ||||||
|       </Files> |       </Files> | ||||||
|     </Project> |     </Project> | ||||||
| 
 | 
 | ||||||
|     <!-- REST plugins --> |  | ||||||
|     <Project frameworkVersion="v3_5" name="OpenSim.ApplicationPlugins.Rest" path="OpenSim/ApplicationPlugins/Rest" type="Library"> |  | ||||||
|       <Configuration name="Debug"> |  | ||||||
|         <Options> |  | ||||||
|           <OutputPath>../../../bin/</OutputPath> |  | ||||||
|         </Options> |  | ||||||
|       </Configuration> |  | ||||||
|       <Configuration name="Release"> |  | ||||||
|         <Options> |  | ||||||
|           <OutputPath>../../../bin/</OutputPath> |  | ||||||
|         </Options> |  | ||||||
|       </Configuration> |  | ||||||
| 
 |  | ||||||
|       <ReferencePath>../../../bin/</ReferencePath> |  | ||||||
|       <Reference name="Mono.Addins" path="../../../bin/"/> |  | ||||||
|       <Reference name="System"/> |  | ||||||
|       <Reference name="System.Xml"/> |  | ||||||
|       <Reference name="OpenMetaverseTypes" path="../../../bin/"/> |  | ||||||
|       <Reference name="Nini" path="../../../bin/"/> |  | ||||||
|       <Reference name="XMLRPC" path="../../../bin/"/> |  | ||||||
|       <Reference name="OpenSim"/> |  | ||||||
|       <Reference name="OpenSim.Region.ClientStack"/> |  | ||||||
|       <Reference name="OpenSim.Region.Framework"/> |  | ||||||
|       <Reference name="OpenSim.Region.CoreModules"/> |  | ||||||
|       <Reference name="OpenSim.Framework.Communications"/> |  | ||||||
|       <Reference name="OpenSim.Framework"/> |  | ||||||
|       <Reference name="OpenSim.Framework.Servers"/> |  | ||||||
|       <Reference name="OpenSim.Framework.Servers.HttpServer"/> |  | ||||||
|       <Reference name="OpenSim.Framework.Console"/> |  | ||||||
|       <Reference name="log4net" path="../../../bin/"/> |  | ||||||
| 
 |  | ||||||
|       <Files> |  | ||||||
|         <Match pattern="*.cs" recurse="false"/> |  | ||||||
|       </Files> |  | ||||||
|     </Project> |  | ||||||
| 
 |  | ||||||
|     <Project frameworkVersion="v3_5" name="OpenSim.ApplicationPlugins.Rest.Regions" path="OpenSim/ApplicationPlugins/Rest/Regions" type="Library"> |  | ||||||
|       <Configuration name="Debug"> |  | ||||||
|         <Options> |  | ||||||
|           <OutputPath>../../../../bin/</OutputPath> |  | ||||||
|         </Options> |  | ||||||
|       </Configuration> |  | ||||||
|       <Configuration name="Release"> |  | ||||||
|         <Options> |  | ||||||
|           <OutputPath>../../../../bin/</OutputPath> |  | ||||||
|         </Options> |  | ||||||
|       </Configuration> |  | ||||||
| 
 |  | ||||||
|       <ReferencePath>../../../../bin/</ReferencePath> |  | ||||||
|       <Reference name="Mono.Addins" path="../../../../bin/"/> |  | ||||||
|       <Reference name="System"/> |  | ||||||
|       <Reference name="System.Xml"/> |  | ||||||
|       <Reference name="OpenMetaverseTypes" path="../../../../bin/"/> |  | ||||||
|       <Reference name="Nini" path="../../../../bin/"/> |  | ||||||
|       <Reference name="XMLRPC" path="../../../../bin/"/> |  | ||||||
|       <Reference name="OpenSim"/> |  | ||||||
|       <Reference name="OpenSim.Region.Framework"/> |  | ||||||
|       <Reference name="OpenSim.Region.ClientStack"/> |  | ||||||
|       <Reference name="OpenSim.Region.CoreModules"/> |  | ||||||
|       <Reference name="OpenSim.Framework.Communications"/> |  | ||||||
|       <Reference name="OpenSim.Framework"/> |  | ||||||
|       <Reference name="OpenSim.Framework.Servers"/> |  | ||||||
|       <Reference name="OpenSim.Framework.Servers.HttpServer"/> |  | ||||||
|       <Reference name="OpenSim.Framework.Console"/> |  | ||||||
|       <Reference name="OpenSim.ApplicationPlugins.Rest"/> |  | ||||||
|       <Reference name="log4net" path="../../../../bin/"/> |  | ||||||
| 
 |  | ||||||
|       <Files> |  | ||||||
|         <Match pattern="*.cs" recurse="true"/> |  | ||||||
|         <Match buildAction="EmbeddedResource" path="Resources" pattern="*.addin.xml" recurse="true"/> |  | ||||||
|       </Files> |  | ||||||
|     </Project> |  | ||||||
| 
 |  | ||||||
|     <Project frameworkVersion="v3_5" name="OpenSim.ApplicationPlugins.Rest.Inventory" path="OpenSim/ApplicationPlugins/Rest/Inventory" type="Library"> |  | ||||||
|       <Configuration name="Debug"> |  | ||||||
|         <Options> |  | ||||||
|           <OutputPath>../../../../bin/</OutputPath> |  | ||||||
|         </Options> |  | ||||||
|       </Configuration> |  | ||||||
|       <Configuration name="Release"> |  | ||||||
|         <Options> |  | ||||||
|           <OutputPath>../../../../bin/</OutputPath> |  | ||||||
|         </Options> |  | ||||||
|       </Configuration> |  | ||||||
| 
 |  | ||||||
|       <ReferencePath>../../../../bin/</ReferencePath> |  | ||||||
|       <Reference name="Mono.Addins" path="../../../../bin/"/> |  | ||||||
|       <Reference name="System"/> |  | ||||||
|       <Reference name="System.Xml"/> |  | ||||||
|       <Reference name="System.Drawing"/> |  | ||||||
|       <Reference name="OpenMetaverseTypes" path="../../../../bin/"/> |  | ||||||
|       <Reference name="OpenMetaverse" path="../../../../bin/"/> |  | ||||||
|       <Reference name="Nini" path="../../../../bin/"/> |  | ||||||
|       <Reference name="XMLRPC" path="../../../../bin/"/> |  | ||||||
|       <Reference name="OpenSim"/> |  | ||||||
|       <Reference name="OpenSim.Region.Framework"/> |  | ||||||
|       <Reference name="OpenSim.Region.ClientStack"/> |  | ||||||
|       <Reference name="OpenSim.Region.CoreModules"/> |  | ||||||
|       <Reference name="OpenSim.Framework.Communications"/> |  | ||||||
|       <Reference name="OpenSim.Framework"/> |  | ||||||
|       <Reference name="OpenSim.Framework.Servers"/> |  | ||||||
|       <Reference name="OpenSim.Framework.Servers.HttpServer"/> |  | ||||||
|       <Reference name="OpenSim.Framework.Console"/> |  | ||||||
|       <Reference name="OpenSim.Services.Interfaces"/> |  | ||||||
|       <Reference name="OpenSim.ApplicationPlugins.Rest"/> |  | ||||||
|       <Reference name="log4net" path="../../../../bin/"/> |  | ||||||
| 
 |  | ||||||
|       <Files> |  | ||||||
|         <Match pattern="*.cs" recurse="true"/> |  | ||||||
|         <Match buildAction="EmbeddedResource" path="Resources" pattern="*.addin.xml" recurse="true"/> |  | ||||||
|       </Files> |  | ||||||
|     </Project> |  | ||||||
| 
 |  | ||||||
|     <!-- /REST plugins --> |  | ||||||
| 
 |  | ||||||
|     <!-- Scene Server API Example Apps --> |     <!-- Scene Server API Example Apps --> | ||||||
| 
 | 
 | ||||||
|     <Project frameworkVersion="v3_5" name="OpenSim.Region.DataSnapshot" path="OpenSim/Region/DataSnapshot" type="Library"> |     <Project frameworkVersion="v3_5" name="OpenSim.Region.DataSnapshot" path="OpenSim/Region/DataSnapshot" type="Library"> | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue
	
	 Melanie
						Melanie