aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/ApplicationPlugins/Rest/Inventory
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--OpenSim/ApplicationPlugins/Rest/Inventory/IRestHandler.cs7
-rw-r--r--OpenSim/ApplicationPlugins/Rest/Inventory/RequestData.cs147
-rw-r--r--OpenSim/ApplicationPlugins/Rest/Inventory/Rest.cs40
-rw-r--r--OpenSim/ApplicationPlugins/Rest/Inventory/RestAssetServices.cs31
-rw-r--r--OpenSim/ApplicationPlugins/Rest/Inventory/RestHandler.cs70
-rw-r--r--OpenSim/ApplicationPlugins/Rest/Inventory/RestInventoryServices.cs325
-rw-r--r--OpenSim/ApplicationPlugins/Rest/Inventory/tests/Remote.cs26
7 files changed, 258 insertions, 388 deletions
diff --git a/OpenSim/ApplicationPlugins/Rest/Inventory/IRestHandler.cs b/OpenSim/ApplicationPlugins/Rest/Inventory/IRestHandler.cs
index 69f91e4..82dc2e4 100644
--- a/OpenSim/ApplicationPlugins/Rest/Inventory/IRestHandler.cs
+++ b/OpenSim/ApplicationPlugins/Rest/Inventory/IRestHandler.cs
@@ -23,7 +23,6 @@
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 *
27 */ 26 */
28 27
29using System; 28using System;
@@ -41,11 +40,11 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
41 40
42 public delegate void RestMethodHandler(RequestData rdata); 41 public delegate void RestMethodHandler(RequestData rdata);
43 public delegate RequestData RestMethodAllocator(OSHttpRequest request, OSHttpResponse response, string path); 42 public delegate RequestData RestMethodAllocator(OSHttpRequest request, OSHttpResponse response, string path);
44 43
45 /// <summary> 44 /// <summary>
46 /// This interface represents the boundary between the general purpose 45 /// This interface represents the boundary between the general purpose
47 /// REST plugin handling, and the functionally specific handlers. The 46 /// REST plugin handling, and the functionally specific handlers. The
48 /// handler knows only to initialize and terminate all such handlers 47 /// handler knows only to initialize and terminate all such handlers
49 /// that it finds. Implementing this interface identifies the class as 48 /// that it finds. Implementing this interface identifies the class as
50 /// a REST handler implementation. 49 /// a REST handler implementation.
51 /// </summary> 50 /// </summary>
@@ -55,7 +54,7 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
55 54
56 string MsgId { get; } 55 string MsgId { get; }
57 string RequestId { get; } 56 string RequestId { get; }
58 57
59 void AddPathHandler(RestMethodHandler mh, string path, RestMethodAllocator ma); 58 void AddPathHandler(RestMethodHandler mh, string path, RestMethodAllocator ma);
60 void AddStreamHandler(string httpMethod, string path, RestMethod method); 59 void AddStreamHandler(string httpMethod, string path, RestMethod method);
61 60
diff --git a/OpenSim/ApplicationPlugins/Rest/Inventory/RequestData.cs b/OpenSim/ApplicationPlugins/Rest/Inventory/RequestData.cs
index 6742402..24e5ada 100644
--- a/OpenSim/ApplicationPlugins/Rest/Inventory/RequestData.cs
+++ b/OpenSim/ApplicationPlugins/Rest/Inventory/RequestData.cs
@@ -23,7 +23,6 @@
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 *
27 */ 26 */
28 27
29using System; 28using System;
@@ -44,14 +43,14 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
44 43
45 /// <summary> 44 /// <summary>
46 /// This class represents the current REST request. It 45 /// This class represents the current REST request. It
47 /// encapsulates the request/response state and takes care 46 /// encapsulates the request/response state and takes care
48 /// of response generation without exposing the REST handler 47 /// of response generation without exposing the REST handler
49 /// to the actual mechanisms involved. 48 /// to the actual mechanisms involved.
50 /// 49 ///
51 /// This structure is created on entry to the Handler 50 /// This structure is created on entry to the Handler
52 /// method and is disposed of upon return. It is part of 51 /// method and is disposed of upon return. It is part of
53 /// the plug-in infrastructure, rather than the functionally 52 /// the plug-in infrastructure, rather than the functionally
54 /// specific REST handler, and fundamental changes to 53 /// specific REST handler, and fundamental changes to
55 /// this should be reflected in the Rest HandlerVersion. The 54 /// this should be reflected in the Rest HandlerVersion. The
56 /// object is instantiated, and may be extended by, any 55 /// object is instantiated, and may be extended by, any
57 /// given handler. See the inventory handler for an example 56 /// given handler. See the inventory handler for an example
@@ -84,7 +83,7 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
84 // Storing information in body will suppress the return of 83 // Storing information in body will suppress the return of
85 // statusBody which is only intended to report status on 84 // statusBody which is only intended to report status on
86 // requests which do not themselves ordinarily generate 85 // requests which do not themselves ordinarily generate
87 // an informational response. All of this is handled in 86 // an informational response. All of this is handled in
88 // Respond(). 87 // Respond().
89 88
90 internal byte[] buffer = null; 89 internal byte[] buffer = null;
@@ -92,8 +91,8 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
92 internal string bodyType = "text/html"; 91 internal string bodyType = "text/html";
93 92
94 // The encoding in effect is set to a server default. It may 93 // The encoding in effect is set to a server default. It may
95 // subsequently be overridden by a Content header. This 94 // subsequently be overridden by a Content header. This
96 // value is established during construction and is used 95 // value is established during construction and is used
97 // wherever encoding services are needed. 96 // wherever encoding services are needed.
98 97
99 internal Encoding encoding = Rest.Encoding; 98 internal Encoding encoding = Rest.Encoding;
@@ -110,7 +109,7 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
110 109
111 // The path part of the URI is decomposed. pathNodes 110 // The path part of the URI is decomposed. pathNodes
112 // is an array of every element in the URI. Parameters 111 // is an array of every element in the URI. Parameters
113 // is an array that contains only those nodes that 112 // is an array that contains only those nodes that
114 // are not a part of the authority prefix 113 // are not a part of the authority prefix
115 114
116 private string[] pathNodes = null; 115 private string[] pathNodes = null;
@@ -118,7 +117,7 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
118 private static readonly string[] EmptyPath = { String.Empty }; 117 private static readonly string[] EmptyPath = { String.Empty };
119 118
120 // The status code gets set during the course of processing 119 // The status code gets set during the course of processing
121 // and is the HTTP completion code. The status body is 120 // and is the HTTP completion code. The status body is
122 // initialized during construction, is appended to during the 121 // initialized during construction, is appended to during the
123 // course of execution, and is finalized during Respond 122 // course of execution, and is finalized during Respond
124 // processing. 123 // processing.
@@ -166,7 +165,7 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
166 // force selection of a particular authentication model 165 // force selection of a particular authentication model
167 // (choosing from amongst those supported of course) 166 // (choosing from amongst those supported of course)
168 // 167 //
169 168
170 internal bool authenticated = false; 169 internal bool authenticated = false;
171 internal string scheme = null; 170 internal string scheme = null;
172 internal string realm = Rest.Realm; 171 internal string realm = Rest.Realm;
@@ -183,7 +182,7 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
183 internal string userPass = String.Empty; 182 internal string userPass = String.Empty;
184 183
185 // Session related tables. These are only needed if QOP is set to "auth-sess" 184 // Session related tables. These are only needed if QOP is set to "auth-sess"
186 // and for now at least, it is not. Session related authentication is of 185 // and for now at least, it is not. Session related authentication is of
187 // questionable merit in the context of REST anyway, but it is, arguably, more 186 // questionable merit in the context of REST anyway, but it is, arguably, more
188 // secure. 187 // secure.
189 188
@@ -199,23 +198,23 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
199 198
200 private static Regex schema = new Regex("^\\s*(?<scheme>\\w+)\\s*.*", 199 private static Regex schema = new Regex("^\\s*(?<scheme>\\w+)\\s*.*",
201 RegexOptions.Compiled | RegexOptions.IgnoreCase); 200 RegexOptions.Compiled | RegexOptions.IgnoreCase);
202 201
203 private static Regex basicParms = new Regex("^\\s*(?:\\w+)\\s+(?<pval>\\S+)\\s*", 202 private static Regex basicParms = new Regex("^\\s*(?:\\w+)\\s+(?<pval>\\S+)\\s*",
204 RegexOptions.Compiled | RegexOptions.IgnoreCase); 203 RegexOptions.Compiled | RegexOptions.IgnoreCase);
205 204
206 private static Regex digestParm1 = new Regex("\\s*(?<parm>\\w+)\\s*=\\s*\"(?<pval>[^\"]+)\"", 205 private static Regex digestParm1 = new Regex("\\s*(?<parm>\\w+)\\s*=\\s*\"(?<pval>[^\"]+)\"",
207 RegexOptions.Compiled | RegexOptions.IgnoreCase); 206 RegexOptions.Compiled | RegexOptions.IgnoreCase);
208 207
209 private static Regex digestParm2 = new Regex("\\s*(?<parm>\\w+)\\s*=\\s*(?<pval>[^\\p{P}\\s]+)", 208 private static Regex digestParm2 = new Regex("\\s*(?<parm>\\w+)\\s*=\\s*(?<pval>[^\\p{P}\\s]+)",
210 RegexOptions.Compiled | RegexOptions.IgnoreCase); 209 RegexOptions.Compiled | RegexOptions.IgnoreCase);
211 210
212 private static Regex reuserPass = new Regex("(?<user>[^:]+):(?<pass>[\\S\\s]*)", 211 private static Regex reuserPass = new Regex("(?<user>[^:]+):(?<pass>[\\S\\s]*)",
213 RegexOptions.Compiled | RegexOptions.IgnoreCase); 212 RegexOptions.Compiled | RegexOptions.IgnoreCase);
214 213
215 // For efficiency, we create static instances of these objects 214 // For efficiency, we create static instances of these objects
216 215
217 private static MD5 md5hash = MD5.Create(); 216 private static MD5 md5hash = MD5.Create();
218 217
219 private static StringComparer sc = StringComparer.OrdinalIgnoreCase; 218 private static StringComparer sc = StringComparer.OrdinalIgnoreCase;
220 219
221#region properties 220#region properties
@@ -228,15 +227,15 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
228 } 227 }
229 228
230 /// <summary> 229 /// <summary>
231 /// Return a boolean indication of whether or no an authenticated user is 230 /// Return a boolean indication of whether or no an authenticated user is
232 /// associated with this request. This could be wholly integrated, but 231 /// associated with this request. This could be wholly integrated, but
233 /// that would make authentication mandatory. 232 /// that would make authentication mandatory.
234 /// </summary> 233 /// </summary>
235 234
236 internal bool IsAuthenticated 235 internal bool IsAuthenticated
237 { 236 {
238 get 237 get
239 { 238 {
240 if (Rest.Authenticate) 239 if (Rest.Authenticate)
241 { 240 {
242 if (!authenticated) 241 if (!authenticated)
@@ -258,31 +257,31 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
258 internal string[] PathNodes 257 internal string[] PathNodes
259 { 258 {
260 get 259 get
261 { 260 {
262 return pathNodes; 261 return pathNodes;
263 } 262 }
264 } 263 }
265 264
266 /// <summary> 265 /// <summary>
267 /// Access to all non-prefix 'nodes' in the supplied URI as an 266 /// Access to all non-prefix 'nodes' in the supplied URI as an
268 /// array of strings. These identify a specific resource that 267 /// array of strings. These identify a specific resource that
269 /// is managed by the authority (the prefix). 268 /// is managed by the authority (the prefix).
270 /// </summary> 269 /// </summary>
271 270
272 internal string[] Parameters 271 internal string[] Parameters
273 { 272 {
274 get 273 get
275 { 274 {
276 return parameters; 275 return parameters;
277 } 276 }
278 } 277 }
279 278
280#endregion properties 279#endregion properties
281 280
282#region constructors 281#region constructors
283 282
284 // Constructor 283 // Constructor
285 284
286 internal RequestData(OSHttpRequest p_request, OSHttpResponse p_response, string p_qprefix) 285 internal RequestData(OSHttpRequest p_request, OSHttpResponse p_response, string p_qprefix)
287 { 286 {
288 287
@@ -315,7 +314,7 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
315 /// Realm, domain, etc. 314 /// Realm, domain, etc.
316 /// 315 ///
317 /// This method checks to see if the current request is already 316 /// This method checks to see if the current request is already
318 /// authenticated for this domain. If it is, then it returns 317 /// authenticated for this domain. If it is, then it returns
319 /// true. If it is not, then it issues a challenge to the client 318 /// true. If it is not, then it issues a challenge to the client
320 /// and responds negatively to the request. 319 /// and responds negatively to the request.
321 /// 320 ///
@@ -339,7 +338,7 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
339 Rest.Log.DebugFormat("{0} Challenge reason: No authorization data", MsgId); 338 Rest.Log.DebugFormat("{0} Challenge reason: No authorization data", MsgId);
340 DoChallenge(); 339 DoChallenge();
341 } 340 }
342 341
343 // So, we have authentication data, now we have to check to 342 // So, we have authentication data, now we have to check to
344 // see what we got and whether or not it is valid for the 343 // see what we got and whether or not it is valid for the
345 // current domain. To do this we need to interpret the data 344 // current domain. To do this we need to interpret the data
@@ -438,7 +437,7 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
438 437
439 // The service provider can force a particular scheme by 438 // The service provider can force a particular scheme by
440 // assigning a value to scheme. 439 // assigning a value to scheme.
441 440
442 // Basic authentication is pretty simple. 441 // Basic authentication is pretty simple.
443 // Just specify the realm in question. 442 // Just specify the realm in question.
444 443
@@ -468,8 +467,8 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
468 sbuilder.Append(" "); 467 sbuilder.Append(" ");
469 468
470 // Specify the effective realm. This should 469 // Specify the effective realm. This should
471 // never be null if we are uthenticating, as it is required for all 470 // never be null if we are uthenticating, as it is required for all
472 // authentication schemes. It defines, in conjunction with the 471 // authentication schemes. It defines, in conjunction with the
473 // absolute URI information, the domain to which the authentication 472 // absolute URI information, the domain to which the authentication
474 // applies. It is an arbitrary string. I *believe* this allows an 473 // applies. It is an arbitrary string. I *believe* this allows an
475 // authentication to apply to disjoint resources within the same 474 // authentication to apply to disjoint resources within the same
@@ -485,7 +484,7 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
485 } 484 }
486 485
487 // Share our nonce. This is *uniquely* generated each time a 401 is 486 // Share our nonce. This is *uniquely* generated each time a 401 is
488 // returned. We do not generate a very sophisticated nonce at the 487 // returned. We do not generate a very sophisticated nonce at the
489 // moment (it's simply a base64 encoded UUID). 488 // moment (it's simply a base64 encoded UUID).
490 489
491 if (nonce != null) 490 if (nonce != null)
@@ -532,7 +531,7 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
532 sbuilder.Append(Rest.CS_COMMA); 531 sbuilder.Append(Rest.CS_COMMA);
533 } 532 }
534 533
535 // Theoretically QOP is optional, but it is required by a compliant 534 // Theoretically QOP is optional, but it is required by a compliant
536 // with current versions of the scheme. In fact IE requires that QOP 535 // with current versions of the scheme. In fact IE requires that QOP
537 // be specified and will refuse to authenticate otherwise. 536 // be specified and will refuse to authenticate otherwise.
538 537
@@ -555,7 +554,7 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
555 } 554 }
556 555
557 // We don't know the userid that will be used 556 // We don't know the userid that will be used
558 // so we cannot make any authentication domain 557 // so we cannot make any authentication domain
559 // assumptions. So the prefix will determine 558 // assumptions. So the prefix will determine
560 // this. 559 // this.
561 560
@@ -582,7 +581,7 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
582 /// understand this and also expect it to be the first one 581 /// understand this and also expect it to be the first one
583 /// offered. So we do. 582 /// offered. So we do.
584 /// OpenSim also needs this, as it is the only scheme that allows 583 /// OpenSim also needs this, as it is the only scheme that allows
585 /// authentication using the hashed passwords stored in the 584 /// authentication using the hashed passwords stored in the
586 /// user database. 585 /// user database.
587 /// </summary> 586 /// </summary>
588 587
@@ -599,7 +598,7 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
599 foreach (Match m in matches) 598 foreach (Match m in matches)
600 { 599 {
601 authparms.Add("response",m.Groups["pval"].Value); 600 authparms.Add("response",m.Groups["pval"].Value);
602 Rest.Log.DebugFormat("{0} Parameter matched : {1} = {2}", 601 Rest.Log.DebugFormat("{0} Parameter matched : {1} = {2}",
603 MsgId, "response", m.Groups["pval"].Value); 602 MsgId, "response", m.Groups["pval"].Value);
604 } 603 }
605 604
@@ -623,7 +622,7 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
623 } 622 }
624 623
625 /// <summary> 624 /// <summary>
626 /// This method provides validation in support of the BASIC 625 /// This method provides validation in support of the BASIC
627 /// authentication method. This is not normaly expected to be 626 /// authentication method. This is not normaly expected to be
628 /// used, but is included for completeness (and because I tried 627 /// used, but is included for completeness (and because I tried
629 /// it first). 628 /// it first).
@@ -664,12 +663,12 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
664 string last; 663 string last;
665 664
666 // Distinguish the parts, if necessary 665 // Distinguish the parts, if necessary
667 666
668 if ((x=user.IndexOf(Rest.C_SPACE)) != -1) 667 if ((x=user.IndexOf(Rest.C_SPACE)) != -1)
669 { 668 {
670 first = user.Substring(0,x); 669 first = user.Substring(0,x);
671 last = user.Substring(x+1); 670 last = user.Substring(x+1);
672 } 671 }
673 else 672 else
674 { 673 {
675 first = user; 674 first = user;
@@ -685,9 +684,9 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
685 684
686 HA1 = HashToString(pass); 685 HA1 = HashToString(pass);
687 HA1 = HashToString(String.Format("{0}:{1}",HA1,udata.PasswordSalt)); 686 HA1 = HashToString(String.Format("{0}:{1}",HA1,udata.PasswordSalt));
688 687
689 return (0 == sc.Compare(HA1, udata.PasswordHash)); 688 return (0 == sc.Compare(HA1, udata.PasswordHash));
690 689
691 } 690 }
692 691
693#endregion authentication_basic 692#endregion authentication_basic
@@ -712,7 +711,7 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
712 foreach (Match m in matches) 711 foreach (Match m in matches)
713 { 712 {
714 authparms.Add(m.Groups["parm"].Value,m.Groups["pval"].Value); 713 authparms.Add(m.Groups["parm"].Value,m.Groups["pval"].Value);
715 Rest.Log.DebugFormat("{0} String Parameter matched : {1} = {2}", 714 Rest.Log.DebugFormat("{0} String Parameter matched : {1} = {2}",
716 MsgId, m.Groups["parm"].Value,m.Groups["pval"].Value); 715 MsgId, m.Groups["parm"].Value,m.Groups["pval"].Value);
717 } 716 }
718 717
@@ -723,7 +722,7 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
723 foreach (Match m in matches) 722 foreach (Match m in matches)
724 { 723 {
725 authparms.Add(m.Groups["parm"].Value,m.Groups["pval"].Value); 724 authparms.Add(m.Groups["parm"].Value,m.Groups["pval"].Value);
726 Rest.Log.DebugFormat("{0} Tokenized Parameter matched : {1} = {2}", 725 Rest.Log.DebugFormat("{0} Tokenized Parameter matched : {1} = {2}",
727 MsgId, m.Groups["parm"].Value,m.Groups["pval"].Value); 726 MsgId, m.Groups["parm"].Value,m.Groups["pval"].Value);
728 } 727 }
729 728
@@ -760,7 +759,7 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
760 759
761 if (!authparms.TryGetValue("nonce", out nonce) || nonce == null) 760 if (!authparms.TryGetValue("nonce", out nonce) || nonce == null)
762 { 761 {
763 Rest.Log.WarnFormat("{0} Authentication failed: nonce missing", MsgId); 762 Rest.Log.WarnFormat("{0} Authentication failed: nonce missing", MsgId);
764 break; 763 break;
765 } 764 }
766 765
@@ -771,7 +770,7 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
771 { 770 {
772 if (temp != opaque) 771 if (temp != opaque)
773 { 772 {
774 Rest.Log.WarnFormat("{0} Authentication failed: bad opaque value", MsgId); 773 Rest.Log.WarnFormat("{0} Authentication failed: bad opaque value", MsgId);
775 break; 774 break;
776 } 775 }
777 } 776 }
@@ -783,7 +782,7 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
783 { 782 {
784 if (temp != algorithm) 783 if (temp != algorithm)
785 { 784 {
786 Rest.Log.WarnFormat("{0} Authentication failed: bad algorithm value", MsgId); 785 Rest.Log.WarnFormat("{0} Authentication failed: bad algorithm value", MsgId);
787 break; 786 break;
788 } 787 }
789 } 788 }
@@ -800,7 +799,7 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
800 799
801 if (!authparms.ContainsKey("cnonce")) 800 if (!authparms.ContainsKey("cnonce"))
802 { 801 {
803 Rest.Log.WarnFormat("{0} Authentication failed: cnonce missing", MsgId); 802 Rest.Log.WarnFormat("{0} Authentication failed: cnonce missing", MsgId);
804 break; 803 break;
805 } 804 }
806 805
@@ -808,7 +807,7 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
808 807
809 if (!authparms.TryGetValue("nc", out nck) || nck == null) 808 if (!authparms.TryGetValue("nc", out nck) || nck == null)
810 { 809 {
811 Rest.Log.WarnFormat("{0} Authentication failed: cnonce counter missing", MsgId); 810 Rest.Log.WarnFormat("{0} Authentication failed: cnonce counter missing", MsgId);
812 break; 811 break;
813 } 812 }
814 813
@@ -820,7 +819,7 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
820 819
821 if (Rest.Hex2Int(ncl) >= Rest.Hex2Int(nck)) 820 if (Rest.Hex2Int(ncl) >= Rest.Hex2Int(nck))
822 { 821 {
823 Rest.Log.WarnFormat("{0} Authentication failed: bad cnonce counter", MsgId); 822 Rest.Log.WarnFormat("{0} Authentication failed: bad cnonce counter", MsgId);
824 break; 823 break;
825 } 824 }
826 cntable[nonce] = nck; 825 cntable[nonce] = nck;
@@ -840,12 +839,12 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
840 // these MUST NOT be present. 839 // these MUST NOT be present.
841 if (authparms.ContainsKey("cnonce")) 840 if (authparms.ContainsKey("cnonce"))
842 { 841 {
843 Rest.Log.WarnFormat("{0} Authentication failed: invalid cnonce", MsgId); 842 Rest.Log.WarnFormat("{0} Authentication failed: invalid cnonce", MsgId);
844 break; 843 break;
845 } 844 }
846 if (authparms.ContainsKey("nc")) 845 if (authparms.ContainsKey("nc"))
847 { 846 {
848 Rest.Log.WarnFormat("{0} Authentication failed: invalid cnonce counter[2]", MsgId); 847 Rest.Log.WarnFormat("{0} Authentication failed: invalid cnonce counter[2]", MsgId);
849 break; 848 break;
850 } 849 }
851 } 850 }
@@ -854,7 +853,7 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
854 853
855 authenticated = ValidateDigest(userName, nonce, cnonce, nck, authPrefix, response); 854 authenticated = ValidateDigest(userName, nonce, cnonce, nck, authPrefix, response);
856 855
857 } 856 }
858 while (false); 857 while (false);
859 858
860 } 859 }
@@ -864,10 +863,10 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
864 /// <summary> 863 /// <summary>
865 /// This mechanism is used by the digest authentication mechanism 864 /// This mechanism is used by the digest authentication mechanism
866 /// to return the user's password. In fact, because the OpenSim 865 /// to return the user's password. In fact, because the OpenSim
867 /// user's passwords are already hashed, and the HTTP mechanism 866 /// user's passwords are already hashed, and the HTTP mechanism
868 /// does not supply an open password, the hashed passwords cannot 867 /// does not supply an open password, the hashed passwords cannot
869 /// be used unless the client has used the same salting mechanism 868 /// be used unless the client has used the same salting mechanism
870 /// to has the password before using it in the authentication 869 /// to has the password before using it in the authentication
871 /// algorithn. This is not inconceivable... 870 /// algorithn. This is not inconceivable...
872 /// </summary> 871 /// </summary>
873 872
@@ -879,12 +878,12 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
879 string last; 878 string last;
880 879
881 // Distinguish the parts, if necessary 880 // Distinguish the parts, if necessary
882 881
883 if ((x=user.IndexOf(Rest.C_SPACE)) != -1) 882 if ((x=user.IndexOf(Rest.C_SPACE)) != -1)
884 { 883 {
885 first = user.Substring(0,x); 884 first = user.Substring(0,x);
886 last = user.Substring(x+1); 885 last = user.Substring(x+1);
887 } 886 }
888 else 887 else
889 { 888 {
890 first = user; 889 first = user;
@@ -955,7 +954,7 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
955 HA2 = HashToString(patt); 954 HA2 = HashToString(patt);
956 955
957 // Generate Digest 956 // Generate Digest
958 957
959 if (qop != String.Empty) 958 if (qop != String.Empty)
960 { 959 {
961 patt = String.Format("{0}:{1}:{2}:{3}:{4}:{5}", HA1, nonce, nck, cnonce, qop, HA2); 960 patt = String.Format("{0}:{1}:{2}:{3}:{4}:{5}", HA1, nonce, nck, cnonce, qop, HA2);
@@ -1011,7 +1010,7 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
1011 } 1010 }
1012 1011
1013 /// <summary> 1012 /// <summary>
1014 /// Indicate a functionally-dependent conclusion to the 1013 /// Indicate a functionally-dependent conclusion to the
1015 /// request. See Rest.cs for a list of possible values. 1014 /// request. See Rest.cs for a list of possible values.
1016 /// </summary> 1015 /// </summary>
1017 1016
@@ -1023,7 +1022,7 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
1023 /// <summary> 1022 /// <summary>
1024 /// Indicate that a request should be redirected, using 1023 /// Indicate that a request should be redirected, using
1025 /// the HTTP completion codes. Permanent and temporary 1024 /// the HTTP completion codes. Permanent and temporary
1026 /// redirections may be indicated. The supplied URL is 1025 /// redirections may be indicated. The supplied URL is
1027 /// the new location of the resource. 1026 /// the new location of the resource.
1028 /// </summary> 1027 /// </summary>
1029 1028
@@ -1057,7 +1056,7 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
1057 } 1056 }
1058 1057
1059 /// <summary> 1058 /// <summary>
1060 /// For the more adventurous. This failure also includes a 1059 /// For the more adventurous. This failure also includes a
1061 /// specified entity to be appended to the code-related 1060 /// specified entity to be appended to the code-related
1062 /// status string. 1061 /// status string.
1063 /// </summary> 1062 /// </summary>
@@ -1101,12 +1100,12 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
1101 1100
1102 fail = true; 1101 fail = true;
1103 1102
1104 // Respond to the client's request, tag the response (for the 1103 // Respond to the client's request, tag the response (for the
1105 // benefit of trace) to indicate the reason. 1104 // benefit of trace) to indicate the reason.
1106 1105
1107 Respond(String.Format("Failure response: ({0}) : {1}", 1106 Respond(String.Format("Failure response: ({0}) : {1}",
1108 code, Rest.HttpStatusDesc[code])); 1107 code, Rest.HttpStatusDesc[code]));
1109 1108
1110 // Finally initialize and the throw a RestException. All of the 1109 // Finally initialize and the throw a RestException. All of the
1111 // handler's infrastructure knows that this is a "normal" 1110 // handler's infrastructure knows that this is a "normal"
1112 // completion from a code point-of-view. 1111 // completion from a code point-of-view.
@@ -1129,7 +1128,7 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
1129 Fail(Rest.HttpStatusCodeNotImplemented, "request rejected (not implemented)"); 1128 Fail(Rest.HttpStatusCodeNotImplemented, "request rejected (not implemented)");
1130 } 1129 }
1131 1130
1132 // This MUST be called by an agent handler before it returns 1131 // This MUST be called by an agent handler before it returns
1133 // control to Handle, otherwise the request will be ignored. 1132 // control to Handle, otherwise the request will be ignored.
1134 // This is called implciitly for the REST stream handlers and 1133 // This is called implciitly for the REST stream handlers and
1135 // is harmless if it is called twice. 1134 // is harmless if it is called twice.
@@ -1222,7 +1221,7 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
1222 1221
1223 } 1222 }
1224 1223
1225 // Set the status code & description. If nothing has been stored, 1224 // Set the status code & description. If nothing has been stored,
1226 // we consider that a success. 1225 // we consider that a success.
1227 1226
1228 if (statusCode == 0) 1227 if (statusCode == 0)
@@ -1236,7 +1235,7 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
1236 1235
1237 // For a redirect we need to set the relocation header accordingly 1236 // For a redirect we need to set the relocation header accordingly
1238 1237
1239 if (response.StatusCode == (int) Rest.HttpStatusCodeTemporaryRedirect || 1238 if (response.StatusCode == (int) Rest.HttpStatusCodeTemporaryRedirect ||
1240 response.StatusCode == (int) Rest.HttpStatusCodePermanentRedirect) 1239 response.StatusCode == (int) Rest.HttpStatusCodePermanentRedirect)
1241 { 1240 {
1242 Rest.Log.DebugFormat("{0} Re-direct location is {1}", MsgId, redirectLocation); 1241 Rest.Log.DebugFormat("{0} Re-direct location is {1}", MsgId, redirectLocation);
@@ -1252,7 +1251,7 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
1252 // We've left the setting of handled' until the 1251 // We've left the setting of handled' until the
1253 // last minute because the header settings included 1252 // last minute because the header settings included
1254 // above are pretty harmless. But everything from 1253 // above are pretty harmless. But everything from
1255 // here on down probably leaves the response 1254 // here on down probably leaves the response
1256 // element unusable by anyone else. 1255 // element unusable by anyone else.
1257 1256
1258 handled = true; 1257 handled = true;
@@ -1267,7 +1266,7 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
1267 1266
1268 if (buffer != null && buffer.Length != 0) 1267 if (buffer != null && buffer.Length != 0)
1269 { 1268 {
1270 Rest.Log.DebugFormat("{0} Entity buffer, length = {1} : <{2}>", 1269 Rest.Log.DebugFormat("{0} Entity buffer, length = {1} : <{2}>",
1271 MsgId, buffer.Length, encoding.GetString(buffer)); 1270 MsgId, buffer.Length, encoding.GetString(buffer));
1272 response.OutputStream.Write(buffer, 0, buffer.Length); 1271 response.OutputStream.Write(buffer, 0, buffer.Length);
1273 } 1272 }
@@ -1295,11 +1294,11 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
1295 { 1294 {
1296 if (Rest.DEBUG) 1295 if (Rest.DEBUG)
1297 { 1296 {
1298 Rest.Log.DebugFormat("{0} Adding header: <{1}: {2}>", 1297 Rest.Log.DebugFormat("{0} Adding header: <{1}: {2}>",
1299 MsgId, hdr, data); 1298 MsgId, hdr, data);
1300 if (response.Headers.Get(hdr) != null) 1299 if (response.Headers.Get(hdr) != null)
1301 { 1300 {
1302 Rest.Log.DebugFormat("{0} Multipe {1} headers will be generated>", 1301 Rest.Log.DebugFormat("{0} Multipe {1} headers will be generated>",
1303 MsgId, hdr); 1302 MsgId, hdr);
1304 } 1303 }
1305 } 1304 }
@@ -1313,7 +1312,7 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
1313 Rest.Log.DebugFormat("{0} Removing header: <{1}>", MsgId, hdr); 1312 Rest.Log.DebugFormat("{0} Removing header: <{1}>", MsgId, hdr);
1314 if (response.Headers.Get(hdr) == null) 1313 if (response.Headers.Get(hdr) == null)
1315 { 1314 {
1316 Rest.Log.DebugFormat("{0} No such header existed", 1315 Rest.Log.DebugFormat("{0} No such header existed",
1317 MsgId, hdr); 1316 MsgId, hdr);
1318 } 1317 }
1319 } 1318 }
@@ -1326,7 +1325,7 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
1326 { 1325 {
1327 for (int i=0;i<response.Headers.Count;i++) 1326 for (int i=0;i<response.Headers.Count;i++)
1328 { 1327 {
1329 Rest.Log.DebugFormat("{0} Header[{1}] : {2}", MsgId, i, 1328 Rest.Log.DebugFormat("{0} Header[{1}] : {2}", MsgId, i,
1330 response.Headers.Get(i)); 1329 response.Headers.Get(i));
1331 } 1330 }
1332 } 1331 }
@@ -1404,7 +1403,7 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
1404 // If we succeeded in getting a path, perform any 1403 // If we succeeded in getting a path, perform any
1405 // additional pre-processing required. 1404 // additional pre-processing required.
1406 1405
1407 if (path != null) 1406 if (path != null)
1408 { 1407 {
1409 if (Rest.ExtendedEscape) 1408 if (Rest.ExtendedEscape)
1410 { 1409 {
@@ -1442,14 +1441,14 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
1442 { 1441 {
1443 parameters = new string[0]; 1442 parameters = new string[0];
1444 } 1443 }
1445 1444
1446 // Generate a debug list of the decoded parameters 1445 // Generate a debug list of the decoded parameters
1447 1446
1448 if (Rest.DEBUG && prfxlen < path.Length-1) 1447 if (Rest.DEBUG && prfxlen < path.Length-1)
1449 { 1448 {
1450 Rest.Log.DebugFormat("{0} URI: Parameters: {1}", MsgId, path.Substring(prfxlen)); 1449 Rest.Log.DebugFormat("{0} URI: Parameters: {1}", MsgId, path.Substring(prfxlen));
1451 for (int i = 0; i < parameters.Length; i++) 1450 for (int i = 0; i < parameters.Length; i++)
1452 { 1451 {
1453 Rest.Log.DebugFormat("{0} Parameter[{1}]: {2}", MsgId, i, parameters[i]); 1452 Rest.Log.DebugFormat("{0} Parameter[{1}]: {2}", MsgId, i, parameters[i]);
1454 } 1453 }
1455 } 1454 }
diff --git a/OpenSim/ApplicationPlugins/Rest/Inventory/Rest.cs b/OpenSim/ApplicationPlugins/Rest/Inventory/Rest.cs
index fa22481..19bf381 100644
--- a/OpenSim/ApplicationPlugins/Rest/Inventory/Rest.cs
+++ b/OpenSim/ApplicationPlugins/Rest/Inventory/Rest.cs
@@ -23,7 +23,7 @@
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 * 26 *
27 */ 27 */
28 28
29using System; 29using System;
@@ -38,11 +38,9 @@ using Nini.Config;
38 38
39namespace OpenSim.ApplicationPlugins.Rest.Inventory 39namespace OpenSim.ApplicationPlugins.Rest.Inventory
40{ 40{
41
42 public class Rest 41 public class Rest
43 { 42 {
44 43 internal static readonly log4net.ILog Log =
45 internal static readonly log4net.ILog Log =
46 log4net.LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 44 log4net.LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
47 45
48 internal static bool DEBUG = Log.IsDebugEnabled; 46 internal static bool DEBUG = Log.IsDebugEnabled;
@@ -77,7 +75,7 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
77 /// HTTP requires that status information be generated for PUT 75 /// HTTP requires that status information be generated for PUT
78 /// and POST opertaions. This is in support of that. The 76 /// and POST opertaions. This is in support of that. The
79 /// operation verb gets substituted into the first string, 77 /// operation verb gets substituted into the first string,
80 /// and the completion code is inserted into the tail. The 78 /// and the completion code is inserted into the tail. The
81 /// strings are put here to encourage consistency. 79 /// strings are put here to encourage consistency.
82 /// </summary> 80 /// </summary>
83 81
@@ -88,7 +86,7 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
88 86
89 static Rest() 87 static Rest()
90 { 88 {
91 HttpStatusDesc = new Dictionary<int,string>(); 89 HttpStatusDesc = new Dictionary<int,string>();
92 if (HttpStatusCodeArray.Length != HttpStatusDescArray.Length) 90 if (HttpStatusCodeArray.Length != HttpStatusDescArray.Length)
93 { 91 {
94 Log.ErrorFormat("{0} HTTP Status Code and Description arrays do not match"); 92 Log.ErrorFormat("{0} HTTP Status Code and Description arrays do not match");
@@ -143,7 +141,7 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
143 /// supported by all servers. See Respond 141 /// supported by all servers. See Respond
144 /// to see how these are handled. 142 /// to see how these are handled.
145 /// </summary> 143 /// </summary>
146 144
147 // REST AGENT 1.0 interpretations 145 // REST AGENT 1.0 interpretations
148 public const string GET = "get"; // information retrieval - server state unchanged 146 public const string GET = "get"; // information retrieval - server state unchanged
149 public const string HEAD = "head"; // same as get except only the headers are returned. 147 public const string HEAD = "head"; // same as get except only the headers are returned.
@@ -175,7 +173,7 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
175 public static readonly char C_PERIOD = '.'; 173 public static readonly char C_PERIOD = '.';
176 public static readonly char C_COMMA = ','; 174 public static readonly char C_COMMA = ',';
177 public static readonly char C_DQUOTE = '"'; 175 public static readonly char C_DQUOTE = '"';
178 176
179 public static readonly string CS_SPACE = " "; 177 public static readonly string CS_SPACE = " ";
180 public static readonly string CS_SLASH = "/"; 178 public static readonly string CS_SLASH = "/";
181 public static readonly string CS_PATHSEP = "/"; 179 public static readonly string CS_PATHSEP = "/";
@@ -184,7 +182,7 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
184 public static readonly string CS_PERIOD = "."; 182 public static readonly string CS_PERIOD = ".";
185 public static readonly string CS_COMMA = ","; 183 public static readonly string CS_COMMA = ",";
186 public static readonly string CS_DQUOTE = "\""; 184 public static readonly string CS_DQUOTE = "\"";
187 185
188 public static readonly char[] CA_SPACE = { C_SPACE }; 186 public static readonly char[] CA_SPACE = { C_SPACE };
189 public static readonly char[] CA_SLASH = { C_SLASH }; 187 public static readonly char[] CA_SLASH = { C_SLASH };
190 public static readonly char[] CA_PATHSEP = { C_PATHSEP }; 188 public static readonly char[] CA_PATHSEP = { C_PATHSEP };
@@ -392,7 +390,7 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
392 public const string AS_DIGEST = "Digest"; 390 public const string AS_DIGEST = "Digest";
393 391
394 /// Supported Digest algorithms 392 /// Supported Digest algorithms
395 393
396 public const string Digest_MD5 = "MD5"; // assumedd efault if omitted 394 public const string Digest_MD5 = "MD5"; // assumedd efault if omitted
397 public const string Digest_MD5Sess = "MD5-sess"; 395 public const string Digest_MD5Sess = "MD5-sess";
398 396
@@ -440,7 +438,7 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
440 int val = 0; 438 int val = 0;
441 int sum = 0; 439 int sum = 0;
442 string tmp = null; 440 string tmp = null;
443 441
444 if (hex != null) 442 if (hex != null)
445 { 443 {
446 tmp = hex.ToLower(); 444 tmp = hex.ToLower();
@@ -455,7 +453,6 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
455 } 453 }
456 454
457 return sum; 455 return sum;
458
459 } 456 }
460 457
461 // Nonce management 458 // Nonce management
@@ -465,17 +462,15 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
465 return StringToBase64(CreationDate + Guid.NewGuid().ToString()); 462 return StringToBase64(CreationDate + Guid.NewGuid().ToString());
466 } 463 }
467 464
468 // Dump he specified data stream; 465 // Dump the specified data stream
469 466
470 public static void Dump(byte[] data) 467 public static void Dump(byte[] data)
471 { 468 {
472
473 char[] buffer = new char[Rest.DumpLineSize]; 469 char[] buffer = new char[Rest.DumpLineSize];
474 int cc = 0; 470 int cc = 0;
475 471
476 for (int i = 0; i < data.Length; i++) 472 for (int i = 0; i < data.Length; i++)
477 { 473 {
478
479 if (i % Rest.DumpLineSize == 0) Console.Write("\n{0}: ",i.ToString("d8")); 474 if (i % Rest.DumpLineSize == 0) Console.Write("\n{0}: ",i.ToString("d8"));
480 475
481 if (i % 4 == 0) Console.Write(" "); 476 if (i % 4 == 0) Console.Write(" ");
@@ -494,7 +489,6 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
494 Console.Write(" |"+(new String(buffer))+"|"); 489 Console.Write(" |"+(new String(buffer))+"|");
495 cc = 0; 490 cc = 0;
496 } 491 }
497
498 } 492 }
499 493
500 // Finish off any incomplete line 494 // Finish off any incomplete line
@@ -504,33 +498,29 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
504 for (int i = cc ; i < Rest.DumpLineSize; i++) 498 for (int i = cc ; i < Rest.DumpLineSize; i++)
505 { 499 {
506 if (i % 4 == 0) Console.Write(" "); 500 if (i % 4 == 0) Console.Write(" ");
507 Console.Write(" "); 501 Console.Write(" ");
508 buffer[i % Rest.DumpLineSize] = ' '; 502 buffer[i % Rest.DumpLineSize] = ' ';
509 } 503 }
510 Console.WriteLine(" |"+(new String(buffer))+"|"); 504 Console.WriteLine(" |"+(new String(buffer))+"|");
511 } 505 }
512 else 506 else
513 { 507 {
514 Console.Write("\n"); 508 Console.Write("\n");
515 } 509 }
516
517 } 510 }
518
519 } 511 }
520 512
521 // Local exception type 513 // Local exception type
522 514
523 public class RestException : Exception 515 public class RestException : Exception
524 { 516 {
525
526 internal int statusCode; 517 internal int statusCode;
527 internal string statusDesc; 518 internal string statusDesc;
528 internal string httpmethod; 519 internal string httpmethod;
529 internal string httppath; 520 internal string httppath;
530 521
531 public RestException(string msg) : base(msg) 522 public RestException(string msg) : base(msg)
532 { 523 {
533 } 524 }
534 } 525 }
535
536} 526}
diff --git a/OpenSim/ApplicationPlugins/Rest/Inventory/RestAssetServices.cs b/OpenSim/ApplicationPlugins/Rest/Inventory/RestAssetServices.cs
index 6b802d3..1b94741 100644
--- a/OpenSim/ApplicationPlugins/Rest/Inventory/RestAssetServices.cs
+++ b/OpenSim/ApplicationPlugins/Rest/Inventory/RestAssetServices.cs
@@ -23,7 +23,6 @@
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 *
27 */ 26 */
28 27
29using libsecondlife; 28using libsecondlife;
@@ -40,10 +39,8 @@ using OpenSim.Framework.Communications.Cache;
40 39
41namespace OpenSim.ApplicationPlugins.Rest.Inventory 40namespace OpenSim.ApplicationPlugins.Rest.Inventory
42{ 41{
43
44 public class RestAssetServices : IRest 42 public class RestAssetServices : IRest
45 { 43 {
46
47 private bool enabled = false; 44 private bool enabled = false;
48 private string qPrefix = "assets"; 45 private string qPrefix = "assets";
49 46
@@ -52,7 +49,6 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
52 49
53 public RestAssetServices() 50 public RestAssetServices()
54 { 51 {
55
56 Rest.Log.InfoFormat("{0} Asset services initializing", MsgId); 52 Rest.Log.InfoFormat("{0} Asset services initializing", MsgId);
57 Rest.Log.InfoFormat("{0} Using REST Implementation Version {1}", MsgId, Rest.Version); 53 Rest.Log.InfoFormat("{0} Using REST Implementation Version {1}", MsgId, Rest.Version);
58 54
@@ -73,7 +69,6 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
73 enabled = true; 69 enabled = true;
74 70
75 Rest.Log.InfoFormat("{0} Asset services initialization complete", MsgId); 71 Rest.Log.InfoFormat("{0} Asset services initialization complete", MsgId);
76
77 } 72 }
78 73
79 // Post-construction, pre-enabled initialization opportunity 74 // Post-construction, pre-enabled initialization opportunity
@@ -84,7 +79,7 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
84 } 79 }
85 80
86 // Called by the plug-in to halt REST processing. Local processing is 81 // Called by the plug-in to halt REST processing. Local processing is
87 // disabled, and control blocks until all current processing has 82 // disabled, and control blocks until all current processing has
88 // completed. No new processing will be started 83 // completed. No new processing will be started
89 84
90 public void Close() 85 public void Close()
@@ -111,14 +106,13 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
111 106
112 private void DoAsset(RequestData rparm) 107 private void DoAsset(RequestData rparm)
113 { 108 {
114
115 if (!enabled) return; 109 if (!enabled) return;
116 110
117 AssetRequestData rdata = (AssetRequestData) rparm; 111 AssetRequestData rdata = (AssetRequestData) rparm;
118 112
119 Rest.Log.DebugFormat("{0} REST Asset handler ENTRY", MsgId); 113 Rest.Log.DebugFormat("{0} REST Asset handler ENTRY", MsgId);
120 114
121 // Now that we know this is a serious attempt to 115 // Now that we know this is a serious attempt to
122 // access inventory data, we should find out who 116 // access inventory data, we should find out who
123 // is asking, and make sure they are authorized 117 // is asking, and make sure they are authorized
124 // to do so. We need to validate the caller's 118 // to do so. We need to validate the caller's
@@ -129,9 +123,9 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
129 // With the present HTTP server we can't use the 123 // With the present HTTP server we can't use the
130 // builtin authentication mechanisms because they 124 // builtin authentication mechanisms because they
131 // would be enforced for all in-bound requests. 125 // would be enforced for all in-bound requests.
132 // Instead we look at the headers ourselves and 126 // Instead we look at the headers ourselves and
133 // handle authentication directly. 127 // handle authentication directly.
134 128
135 try 129 try
136 { 130 {
137 if (!rdata.IsAuthenticated) 131 if (!rdata.IsAuthenticated)
@@ -144,13 +138,13 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
144 if (e.statusCode == Rest.HttpStatusCodeNotAuthorized) 138 if (e.statusCode == Rest.HttpStatusCodeNotAuthorized)
145 { 139 {
146 Rest.Log.WarnFormat("{0} User not authenticated", MsgId); 140 Rest.Log.WarnFormat("{0} User not authenticated", MsgId);
147 Rest.Log.DebugFormat("{0} Authorization header: {1}", MsgId, 141 Rest.Log.DebugFormat("{0} Authorization header: {1}", MsgId,
148 rdata.request.Headers.Get("Authorization")); 142 rdata.request.Headers.Get("Authorization"));
149 } 143 }
150 else 144 else
151 { 145 {
152 Rest.Log.ErrorFormat("{0} User authentication failed", MsgId); 146 Rest.Log.ErrorFormat("{0} User authentication failed", MsgId);
153 Rest.Log.DebugFormat("{0} Authorization header: {1}", MsgId, 147 Rest.Log.DebugFormat("{0} Authorization header: {1}", MsgId,
154 rdata.request.Headers.Get("Authorization")); 148 rdata.request.Headers.Get("Authorization"));
155 } 149 }
156 throw (e); 150 throw (e);
@@ -173,7 +167,7 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
173 case "post" : 167 case "post" :
174 case "delete" : 168 case "delete" :
175 default : 169 default :
176 Rest.Log.WarnFormat("{0} Asset: Method not supported: {1}", 170 Rest.Log.WarnFormat("{0} Asset: Method not supported: {1}",
177 MsgId, rdata.method); 171 MsgId, rdata.method);
178 rdata.Fail(Rest.HttpStatusCodeBadRequest,String.Format("method <{0}> not supported", rdata.method)); 172 rdata.Fail(Rest.HttpStatusCodeBadRequest,String.Format("method <{0}> not supported", rdata.method));
179 break; 173 break;
@@ -186,14 +180,12 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
186 } 180 }
187 181
188 Rest.Log.DebugFormat("{0} REST Asset handler EXIT", MsgId); 182 Rest.Log.DebugFormat("{0} REST Asset handler EXIT", MsgId);
189
190 } 183 }
191 184
192 #endregion Interface 185 #endregion Interface
193 186
194 private void DoGet(AssetRequestData rdata) 187 private void DoGet(AssetRequestData rdata)
195 { 188 {
196
197 bool istexture = false; 189 bool istexture = false;
198 190
199 Rest.Log.DebugFormat("{0} REST Asset handler, Method = <{1}> ENTRY", MsgId, rdata.method); 191 Rest.Log.DebugFormat("{0} REST Asset handler, Method = <{1}> ENTRY", MsgId, rdata.method);
@@ -203,13 +195,11 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
203 195
204 if (rdata.Parameters.Length == 1) 196 if (rdata.Parameters.Length == 1)
205 { 197 {
206
207 LLUUID uuid = new LLUUID(rdata.Parameters[0]); 198 LLUUID uuid = new LLUUID(rdata.Parameters[0]);
208 AssetBase asset = Rest.AssetServices.GetAsset(uuid, istexture); 199 AssetBase asset = Rest.AssetServices.GetAsset(uuid, istexture);
209 200
210 if (asset != null) 201 if (asset != null)
211 { 202 {
212
213 Rest.Log.DebugFormat("{0} Asset located <{1}>", MsgId, rdata.Parameters[0]); 203 Rest.Log.DebugFormat("{0} Asset located <{1}>", MsgId, rdata.Parameters[0]);
214 204
215 rdata.initXmlWriter(); 205 rdata.initXmlWriter();
@@ -237,7 +227,6 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
237 227
238 rdata.Complete(); 228 rdata.Complete();
239 rdata.Respond("Asset " + rdata.method + ": Normal completion"); 229 rdata.Respond("Asset " + rdata.method + ": Normal completion");
240
241 } 230 }
242 231
243 private void DoPut(AssetRequestData rdata) 232 private void DoPut(AssetRequestData rdata)
@@ -255,7 +244,7 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
255 if (!xml.ReadToFollowing("Asset")) 244 if (!xml.ReadToFollowing("Asset"))
256 { 245 {
257 Rest.Log.DebugFormat("{0} Invalid request data: <{1}>", MsgId, rdata.path); 246 Rest.Log.DebugFormat("{0} Invalid request data: <{1}>", MsgId, rdata.path);
258 rdata.Fail(Rest.HttpStatusCodeBadRequest,"invalid request data"); 247 rdata.Fail(Rest.HttpStatusCodeBadRequest,"invalid request data");
259 } 248 }
260 249
261 AssetBase asset = new AssetBase(); 250 AssetBase asset = new AssetBase();
@@ -272,12 +261,11 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
272 else 261 else
273 { 262 {
274 Rest.Log.DebugFormat("{0} Invalid parameters: <{1}>", MsgId, rdata.path); 263 Rest.Log.DebugFormat("{0} Invalid parameters: <{1}>", MsgId, rdata.path);
275 rdata.Fail(Rest.HttpStatusCodeNotFound, "invalid parameters"); 264 rdata.Fail(Rest.HttpStatusCodeNotFound, "invalid parameters");
276 } 265 }
277 266
278 rdata.Complete(); 267 rdata.Complete();
279 rdata.Respond("Asset " + rdata.method + ": Normal completion"); 268 rdata.Respond("Asset " + rdata.method + ": Normal completion");
280
281 } 269 }
282 270
283 internal class AssetRequestData : RequestData 271 internal class AssetRequestData : RequestData
@@ -287,6 +275,5 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
287 { 275 {
288 } 276 }
289 } 277 }
290
291 } 278 }
292} 279}
diff --git a/OpenSim/ApplicationPlugins/Rest/Inventory/RestHandler.cs b/OpenSim/ApplicationPlugins/Rest/Inventory/RestHandler.cs
index 61cf0e4..ab6128f 100644
--- a/OpenSim/ApplicationPlugins/Rest/Inventory/RestHandler.cs
+++ b/OpenSim/ApplicationPlugins/Rest/Inventory/RestHandler.cs
@@ -23,7 +23,6 @@
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 *
27 */ 26 */
28 27
29using System; 28using System;
@@ -35,7 +34,6 @@ using OpenSim.ApplicationPlugins.Rest;
35 34
36namespace OpenSim.ApplicationPlugins.Rest.Inventory 35namespace OpenSim.ApplicationPlugins.Rest.Inventory
37{ 36{
38
39 /// <remarks> 37 /// <remarks>
40 /// The class signature reveals the roles that RestHandler plays. 38 /// The class signature reveals the roles that RestHandler plays.
41 /// 39 ///
@@ -74,10 +72,10 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
74 /// <summary> 72 /// <summary>
75 /// This static initializer scans the ASSEMBLY for classes that 73 /// This static initializer scans the ASSEMBLY for classes that
76 /// export the IRest interface and builds a list of them. These 74 /// export the IRest interface and builds a list of them. These
77 /// are later activated by the handler. To add a new handler it 75 /// are later activated by the handler. To add a new handler it
78 /// is only necessary to create a new services class that implements 76 /// is only necessary to create a new services class that implements
79 /// the IRest interface, and recompile the handler. This gives 77 /// the IRest interface, and recompile the handler. This gives
80 /// all of the build-time flexibility of a modular approach 78 /// all of the build-time flexibility of a modular approach
81 /// while not introducing yet-another module loader. Note that 79 /// while not introducing yet-another module loader. Note that
82 /// multiple assembles can still be built, each with its own set 80 /// multiple assembles can still be built, each with its own set
83 /// of handlers. Examples of services classes are RestInventoryServices 81 /// of handlers. Examples of services classes are RestInventoryServices
@@ -86,13 +84,12 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
86 84
87 static RestHandler() 85 static RestHandler()
88 { 86 {
89
90 Module[] mods = Assembly.GetExecutingAssembly().GetModules(); 87 Module[] mods = Assembly.GetExecutingAssembly().GetModules();
91 88
92 foreach (Module m in mods) 89 foreach (Module m in mods)
93 { 90 {
94 Type[] types = m.GetTypes(); 91 Type[] types = m.GetTypes();
95 foreach (Type t in types) 92 foreach (Type t in types)
96 { 93 {
97 try 94 try
98 { 95 {
@@ -108,7 +105,6 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
108 } 105 }
109 } 106 }
110 } 107 }
111
112 } 108 }
113 109
114 #endregion local static state 110 #endregion local static state
@@ -117,13 +113,13 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
117 113
118 /// <summary> 114 /// <summary>
119 /// This routine loads all of the handlers discovered during 115 /// This routine loads all of the handlers discovered during
120 /// instance initialization. 116 /// instance initialization.
121 /// A table of all loaded and successfully constructed handlers 117 /// A table of all loaded and successfully constructed handlers
122 /// is built, and this table is then used by the constructor to 118 /// is built, and this table is then used by the constructor to
123 /// initialize each of the handlers in turn. 119 /// initialize each of the handlers in turn.
124 /// NOTE: The loading process does not automatically imply that 120 /// NOTE: The loading process does not automatically imply that
125 /// the handler has registered any kind of an interface, that 121 /// the handler has registered any kind of an interface, that
126 /// may be (optionally) done by the handler either during 122 /// may be (optionally) done by the handler either during
127 /// construction, or during initialization. 123 /// construction, or during initialization.
128 /// 124 ///
129 /// I was not able to make this code work within a constructor 125 /// I was not able to make this code work within a constructor
@@ -136,7 +132,6 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
136 { 132 {
137 if (!handlersLoaded) 133 if (!handlersLoaded)
138 { 134 {
139
140 ConstructorInfo ci; 135 ConstructorInfo ci;
141 Object ht; 136 Object ht;
142 137
@@ -167,8 +162,8 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
167 162
168 // Name is used to differentiate the message header. 163 // Name is used to differentiate the message header.
169 164
170 public override string Name 165 public override string Name
171 { 166 {
172 get { return "HANDLER"; } 167 get { return "HANDLER"; }
173 } 168 }
174 169
@@ -181,7 +176,7 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
181 176
182 // We have to rename these because we want 177 // We have to rename these because we want
183 // to be able to share the values with other 178 // to be able to share the values with other
184 // classes in our assembly and the base 179 // classes in our assembly and the base
185 // names are protected. 180 // names are protected.
186 181
187 public string MsgId 182 public string MsgId
@@ -211,7 +206,6 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
211 { 206 {
212 try 207 try
213 { 208 {
214
215 // This plugin will only be enabled if the broader 209 // This plugin will only be enabled if the broader
216 // REST plugin mechanism is enabled. 210 // REST plugin mechanism is enabled.
217 211
@@ -222,7 +216,7 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
222 // IsEnabled is implemented by the base class and 216 // IsEnabled is implemented by the base class and
223 // reflects an overall RestPlugin status 217 // reflects an overall RestPlugin status
224 218
225 if (!IsEnabled) 219 if (!IsEnabled)
226 { 220 {
227 Rest.Log.WarnFormat("{0} Plugins are disabled", MsgId); 221 Rest.Log.WarnFormat("{0} Plugins are disabled", MsgId);
228 return; 222 return;
@@ -278,15 +272,15 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
278 Rest.DumpLineSize); 272 Rest.DumpLineSize);
279 } 273 }
280 274
281 // Load all of the handlers present in the 275 // Load all of the handlers present in the
282 // assembly 276 // assembly
283 277
284 // In principle, as we're an application plug-in, 278 // In principle, as we're an application plug-in,
285 // most of what needs to be done could be done using 279 // most of what needs to be done could be done using
286 // static resources, however the Open Sim plug-in 280 // static resources, however the Open Sim plug-in
287 // model makes this an instance, so that's what we 281 // model makes this an instance, so that's what we
288 // need to be. 282 // need to be.
289 // There is only one Communications manager per 283 // There is only one Communications manager per
290 // server, and by inference, only one each of the 284 // server, and by inference, only one each of the
291 // user, asset, and inventory servers. So we can cache 285 // user, asset, and inventory servers. So we can cache
292 // those using a static initializer. 286 // those using a static initializer.
@@ -329,13 +323,12 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
329 { 323 {
330 Rest.Log.ErrorFormat("{0} Plugin initialization has failed: {1}", MsgId, e.Message); 324 Rest.Log.ErrorFormat("{0} Plugin initialization has failed: {1}", MsgId, e.Message);
331 } 325 }
332
333 } 326 }
334 327
335 /// <summary> 328 /// <summary>
336 /// In the interests of efficiency, and because we cannot determine whether 329 /// In the interests of efficiency, and because we cannot determine whether
337 /// or not this instance will actually be harvested, we clobber the only 330 /// or not this instance will actually be harvested, we clobber the only
338 /// anchoring reference to the working state for this plug-in. What the 331 /// anchoring reference to the working state for this plug-in. What the
339 /// call to close does is irrelevant to this class beyond knowing that it 332 /// call to close does is irrelevant to this class beyond knowing that it
340 /// can nullify the reference when it returns. 333 /// can nullify the reference when it returns.
341 /// To make sure everything is copacetic we make sure the primary interface 334 /// To make sure everything is copacetic we make sure the primary interface
@@ -344,7 +337,6 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
344 337
345 public override void Close() 338 public override void Close()
346 { 339 {
347
348 Rest.Log.InfoFormat("{0} Plugin is terminating", MsgId); 340 Rest.Log.InfoFormat("{0} Plugin is terminating", MsgId);
349 341
350 try 342 try
@@ -352,12 +344,11 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
352 RemoveAgentHandler(Rest.Name, this); 344 RemoveAgentHandler(Rest.Name, this);
353 } 345 }
354 catch (KeyNotFoundException){} 346 catch (KeyNotFoundException){}
355 347
356 foreach (IRest handler in handlers) 348 foreach (IRest handler in handlers)
357 { 349 {
358 handler.Close(); 350 handler.Close();
359 } 351 }
360
361 } 352 }
362 353
363 #endregion overriding methods 354 #endregion overriding methods
@@ -383,7 +374,7 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
383 foreach (string key in pathHandlers.Keys) 374 foreach (string key in pathHandlers.Keys)
384 { 375 {
385 Rest.Log.DebugFormat("{0} Match testing {1} against agent prefix <{2}>", MsgId, path, key); 376 Rest.Log.DebugFormat("{0} Match testing {1} against agent prefix <{2}>", MsgId, path, key);
386 377
387 // Note that Match will not necessarily find the handler that will 378 // Note that Match will not necessarily find the handler that will
388 // actually be used - it does no test for the "closest" fit. It 379 // actually be used - it does no test for the "closest" fit. It
389 // simply reflects that at least one possible handler exists. 380 // simply reflects that at least one possible handler exists.
@@ -393,7 +384,7 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
393 Rest.Log.DebugFormat("{0} Matched prefix <{1}>", MsgId, key); 384 Rest.Log.DebugFormat("{0} Matched prefix <{1}>", MsgId, key);
394 385
395 // This apparently odd evaluation is needed to prevent a match 386 // This apparently odd evaluation is needed to prevent a match
396 // on anything other than a URI token boundary. Otherwise we 387 // on anything other than a URI token boundary. Otherwise we
397 // may match on URL's that were not intended for this handler. 388 // may match on URL's that were not intended for this handler.
398 389
399 return ( path.Length == key.Length || 390 return ( path.Length == key.Length ||
@@ -406,9 +397,8 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
406 397
407 foreach (string key in streamHandlers.Keys) 398 foreach (string key in streamHandlers.Keys)
408 { 399 {
409
410 Rest.Log.DebugFormat("{0} Match testing {1} against stream prefix <{2}>", MsgId, path, key); 400 Rest.Log.DebugFormat("{0} Match testing {1} against stream prefix <{2}>", MsgId, path, key);
411 401
412 // Note that Match will not necessarily find the handler that will 402 // Note that Match will not necessarily find the handler that will
413 // actually be used - it does no test for the "closest" fit. It 403 // actually be used - it does no test for the "closest" fit. It
414 // simply reflects that at least one possible handler exists. 404 // simply reflects that at least one possible handler exists.
@@ -418,7 +408,7 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
418 Rest.Log.DebugFormat("{0} Matched prefix <{1}>", MsgId, key); 408 Rest.Log.DebugFormat("{0} Matched prefix <{1}>", MsgId, key);
419 409
420 // This apparently odd evaluation is needed to prevent a match 410 // This apparently odd evaluation is needed to prevent a match
421 // on anything other than a URI token boundary. Otherwise we 411 // on anything other than a URI token boundary. Otherwise we
422 // may match on URL's that were not intended for this handler. 412 // may match on URL's that were not intended for this handler.
423 413
424 return ( path.Length == key.Length || 414 return ( path.Length == key.Length ||
@@ -426,7 +416,6 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
426 416
427 } 417 }
428 } 418 }
429
430 } 419 }
431 catch (Exception e) 420 catch (Exception e)
432 { 421 {
@@ -460,7 +449,7 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
460 449
461 for (int i = 0; i < request.Headers.Count; i++) 450 for (int i = 0; i < request.Headers.Count; i++)
462 { 451 {
463 Rest.Log.DebugFormat("{0} Header [{1}] : <{2}> = <{3}>", 452 Rest.Log.DebugFormat("{0} Header [{1}] : <{2}> = <{3}>",
464 MsgId, i, request.Headers.GetKey(i), request.Headers.Get(i)); 453 MsgId, i, request.Headers.GetKey(i), request.Headers.Get(i));
465 } 454 }
466 Rest.Log.DebugFormat("{0} URI: {1}", MsgId, request.RawUrl); 455 Rest.Log.DebugFormat("{0} URI: {1}", MsgId, request.RawUrl);
@@ -486,7 +475,6 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
486 Rest.Log.DebugFormat("{0} EXIT", MsgId); 475 Rest.Log.DebugFormat("{0} EXIT", MsgId);
487 476
488 return handled; 477 return handled;
489
490 } 478 }
491 479
492 #endregion interface methods 480 #endregion interface methods
@@ -534,7 +522,6 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
534 } 522 }
535 523
536 return rdata.handled; 524 return rdata.handled;
537
538 } 525 }
539 526
540 /// <summary> 527 /// <summary>
@@ -547,13 +534,12 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
547 534
548 public void AddStreamHandler(string httpMethod, string path, RestMethod method) 535 public void AddStreamHandler(string httpMethod, string path, RestMethod method)
549 { 536 {
550
551 if (!IsEnabled) 537 if (!IsEnabled)
552 { 538 {
553 return; 539 return;
554 } 540 }
555 541
556 if (!path.StartsWith(Rest.Prefix)) 542 if (!path.StartsWith(Rest.Prefix))
557 { 543 {
558 path = String.Format("{0}{1}", Rest.Prefix, path); 544 path = String.Format("{0}{1}", Rest.Prefix, path);
559 } 545 }
@@ -571,7 +557,6 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
571 { 557 {
572 Rest.Log.WarnFormat("{0} Ignoring duplicate handler for {1}", MsgId, path); 558 Rest.Log.WarnFormat("{0} Ignoring duplicate handler for {1}", MsgId, path);
573 } 559 }
574
575 } 560 }
576 561
577 /// <summary> 562 /// <summary>
@@ -586,10 +571,9 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
586 571
587 internal bool FindPathHandler(OSHttpRequest request, OSHttpResponse response) 572 internal bool FindPathHandler(OSHttpRequest request, OSHttpResponse response)
588 { 573 {
589
590 RequestData rdata = null; 574 RequestData rdata = null;
591 string bestMatch = null; 575 string bestMatch = null;
592 576
593 if (!IsEnabled) 577 if (!IsEnabled)
594 { 578 {
595 return false; 579 return false;
@@ -612,7 +596,6 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
612 596
613 if (!String.IsNullOrEmpty(bestMatch)) 597 if (!String.IsNullOrEmpty(bestMatch))
614 { 598 {
615
616 rdata = pathAllocators[bestMatch](request, response, bestMatch); 599 rdata = pathAllocators[bestMatch](request, response, bestMatch);
617 600
618 Rest.Log.DebugFormat("{0} Path based REST handler matched with <{1}>", MsgId, bestMatch); 601 Rest.Log.DebugFormat("{0} Path based REST handler matched with <{1}>", MsgId, bestMatch);
@@ -621,7 +604,7 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
621 { 604 {
622 pathHandlers[bestMatch](rdata); 605 pathHandlers[bestMatch](rdata);
623 } 606 }
624 607
625 // A plugin generated error indicates a request-related error 608 // A plugin generated error indicates a request-related error
626 // that has been handled by the plugin. 609 // that has been handled by the plugin.
627 610
@@ -629,11 +612,9 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
629 { 612 {
630 Rest.Log.WarnFormat("{0} Request failed: {1}", MsgId, r.Message); 613 Rest.Log.WarnFormat("{0} Request failed: {1}", MsgId, r.Message);
631 } 614 }
632
633 } 615 }
634 616
635 return (rdata == null) ? false : rdata.handled; 617 return (rdata == null) ? false : rdata.handled;
636
637 } 618 }
638 619
639 /// <summary> 620 /// <summary>
@@ -643,7 +624,6 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
643 624
644 public void AddPathHandler(RestMethodHandler mh, string path, RestMethodAllocator ra) 625 public void AddPathHandler(RestMethodHandler mh, string path, RestMethodAllocator ra)
645 { 626 {
646
647 if (!IsEnabled) 627 if (!IsEnabled)
648 { 628 {
649 return; 629 return;
@@ -665,8 +645,6 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
665 645
666 pathHandlers.Add(path, mh); 646 pathHandlers.Add(path, mh);
667 pathAllocators.Add(path, ra); 647 pathAllocators.Add(path, ra);
668
669 } 648 }
670 } 649 }
671
672} 650}
diff --git a/OpenSim/ApplicationPlugins/Rest/Inventory/RestInventoryServices.cs b/OpenSim/ApplicationPlugins/Rest/Inventory/RestInventoryServices.cs
index 1ea598e..82e9a13 100644
--- a/OpenSim/ApplicationPlugins/Rest/Inventory/RestInventoryServices.cs
+++ b/OpenSim/ApplicationPlugins/Rest/Inventory/RestInventoryServices.cs
@@ -23,7 +23,6 @@
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 *
27 */ 26 */
28 27
29using System; 28using System;
@@ -42,11 +41,9 @@ using Nini.Config;
42 41
43namespace OpenSim.ApplicationPlugins.Rest.Inventory 42namespace OpenSim.ApplicationPlugins.Rest.Inventory
44{ 43{
45
46 public class RestInventoryServices : IRest 44 public class RestInventoryServices : IRest
47 { 45 {
48 46 private static readonly int PARM_USERID = 0;
49 private static readonly int PARM_USERID = 0;
50 private static readonly int PARM_PATH = 1; 47 private static readonly int PARM_PATH = 1;
51 48
52 private bool enabled = false; 49 private bool enabled = false;
@@ -61,11 +58,10 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
61 58
62 public RestInventoryServices() 59 public RestInventoryServices()
63 { 60 {
64
65 Rest.Log.InfoFormat("{0} Inventory services initializing", MsgId); 61 Rest.Log.InfoFormat("{0} Inventory services initializing", MsgId);
66 Rest.Log.InfoFormat("{0} Using REST Implementation Version {1}", MsgId, Rest.Version); 62 Rest.Log.InfoFormat("{0} Using REST Implementation Version {1}", MsgId, Rest.Version);
67 63
68 // If a relative path was specified for the handler's domain, 64 // If a relative path was specified for the handler's domain,
69 // add the standard prefix to make it absolute, e.g. /admin 65 // add the standard prefix to make it absolute, e.g. /admin
70 66
71 if (!qPrefix.StartsWith(Rest.UrlPathSeparator)) 67 if (!qPrefix.StartsWith(Rest.UrlPathSeparator))
@@ -82,7 +78,6 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
82 enabled = true; 78 enabled = true;
83 79
84 Rest.Log.InfoFormat("{0} Inventory services initialization complete", MsgId); 80 Rest.Log.InfoFormat("{0} Inventory services initialization complete", MsgId);
85
86 } 81 }
87 82
88 /// <summary> 83 /// <summary>
@@ -143,7 +138,6 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
143 138
144 private void DoInventory(RequestData hdata) 139 private void DoInventory(RequestData hdata)
145 { 140 {
146
147 InventoryRequestData rdata = (InventoryRequestData) hdata; 141 InventoryRequestData rdata = (InventoryRequestData) hdata;
148 142
149 Rest.Log.DebugFormat("{0} DoInventory ENTRY", MsgId); 143 Rest.Log.DebugFormat("{0} DoInventory ENTRY", MsgId);
@@ -155,7 +149,7 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
155 return; 149 return;
156 } 150 }
157 151
158 // Now that we know this is a serious attempt to 152 // Now that we know this is a serious attempt to
159 // access inventory data, we should find out who 153 // access inventory data, we should find out who
160 // is asking, and make sure they are authorized 154 // is asking, and make sure they are authorized
161 // to do so. We need to validate the caller's 155 // to do so. We need to validate the caller's
@@ -166,9 +160,9 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
166 // With the present HTTP server we can't use the 160 // With the present HTTP server we can't use the
167 // builtin authentication mechanisms because they 161 // builtin authentication mechanisms because they
168 // would be enforced for all in-bound requests. 162 // would be enforced for all in-bound requests.
169 // Instead we look at the headers ourselves and 163 // Instead we look at the headers ourselves and
170 // handle authentication directly. 164 // handle authentication directly.
171 165
172 try 166 try
173 { 167 {
174 if (!rdata.IsAuthenticated) 168 if (!rdata.IsAuthenticated)
@@ -205,7 +199,7 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
205 // 199 //
206 // Indicating that this is an inventory request for 200 // Indicating that this is an inventory request for
207 // an avatar named Arthur Dent. This is ALL that is 201 // an avatar named Arthur Dent. This is ALL that is
208 // required to designate a GET for an entire 202 // required to designate a GET for an entire
209 // inventory. 203 // inventory.
210 // 204 //
211 // Do we have at least a user agent name? 205 // Do we have at least a user agent name?
@@ -247,7 +241,7 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
247 241
248 if (rdata.userProfile != null) 242 if (rdata.userProfile != null)
249 { 243 {
250 Rest.Log.DebugFormat("{0} Profile obtained for agent {1} {2}", 244 Rest.Log.DebugFormat("{0} Profile obtained for agent {1} {2}",
251 MsgId, rdata.userProfile.FirstName, rdata.userProfile.SurName); 245 MsgId, rdata.userProfile.FirstName, rdata.userProfile.SurName);
252 } 246 }
253 else 247 else
@@ -269,18 +263,17 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
269 // response is not recieved in a timely fashion. 263 // response is not recieved in a timely fashion.
270 264
271 rdata.uuid = rdata.userProfile.ID; 265 rdata.uuid = rdata.userProfile.ID;
272 266
273 if (Rest.InventoryServices.HasInventoryForUser(rdata.uuid)) 267 if (Rest.InventoryServices.HasInventoryForUser(rdata.uuid))
274 { 268 {
275
276 rdata.root = Rest.InventoryServices.RequestRootFolder(rdata.uuid); 269 rdata.root = Rest.InventoryServices.RequestRootFolder(rdata.uuid);
277 270
278 Rest.Log.DebugFormat("{0} Inventory Root retrieved for {1} {2}", 271 Rest.Log.DebugFormat("{0} Inventory Root retrieved for {1} {2}",
279 MsgId, rdata.userProfile.FirstName, rdata.userProfile.SurName); 272 MsgId, rdata.userProfile.FirstName, rdata.userProfile.SurName);
280 273
281 Rest.InventoryServices.RequestInventoryForUser(rdata.uuid, rdata.GetUserInventory); 274 Rest.InventoryServices.RequestInventoryForUser(rdata.uuid, rdata.GetUserInventory);
282 275
283 Rest.Log.DebugFormat("{0} Inventory catalog requested for {1} {2}", 276 Rest.Log.DebugFormat("{0} Inventory catalog requested for {1} {2}",
284 MsgId, rdata.userProfile.FirstName, rdata.userProfile.SurName); 277 MsgId, rdata.userProfile.FirstName, rdata.userProfile.SurName);
285 278
286 lock (rdata) 279 lock (rdata)
@@ -293,7 +286,7 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
293 286
294 if (rdata.root == null) 287 if (rdata.root == null)
295 { 288 {
296 Rest.Log.WarnFormat("{0} Inventory is not available [1] for agent {1} {2}", 289 Rest.Log.WarnFormat("{0} Inventory is not available [1] for agent {1} {2}",
297 MsgId, rdata.userProfile.FirstName, rdata.userProfile.SurName); 290 MsgId, rdata.userProfile.FirstName, rdata.userProfile.SurName);
298 rdata.Fail(Rest.HttpStatusCodeServerError, "inventory retrieval failed"); 291 rdata.Fail(Rest.HttpStatusCodeServerError, "inventory retrieval failed");
299 } 292 }
@@ -301,7 +294,7 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
301 } 294 }
302 else 295 else
303 { 296 {
304 Rest.Log.WarnFormat("{0} Inventory is not locally available for agent {1} {2}", 297 Rest.Log.WarnFormat("{0} Inventory is not locally available for agent {1} {2}",
305 MsgId, rdata.userProfile.FirstName, rdata.userProfile.SurName); 298 MsgId, rdata.userProfile.FirstName, rdata.userProfile.SurName);
306 rdata.Fail(Rest.HttpStatusCodeNotFound, "no local inventory for user"); 299 rdata.Fail(Rest.HttpStatusCodeNotFound, "no local inventory for user");
307 } 300 }
@@ -311,7 +304,6 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
311 304
312 switch (rdata.method) 305 switch (rdata.method)
313 { 306 {
314
315 case Rest.HEAD : // Do the processing, set the status code, suppress entity 307 case Rest.HEAD : // Do the processing, set the status code, suppress entity
316 DoGet(rdata); 308 DoGet(rdata);
317 rdata.buffer = null; 309 rdata.buffer = null;
@@ -334,12 +326,11 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
334 break; 326 break;
335 327
336 default : 328 default :
337 Rest.Log.WarnFormat("{0} Method {1} not supported for {2}", 329 Rest.Log.WarnFormat("{0} Method {1} not supported for {2}",
338 MsgId, rdata.method, rdata.path); 330 MsgId, rdata.method, rdata.path);
339 rdata.Fail(Rest.HttpStatusCodeMethodNotAllowed, rdata.method+" not supported"); 331 rdata.Fail(Rest.HttpStatusCodeMethodNotAllowed, rdata.method+" not supported");
340 break; 332 break;
341 } 333 }
342
343 } 334 }
344 335
345 #endregion Interface 336 #endregion Interface
@@ -355,18 +346,17 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
355 346
356 private void DoGet(InventoryRequestData rdata) 347 private void DoGet(InventoryRequestData rdata)
357 { 348 {
358
359 rdata.initXmlWriter(); 349 rdata.initXmlWriter();
360 350
361 rdata.writer.WriteStartElement(String.Empty,"Inventory",String.Empty); 351 rdata.writer.WriteStartElement(String.Empty,"Inventory",String.Empty);
362 352
363 // If there are additional parameters, then these represent 353 // If there are additional parameters, then these represent
364 // a path relative to the root of the inventory. This path 354 // a path relative to the root of the inventory. This path
365 // must be traversed before we format the sub-tree thus 355 // must be traversed before we format the sub-tree thus
366 // identified. 356 // identified.
367 357
368 traverse(rdata, rdata.root, PARM_PATH); 358 traverse(rdata, rdata.root, PARM_PATH);
369 359
370 // Close all open elements 360 // Close all open elements
371 361
372 rdata.writer.WriteFullEndElement(); 362 rdata.writer.WriteFullEndElement();
@@ -379,9 +369,8 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
379 // constructed from the result of the XML writer. 369 // constructed from the result of the XML writer.
380 370
381 rdata.Respond(String.Format("Inventory {0} Normal completion", rdata.method)); 371 rdata.Respond(String.Format("Inventory {0} Normal completion", rdata.method));
382
383 } 372 }
384 373
385 /// <summary> 374 /// <summary>
386 /// In the case of the inventory, and probably in general, 375 /// In the case of the inventory, and probably in general,
387 /// the distinction between PUT and POST is not always 376 /// the distinction between PUT and POST is not always
@@ -392,7 +381,7 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
392 /// consistency across different implementations. 381 /// consistency across different implementations.
393 /// 382 ///
394 /// For OpenSim PUT is an update and POST is an addition. This 383 /// For OpenSim PUT is an update and POST is an addition. This
395 /// is the behavior required by the HTTP specification and 384 /// is the behavior required by the HTTP specification and
396 /// therefore as required by REST. 385 /// therefore as required by REST.
397 /// 386 ///
398 /// The best way to explain the distinction is to 387 /// The best way to explain the distinction is to
@@ -401,53 +390,51 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
401 /// actual entity to be modified or replaced, i.e. the 390 /// actual entity to be modified or replaced, i.e. the
402 /// enclosed entity. 391 /// enclosed entity.
403 /// 392 ///
404 /// If the operation is POST,then the URI describes the 393 /// If the operation is POST,then the URI describes the
405 /// context into which the new entity will be added. 394 /// context into which the new entity will be added.
406 /// 395 ///
407 /// As an example, suppose the URI contains: 396 /// As an example, suppose the URI contains:
408 /// /admin/inventory/Clothing 397 /// /admin/inventory/Clothing
409 /// 398 ///
410 /// A PUT request will normally result in some modification of 399 /// A PUT request will normally result in some modification of
411 /// the folder or item named "Clothing". Whereas a POST 400 /// the folder or item named "Clothing". Whereas a POST
412 /// request will normally add some new information into the 401 /// request will normally add some new information into the
413 /// content identified by Clothing. It follows from this 402 /// content identified by Clothing. It follows from this
414 /// that for POST, the element identified by the URI MUST 403 /// that for POST, the element identified by the URI MUST
415 /// be a folder. 404 /// be a folder.
416 /// </summary> 405 /// </summary>
417 406
418 /// <summary> 407 /// <summary>
419 /// POST adds new information to the inventory in the 408 /// POST adds new information to the inventory in the
420 /// context identified by the URI. 409 /// context identified by the URI.
421 /// </summary> 410 /// </summary>
422 /// <param name=rdata>HTTP service request work area</param> 411 /// <param name=rdata>HTTP service request work area</param>
423 412
424 private void DoExtend(InventoryRequestData rdata) 413 private void DoExtend(InventoryRequestData rdata)
425 { 414 {
426
427 bool created = false; 415 bool created = false;
428 bool modified = false; 416 bool modified = false;
429 string newnode = String.Empty; 417 string newnode = String.Empty;
430 418
431 // Resolve the context node specified in the URI. Entity 419 // Resolve the context node specified in the URI. Entity
432 // data will be ADDED beneath this node. rdata already contains 420 // data will be ADDED beneath this node. rdata already contains
433 // information about the current content of the user's 421 // information about the current content of the user's
434 // inventory. 422 // inventory.
435 423
436 Object InventoryNode = getInventoryNode(rdata, rdata.root, PARM_PATH, Rest.Fill); 424 Object InventoryNode = getInventoryNode(rdata, rdata.root, PARM_PATH, Rest.Fill);
437 425
438 // Processing depends upon the type of inventory node 426 // Processing depends upon the type of inventory node
439 // identified in the URI. This is the CONTEXT for the 427 // identified in the URI. This is the CONTEXT for the
440 // change. We either got a context or we threw an 428 // change. We either got a context or we threw an
441 // exception. 429 // exception.
442 430
443 // It follows that we can only add information if the URI 431 // It follows that we can only add information if the URI
444 // has identified a folder. So only a type of folder is supported 432 // has identified a folder. So only a type of folder is supported
445 // in this case. 433 // in this case.
446 434
447 if (typeof(InventoryFolderBase) == InventoryNode.GetType() || 435 if (typeof(InventoryFolderBase) == InventoryNode.GetType() ||
448 typeof(InventoryFolderImpl) == InventoryNode.GetType()) 436 typeof(InventoryFolderImpl) == InventoryNode.GetType())
449 { 437 {
450
451 // Cast the context node appropriately. 438 // Cast the context node appropriately.
452 439
453 InventoryFolderBase context = (InventoryFolderBase) InventoryNode; 440 InventoryFolderBase context = (InventoryFolderBase) InventoryNode;
@@ -466,12 +453,11 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
466 XmlInventoryCollection entity = ReconstituteEntity(rdata); 453 XmlInventoryCollection entity = ReconstituteEntity(rdata);
467 454
468 // Inlined assets can be included in entity. These must be incorporated into 455 // Inlined assets can be included in entity. These must be incorporated into
469 // the asset database before we attempt to update the inventory. If anything 456 // the asset database before we attempt to update the inventory. If anything
470 // fails, return a failure to requestor. 457 // fails, return a failure to requestor.
471 458
472 if (entity.Assets.Count > 0) 459 if (entity.Assets.Count > 0)
473 { 460 {
474
475 Rest.Log.DebugFormat("{0} Adding {1} assets to server", 461 Rest.Log.DebugFormat("{0} Adding {1} assets to server",
476 MsgId, entity.Assets.Count); 462 MsgId, entity.Assets.Count);
477 463
@@ -489,9 +475,7 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
489 { 475 {
490 Rest.Dump(asset.Data); 476 Rest.Dump(asset.Data);
491 } 477 }
492
493 } 478 }
494
495 } 479 }
496 480
497 // Modify the context using the collection of folders and items 481 // Modify the context using the collection of folders and items
@@ -499,7 +483,6 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
499 483
500 foreach (InventoryFolderBase folder in entity.Folders) 484 foreach (InventoryFolderBase folder in entity.Folders)
501 { 485 {
502
503 InventoryFolderBase found; 486 InventoryFolderBase found;
504 487
505 // If the parentID is zero, then this folder is going 488 // If the parentID is zero, then this folder is going
@@ -544,7 +527,7 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
544 527
545 modified = true; 528 modified = true;
546 rdata.appendStatus(String.Format("<p> Created folder {0}, UUID {1}<p>", 529 rdata.appendStatus(String.Format("<p> Created folder {0}, UUID {1}<p>",
547 folder.Name, folder.ID)); 530 folder.Name, folder.ID));
548 } 531 }
549 else 532 else
550 { 533 {
@@ -553,10 +536,8 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
553 536
554 created = true; 537 created = true;
555 rdata.appendStatus(String.Format("<p> Modified folder {0}, UUID {1}<p>", 538 rdata.appendStatus(String.Format("<p> Modified folder {0}, UUID {1}<p>",
556 folder.Name, folder.ID)); 539 folder.Name, folder.ID));
557
558 } 540 }
559
560 } 541 }
561 542
562 // Now we repeat a similar process for the items included 543 // Now we repeat a similar process for the items included
@@ -564,7 +545,6 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
564 545
565 foreach (InventoryItemBase item in entity.Items) 546 foreach (InventoryItemBase item in entity.Items)
566 { 547 {
567
568 InventoryItemBase found = null; 548 InventoryItemBase found = null;
569 549
570 // If the parentID is zero, then this is going 550 // If the parentID is zero, then this is going
@@ -575,7 +555,7 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
575 item.Folder = context.ID; 555 item.Folder = context.ID;
576 } 556 }
577 557
578 // Determine whether this is a new item or a 558 // Determine whether this is a new item or a
579 // replacement definition. 559 // replacement definition.
580 560
581 foreach (InventoryItemBase xi in rdata.items) 561 foreach (InventoryItemBase xi in rdata.items)
@@ -604,7 +584,6 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
604 created = true; 584 created = true;
605 rdata.appendStatus(String.Format("<p> Created item {2}, UUID {3}<p>", item.Name, item.ID)); 585 rdata.appendStatus(String.Format("<p> Created item {2}, UUID {3}<p>", item.Name, item.ID));
606 } 586 }
607
608 } 587 }
609 588
610 if (created) 589 if (created)
@@ -627,7 +606,6 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
627 } 606 }
628 607
629 rdata.Respond("Inventory " + rdata.method + ": Normal completion"); 608 rdata.Respond("Inventory " + rdata.method + ": Normal completion");
630
631 } 609 }
632 else 610 else
633 { 611 {
@@ -635,35 +613,33 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
635 MsgId, rdata.method, rdata.path, InventoryNode.GetType()); 613 MsgId, rdata.method, rdata.path, InventoryNode.GetType());
636 rdata.Fail(Rest.HttpStatusCodeBadRequest, "invalid resource context"); 614 rdata.Fail(Rest.HttpStatusCodeBadRequest, "invalid resource context");
637 } 615 }
638
639 } 616 }
640 617
641 /// <summary> 618 /// <summary>
642 /// PUT updates the URI-identified element in the inventory. This 619 /// PUT updates the URI-identified element in the inventory. This
643 /// is actually far more flexible than it might at first sound. For 620 /// is actually far more flexible than it might at first sound. For
644 /// PUT the URI serves two purposes: 621 /// PUT the URI serves two purposes:
645 /// [1] It identifies the user whose inventory is to be 622 /// [1] It identifies the user whose inventory is to be
646 /// processed. 623 /// processed.
647 /// [2] It optionally specifies a subtree of the inventory 624 /// [2] It optionally specifies a subtree of the inventory
648 /// that is to be used to resolve any relative subtree 625 /// that is to be used to resolve any relative subtree
649 /// specifications in the entity. If nothing is specified 626 /// specifications in the entity. If nothing is specified
650 /// then the whole of the private inventory is implied. 627 /// then the whole of the private inventory is implied.
651 /// Please note that the subtree specified by the URI is only relevant 628 /// Please note that the subtree specified by the URI is only relevant
652 /// to an entity containing a URI relative specification, i.e. one or 629 /// to an entity containing a URI relative specification, i.e. one or
653 /// more elements do not specify parent folder information. These 630 /// more elements do not specify parent folder information. These
654 /// elements will be implicitly referenced within the context identified 631 /// elements will be implicitly referenced within the context identified
655 /// by the URI. 632 /// by the URI.
656 /// If an element in the entity specifies an explicit parent folder, then 633 /// If an element in the entity specifies an explicit parent folder, then
657 /// that parent is effective, regardless of any value specified in the 634 /// that parent is effective, regardless of any value specified in the
658 /// URI. If the parent does not exist, then the element, and any dependent 635 /// URI. If the parent does not exist, then the element, and any dependent
659 /// elements, are ignored. This case is actually detected and handled 636 /// elements, are ignored. This case is actually detected and handled
660 /// during the reconstitution process. 637 /// during the reconstitution process.
661 /// </summary> 638 /// </summary>
662 /// <param name=rdata>HTTP service request work area</param> 639 /// <param name=rdata>HTTP service request work area</param>
663 640
664 private void DoUpdate(InventoryRequestData rdata) 641 private void DoUpdate(InventoryRequestData rdata)
665 { 642 {
666
667 int count = 0; 643 int count = 0;
668 bool created = false; 644 bool created = false;
669 bool modified = false; 645 bool modified = false;
@@ -675,8 +651,8 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
675 Object InventoryNode = getInventoryNode(rdata, rdata.root, PARM_PATH, Rest.Fill); 651 Object InventoryNode = getInventoryNode(rdata, rdata.root, PARM_PATH, Rest.Fill);
676 652
677 // As long as we have a node, then we have something 653 // As long as we have a node, then we have something
678 // meaningful to do, unlike POST. So we reconstitute the 654 // meaningful to do, unlike POST. So we reconstitute the
679 // subtree before doing anything else. Note that we 655 // subtree before doing anything else. Note that we
680 // etiher got a valid node or we threw an exception. 656 // etiher got a valid node or we threw an exception.
681 657
682 XmlInventoryCollection entity = ReconstituteEntity(rdata); 658 XmlInventoryCollection entity = ReconstituteEntity(rdata);
@@ -705,33 +681,31 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
705 { 681 {
706 Rest.Dump(asset.Data); 682 Rest.Dump(asset.Data);
707 } 683 }
708
709 } 684 }
710 } 685 }
711 686
712 // The URI specifies either a folder or an item to be updated. 687 // The URI specifies either a folder or an item to be updated.
713 // 688 //
714 // The root node in the entity will replace the node identified 689 // The root node in the entity will replace the node identified
715 // by the URI. This means the parent will remain the same, but 690 // by the URI. This means the parent will remain the same, but
716 // any or all attributes associated with the named element 691 // any or all attributes associated with the named element
717 // will change. 692 // will change.
718 // 693 //
719 // If the inventory collection contains an element with a zero 694 // If the inventory collection contains an element with a zero
720 // parent ID, then this is taken to be the replacement for the 695 // parent ID, then this is taken to be the replacement for the
721 // named node. The collection MAY also specify an explicit 696 // named node. The collection MAY also specify an explicit
722 // parent ID, in this case it MAY identify the same parent as 697 // parent ID, in this case it MAY identify the same parent as
723 // the current node, or it MAY specify a different parent, 698 // the current node, or it MAY specify a different parent,
724 // indicating that the folder is being moved in addition to any 699 // indicating that the folder is being moved in addition to any
725 // other modifications being made. 700 // other modifications being made.
726 701
727 if (typeof(InventoryFolderBase) == InventoryNode.GetType() || 702 if (typeof(InventoryFolderBase) == InventoryNode.GetType() ||
728 typeof(InventoryFolderImpl) == InventoryNode.GetType()) 703 typeof(InventoryFolderImpl) == InventoryNode.GetType())
729 { 704 {
730
731 bool rfound = false; 705 bool rfound = false;
732 InventoryFolderBase uri = (InventoryFolderBase) InventoryNode; 706 InventoryFolderBase uri = (InventoryFolderBase) InventoryNode;
733 InventoryFolderBase xml = null; 707 InventoryFolderBase xml = null;
734 708
735 // If the entity to be replaced resolved to be the root 709 // If the entity to be replaced resolved to be the root
736 // directory itself (My Inventory), then make sure that 710 // directory itself (My Inventory), then make sure that
737 // the supplied data include as appropriately typed and 711 // the supplied data include as appropriately typed and
@@ -741,7 +715,6 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
741 715
742 if (uri == rdata.root) 716 if (uri == rdata.root)
743 { 717 {
744
745 foreach (InventoryFolderBase folder in entity.Folders) 718 foreach (InventoryFolderBase folder in entity.Folders)
746 { 719 {
747 if ((rfound = (folder.Name == PRIVATE_ROOT_NAME))) 720 if ((rfound = (folder.Name == PRIVATE_ROOT_NAME)))
@@ -757,7 +730,6 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
757 MsgId, rdata.method, rdata.path); 730 MsgId, rdata.method, rdata.path);
758 rdata.Fail(Rest.HttpStatusCodeBadRequest, "invalid inventory structure"); 731 rdata.Fail(Rest.HttpStatusCodeBadRequest, "invalid inventory structure");
759 } 732 }
760
761 } 733 }
762 734
763 // Scan the set of folders in the entity collection for an 735 // Scan the set of folders in the entity collection for an
@@ -768,7 +740,7 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
768 // ambiguity in this case because this is POST and we are 740 // ambiguity in this case because this is POST and we are
769 // supposed to be modifying a specific node. 741 // supposed to be modifying a specific node.
770 // We assign any element IDs required as an economy; we don't 742 // We assign any element IDs required as an economy; we don't
771 // want to iterate over the fodler set again if it can be 743 // want to iterate over the fodler set again if it can be
772 // helped. 744 // helped.
773 745
774 foreach (InventoryFolderBase folder in entity.Folders) 746 foreach (InventoryFolderBase folder in entity.Folders)
@@ -795,13 +767,12 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
795 // Exactly one entry means we ARE replacing the node 767 // Exactly one entry means we ARE replacing the node
796 // identified by the URI. So we delete the old folder 768 // identified by the URI. So we delete the old folder
797 // by moving it to the trash and then purging it. 769 // by moving it to the trash and then purging it.
798 // We then add all of the folders and items we 770 // We then add all of the folders and items we
799 // included in the entity. The subtree has been 771 // included in the entity. The subtree has been
800 // modified. 772 // modified.
801 773
802 if (count == 1) 774 if (count == 1)
803 { 775 {
804
805 InventoryFolderBase TrashCan = GetTrashCan(rdata); 776 InventoryFolderBase TrashCan = GetTrashCan(rdata);
806 777
807 // All went well, so we generate a UUID is one is 778 // All went well, so we generate a UUID is one is
@@ -816,10 +787,9 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
816 Rest.InventoryServices.MoveFolder(uri); 787 Rest.InventoryServices.MoveFolder(uri);
817 Rest.InventoryServices.PurgeFolder(TrashCan); 788 Rest.InventoryServices.PurgeFolder(TrashCan);
818 modified = true; 789 modified = true;
819
820 } 790 }
821 791
822 // Now, regardelss of what they represent, we 792 // Now, regardelss of what they represent, we
823 // integrate all of the elements in the entity. 793 // integrate all of the elements in the entity.
824 794
825 foreach (InventoryFolderBase f in entity.Folders) 795 foreach (InventoryFolderBase f in entity.Folders)
@@ -833,7 +803,6 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
833 rdata.appendStatus(String.Format("<p>Storing item {0} UUID {1}<p>", it.Name, it.ID)); 803 rdata.appendStatus(String.Format("<p>Storing item {0} UUID {1}<p>", it.Name, it.ID));
834 Rest.InventoryServices.AddItem(it); 804 Rest.InventoryServices.AddItem(it);
835 } 805 }
836
837 } 806 }
838 807
839 /// <summary> 808 /// <summary>
@@ -846,7 +815,6 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
846 815
847 else 816 else
848 { 817 {
849
850 InventoryItemBase uri = (InventoryItemBase) InventoryNode; 818 InventoryItemBase uri = (InventoryItemBase) InventoryNode;
851 InventoryItemBase xml = null; 819 InventoryItemBase xml = null;
852 820
@@ -865,7 +833,7 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
865 } 833 }
866 834
867 xml = entity.Items[0]; 835 xml = entity.Items[0];
868 836
869 if (xml.ID == LLUUID.Zero) 837 if (xml.ID == LLUUID.Zero)
870 { 838 {
871 xml.ID = LLUUID.Random(); 839 xml.ID = LLUUID.Random();
@@ -884,7 +852,6 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
884 Rest.InventoryServices.AddItem(xml); 852 Rest.InventoryServices.AddItem(xml);
885 853
886 rdata.appendStatus(String.Format("<p>Storing item {0} UUID {1}<p>", xml.Name, xml.ID)); 854 rdata.appendStatus(String.Format("<p>Storing item {0} UUID {1}<p>", xml.Name, xml.ID));
887
888 } 855 }
889 856
890 if (created) 857 if (created)
@@ -904,7 +871,6 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
904 } 871 }
905 872
906 rdata.Respond("Inventory " + rdata.method + ": Normal completion"); 873 rdata.Respond("Inventory " + rdata.method + ": Normal completion");
907
908 } 874 }
909 875
910 /// <summary> 876 /// <summary>
@@ -917,7 +883,7 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
917 /// 883 ///
918 /// Folders are deleted by moving them to another folder and then 884 /// Folders are deleted by moving them to another folder and then
919 /// purging that folder. We'll do that by creating a temporary 885 /// purging that folder. We'll do that by creating a temporary
920 /// sub-folder in the TrashCan and purging that folder's 886 /// sub-folder in the TrashCan and purging that folder's
921 /// contents. If we can't can it, we don't delete it... 887 /// contents. If we can't can it, we don't delete it...
922 /// So, if no trashcan is available, the request does nothing. 888 /// So, if no trashcan is available, the request does nothing.
923 /// Items are summarily deleted. 889 /// Items are summarily deleted.
@@ -930,13 +896,11 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
930 896
931 private void DoDelete(InventoryRequestData rdata) 897 private void DoDelete(InventoryRequestData rdata)
932 { 898 {
933
934 Object InventoryNode = getInventoryNode(rdata, rdata.root, PARM_PATH, false); 899 Object InventoryNode = getInventoryNode(rdata, rdata.root, PARM_PATH, false);
935 900
936 if (typeof(InventoryFolderBase) == InventoryNode.GetType() || 901 if (typeof(InventoryFolderBase) == InventoryNode.GetType() ||
937 typeof(InventoryFolderImpl) == InventoryNode.GetType()) 902 typeof(InventoryFolderImpl) == InventoryNode.GetType())
938 { 903 {
939
940 InventoryFolderBase TrashCan = GetTrashCan(rdata); 904 InventoryFolderBase TrashCan = GetTrashCan(rdata);
941 905
942 InventoryFolderBase folder = (InventoryFolderBase) InventoryNode; 906 InventoryFolderBase folder = (InventoryFolderBase) InventoryNode;
@@ -947,7 +911,6 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
947 Rest.InventoryServices.PurgeFolder(TrashCan); 911 Rest.InventoryServices.PurgeFolder(TrashCan);
948 912
949 rdata.appendStatus(String.Format("<p>Deleted folder {0} UUID {1}<p>", folder.Name, folder.ID)); 913 rdata.appendStatus(String.Format("<p>Deleted folder {0} UUID {1}<p>", folder.Name, folder.ID));
950
951 } 914 }
952 915
953 // Deleting items is much more straight forward. 916 // Deleting items is much more straight forward.
@@ -963,7 +926,6 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
963 926
964 rdata.Complete(); 927 rdata.Complete();
965 rdata.Respond("Inventory " + rdata.method + ": Normal completion"); 928 rdata.Respond("Inventory " + rdata.method + ": Normal completion");
966
967 } 929 }
968 930
969#endregion method-specific processing 931#endregion method-specific processing
@@ -971,10 +933,10 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
971 /// <summary> 933 /// <summary>
972 /// This method is called to obtain the OpenSim inventory object identified 934 /// This method is called to obtain the OpenSim inventory object identified
973 /// by the supplied URI. This may be either an Item or a Folder, so a suitably 935 /// by the supplied URI. This may be either an Item or a Folder, so a suitably
974 /// ambiguous return type is employed (Object). This method recurses as 936 /// ambiguous return type is employed (Object). This method recurses as
975 /// necessary to process the designated hierarchy. 937 /// necessary to process the designated hierarchy.
976 /// 938 ///
977 /// If we reach the end of the URI then we return the contextual folder to 939 /// If we reach the end of the URI then we return the contextual folder to
978 /// our caller. 940 /// our caller.
979 /// 941 ///
980 /// If we are not yet at the end of the URI we attempt to find a child folder 942 /// If we are not yet at the end of the URI we attempt to find a child folder
@@ -1000,7 +962,6 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
1000 InventoryFolderBase folder, 962 InventoryFolderBase folder,
1001 int pi, bool fill) 963 int pi, bool fill)
1002 { 964 {
1003
1004 InventoryFolderBase foundf = null; 965 InventoryFolderBase foundf = null;
1005 int fk = 0; 966 int fk = 0;
1006 967
@@ -1013,18 +974,19 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
1013 return folder; 974 return folder;
1014 } 975 }
1015 976
1016 // There are more names in the parameter sequence, 977 // There are more names in the parameter sequence,
1017 // look for the folder named by param[pi] as a 978 // look for the folder named by param[pi] as a
1018 // child of the folder supplied as an argument. 979 // child of the folder supplied as an argument.
1019 // Note that a UUID may have been supplied as the 980 // Note that a UUID may have been supplied as the
1020 // identifier (it is the ONLY guaranteed unambiguous 981 // identifier (it is the ONLY guaranteed unambiguous
1021 // option. 982 // option.
1022 983
1023 if (rdata.folders != null) 984 if (rdata.folders != null)
985 {
1024 foreach (InventoryFolderBase f in rdata.folders) 986 foreach (InventoryFolderBase f in rdata.folders)
1025 { 987 {
1026 // Look for the present node in the directory list 988 // Look for the present node in the directory list
1027 if (f.ParentID == folder.ID && 989 if (f.ParentID == folder.ID &&
1028 (f.Name == rdata.Parameters[pi] || 990 (f.Name == rdata.Parameters[pi] ||
1029 f.ID.ToString() == rdata.Parameters[pi])) 991 f.ID.ToString() == rdata.Parameters[pi]))
1030 { 992 {
@@ -1032,7 +994,8 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
1032 fk++; 994 fk++;
1033 } 995 }
1034 } 996 }
1035 997 }
998
1036 // If more than one node matched, then the path, as specified 999 // If more than one node matched, then the path, as specified
1037 // is ambiguous. 1000 // is ambiguous.
1038 1001
@@ -1063,7 +1026,7 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
1063 InventoryItemBase li = null; 1026 InventoryItemBase li = null;
1064 foreach (InventoryItemBase i in rdata.items) 1027 foreach (InventoryItemBase i in rdata.items)
1065 { 1028 {
1066 if (i.Folder == folder.ID && 1029 if (i.Folder == folder.ID &&
1067 (i.Name == rdata.Parameters[pi] || 1030 (i.Name == rdata.Parameters[pi] ||
1068 i.ID.ToString() == rdata.Parameters[pi])) 1031 i.ID.ToString() == rdata.Parameters[pi]))
1069 { 1032 {
@@ -1099,11 +1062,10 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
1099 rdata.Fail(Rest.HttpStatusCodeNotFound, "resource "+rdata.path+" not found"); 1062 rdata.Fail(Rest.HttpStatusCodeNotFound, "resource "+rdata.path+" not found");
1100 1063
1101 return null; /* Never reached */ 1064 return null; /* Never reached */
1102
1103 } 1065 }
1104 1066
1105 /// <summary> 1067 /// <summary>
1106 /// This routine traverse the inventory's structure until the end-point identified 1068 /// This routine traverse the inventory's structure until the end-point identified
1107 /// in the URI is reached, the remainder of the inventory (if any) is then formatted 1069 /// in the URI is reached, the remainder of the inventory (if any) is then formatted
1108 /// and returned to the requestor. 1070 /// and returned to the requestor.
1109 /// 1071 ///
@@ -1119,13 +1081,11 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
1119 1081
1120 private void traverse(InventoryRequestData rdata, InventoryFolderBase folder, int pi) 1082 private void traverse(InventoryRequestData rdata, InventoryFolderBase folder, int pi)
1121 { 1083 {
1122
1123 Rest.Log.DebugFormat("{0} Traverse[initial] : {1} {2} [{3}]", MsgId, folder.ID, folder.Name, pi); 1084 Rest.Log.DebugFormat("{0} Traverse[initial] : {1} {2} [{3}]", MsgId, folder.ID, folder.Name, pi);
1124 1085
1125 if (rdata.folders != null) 1086 if (rdata.folders != null)
1126 { 1087 {
1127 1088 // If there was only one parameter (avatar name), then the entire
1128 // If there was only one parameter (avatar name), then the entire
1129 // inventory is being requested. 1089 // inventory is being requested.
1130 1090
1131 if (rdata.Parameters.Length == 1) 1091 if (rdata.Parameters.Length == 1)
@@ -1159,18 +1119,16 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
1159 } 1119 }
1160 1120
1161 return; 1121 return;
1162
1163 } 1122 }
1164 } 1123 }
1165 1124
1166 /// <summary> 1125 /// <summary>
1167 /// This is the recursive method. I've separated them in this way so that 1126 /// This is the recursive method. I've separated them in this way so that
1168 /// we do not have to waste cycles on any first-case-only processing. 1127 /// we do not have to waste cycles on any first-case-only processing.
1169 /// </summary> 1128 /// </summary>
1170 1129
1171 private void traverseInventory(InventoryRequestData rdata, InventoryFolderBase folder, int pi) 1130 private void traverseInventory(InventoryRequestData rdata, InventoryFolderBase folder, int pi)
1172 { 1131 {
1173
1174 int fk = 0; 1132 int fk = 0;
1175 InventoryFolderBase ffound = null; 1133 InventoryFolderBase ffound = null;
1176 InventoryItemBase ifound = null; 1134 InventoryItemBase ifound = null;
@@ -1179,7 +1137,7 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
1179 1137
1180 foreach (InventoryFolderBase f in rdata.folders) 1138 foreach (InventoryFolderBase f in rdata.folders)
1181 { 1139 {
1182 if (f.ParentID == folder.ID && 1140 if (f.ParentID == folder.ID &&
1183 (f.Name == rdata.Parameters[pi] || 1141 (f.Name == rdata.Parameters[pi] ||
1184 f.ID.ToString() == rdata.Parameters[pi])) 1142 f.ID.ToString() == rdata.Parameters[pi]))
1185 { 1143 {
@@ -1194,14 +1152,13 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
1194 1152
1195 if (pi == rdata.Parameters.Length-1) 1153 if (pi == rdata.Parameters.Length-1)
1196 { 1154 {
1197
1198 // Only if there are any items, and there pretty much always are. 1155 // Only if there are any items, and there pretty much always are.
1199 1156
1200 if (rdata.items != null) 1157 if (rdata.items != null)
1201 { 1158 {
1202 foreach (InventoryItemBase i in rdata.items) 1159 foreach (InventoryItemBase i in rdata.items)
1203 { 1160 {
1204 if (i.Folder == folder.ID && 1161 if (i.Folder == folder.ID &&
1205 (i.Name == rdata.Parameters[pi] || 1162 (i.Name == rdata.Parameters[pi] ||
1206 i.ID.ToString() == rdata.Parameters[pi])) 1163 i.ID.ToString() == rdata.Parameters[pi]))
1207 { 1164 {
@@ -1230,7 +1187,7 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
1230 { 1187 {
1231 // Fetching an Item has a special significance. In this 1188 // Fetching an Item has a special significance. In this
1232 // case we also want to fetch the associated asset. 1189 // case we also want to fetch the associated asset.
1233 // To make it interesting, we'll d this via redirection. 1190 // To make it interesting, we'll d this via redirection.
1234 string asseturl = "http://" + rdata.hostname + ":" + rdata.port + 1191 string asseturl = "http://" + rdata.hostname + ":" + rdata.port +
1235 "/admin/assets" + Rest.UrlPathSeparator + ifound.AssetID.ToString(); 1192 "/admin/assets" + Rest.UrlPathSeparator + ifound.AssetID.ToString();
1236 rdata.Redirect(asseturl,Rest.PERMANENT); 1193 rdata.Redirect(asseturl,Rest.PERMANENT);
@@ -1240,14 +1197,14 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
1240 else if (fk > 1) 1197 else if (fk > 1)
1241 { 1198 {
1242 rdata.Fail(Rest.HttpStatusCodeConflict, 1199 rdata.Fail(Rest.HttpStatusCodeConflict,
1243 String.Format("ambiguous element ({0}) in path specified: <{1}>", 1200 String.Format("ambiguous element ({0}) in path specified: <{1}>",
1244 pi, rdata.path)); 1201 pi, rdata.path));
1245 } 1202 }
1246 1203
1247 Rest.Log.DebugFormat("{0} Inventory does not contain item/folder: <{1}>", 1204 Rest.Log.DebugFormat("{0} Inventory does not contain item/folder: <{1}>",
1248 MsgId, rdata.path); 1205 MsgId, rdata.path);
1249 rdata.Fail(Rest.HttpStatusCodeNotFound,String.Format("no such item/folder : {0}", 1206 rdata.Fail(Rest.HttpStatusCodeNotFound,String.Format("no such item/folder : {0}",
1250 rdata.Parameters[pi])); 1207 rdata.Parameters[pi]));
1251 1208
1252 } 1209 }
1253 1210
@@ -1264,10 +1221,9 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
1264 1221
1265 private void formatInventory(InventoryRequestData rdata, InventoryFolderBase folder, string indent) 1222 private void formatInventory(InventoryRequestData rdata, InventoryFolderBase folder, string indent)
1266 { 1223 {
1267
1268 if (Rest.DEBUG) 1224 if (Rest.DEBUG)
1269 { 1225 {
1270 Rest.Log.DebugFormat("{0} Folder : {1} {2} {3} type = {4}", 1226 Rest.Log.DebugFormat("{0} Folder : {1} {2} {3} type = {4}",
1271 MsgId, folder.ID, indent, folder.Name, folder.Type); 1227 MsgId, folder.ID, indent, folder.Name, folder.Type);
1272 indent += "\t"; 1228 indent += "\t";
1273 } 1229 }
@@ -1307,7 +1263,6 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
1307 // End folder item 1263 // End folder item
1308 1264
1309 rdata.writer.WriteEndElement(); 1265 rdata.writer.WriteEndElement();
1310
1311 } 1266 }
1312 1267
1313 /// <summary> 1268 /// <summary>
@@ -1319,8 +1274,7 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
1319 1274
1320 private void formatItem(InventoryRequestData rdata, InventoryItemBase i, string indent) 1275 private void formatItem(InventoryRequestData rdata, InventoryItemBase i, string indent)
1321 { 1276 {
1322 1277 Rest.Log.DebugFormat("{0} Item : {1} {2} {3} Type = {4}, AssetType = {5}",
1323 Rest.Log.DebugFormat("{0} Item : {1} {2} {3} Type = {4}, AssetType = {5}",
1324 MsgId, i.ID, indent, i.Name, i.InvType, i.AssetType); 1278 MsgId, i.ID, indent, i.Name, i.InvType, i.AssetType);
1325 1279
1326 rdata.writer.WriteStartElement(String.Empty,"Item",String.Empty); 1280 rdata.writer.WriteStartElement(String.Empty,"Item",String.Empty);
@@ -1350,11 +1304,10 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
1350 rdata.writer.WriteElementString("Asset",i.AssetID.ToString()); 1304 rdata.writer.WriteElementString("Asset",i.AssetID.ToString());
1351 1305
1352 rdata.writer.WriteEndElement(); 1306 rdata.writer.WriteEndElement();
1353
1354 } 1307 }
1355 1308
1356 /// <summary> 1309 /// <summary>
1357 /// This method creates a "trashcan" folder to support folder and item 1310 /// This method creates a "trashcan" folder to support folder and item
1358 /// deletions by this interface. The xisting trash folder is found and 1311 /// deletions by this interface. The xisting trash folder is found and
1359 /// this folder is created within it. It is called "tmp" to indicate to 1312 /// this folder is created within it. It is called "tmp" to indicate to
1360 /// the client that it is OK to delete this folder. The REST interface 1313 /// the client that it is OK to delete this folder. The REST interface
@@ -1366,7 +1319,6 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
1366 1319
1367 private InventoryFolderBase GetTrashCan(InventoryRequestData rdata) 1320 private InventoryFolderBase GetTrashCan(InventoryRequestData rdata)
1368 { 1321 {
1369
1370 InventoryFolderBase TrashCan = null; 1322 InventoryFolderBase TrashCan = null;
1371 1323
1372 foreach (InventoryFolderBase f in rdata.folders) 1324 foreach (InventoryFolderBase f in rdata.folders)
@@ -1393,7 +1345,7 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
1393 } 1345 }
1394 } 1346 }
1395 } 1347 }
1396 1348
1397 if (TrashCan == null) 1349 if (TrashCan == null)
1398 { 1350 {
1399 Rest.Log.DebugFormat("{0} No Trash Can available", MsgId); 1351 Rest.Log.DebugFormat("{0} No Trash Can available", MsgId);
@@ -1401,7 +1353,6 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
1401 } 1353 }
1402 1354
1403 return TrashCan; 1355 return TrashCan;
1404
1405 } 1356 }
1406 1357
1407 /// <summary> 1358 /// <summary>
@@ -1413,11 +1364,11 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
1413 1364
1414 private bool FolderHasChanged(InventoryFolderBase newf, InventoryFolderBase oldf) 1365 private bool FolderHasChanged(InventoryFolderBase newf, InventoryFolderBase oldf)
1415 { 1366 {
1416 return ( newf.Name != oldf.Name 1367 return (newf.Name != oldf.Name
1417 || newf.ParentID != oldf.ParentID 1368 || newf.ParentID != oldf.ParentID
1418 || newf.Owner != oldf.Owner 1369 || newf.Owner != oldf.Owner
1419 || newf.Type != oldf.Type 1370 || newf.Type != oldf.Type
1420 || newf.Version != oldf.Version 1371 || newf.Version != oldf.Version
1421 ); 1372 );
1422 } 1373 }
1423 1374
@@ -1430,24 +1381,24 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
1430 1381
1431 private bool ItemHasChanged(InventoryItemBase newf, InventoryItemBase oldf) 1382 private bool ItemHasChanged(InventoryItemBase newf, InventoryItemBase oldf)
1432 { 1383 {
1433 return ( newf.Name != oldf.Name 1384 return (newf.Name != oldf.Name
1434 || newf.Folder != oldf.Description 1385 || newf.Folder != oldf.Description
1435 || newf.Description != oldf.Description 1386 || newf.Description != oldf.Description
1436 || newf.Owner != oldf.Owner 1387 || newf.Owner != oldf.Owner
1437 || newf.Creator != oldf.Creator 1388 || newf.Creator != oldf.Creator
1438 || newf.AssetID != oldf.AssetID 1389 || newf.AssetID != oldf.AssetID
1439 || newf.GroupID != oldf.GroupID 1390 || newf.GroupID != oldf.GroupID
1440 || newf.GroupOwned != oldf.GroupOwned 1391 || newf.GroupOwned != oldf.GroupOwned
1441 || newf.InvType != oldf.InvType 1392 || newf.InvType != oldf.InvType
1442 || newf.AssetType != oldf.AssetType 1393 || newf.AssetType != oldf.AssetType
1443 ); 1394 );
1444 } 1395 }
1445 1396
1446 /// <summary> 1397 /// <summary>
1447 /// This method is called by PUT and POST to create an XmlInventoryCollection 1398 /// This method is called by PUT and POST to create an XmlInventoryCollection
1448 /// instance that reflects the content of the entity supplied on the request. 1399 /// instance that reflects the content of the entity supplied on the request.
1449 /// Any elements in the completed collection whose UUID is zero, are 1400 /// Any elements in the completed collection whose UUID is zero, are
1450 /// considered to be located relative to the end-point identified int he 1401 /// considered to be located relative to the end-point identified int he
1451 /// URI. In this way, an entire sub-tree can be conveyed in a single REST 1402 /// URI. In this way, an entire sub-tree can be conveyed in a single REST
1452 /// PUT or POST request. 1403 /// PUT or POST request.
1453 /// 1404 ///
@@ -1455,27 +1406,25 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
1455 /// has an entity, it is more completely initialized. thus, if no entity was 1406 /// has an entity, it is more completely initialized. thus, if no entity was
1456 /// provided the collection is valid, but empty. 1407 /// provided the collection is valid, but empty.
1457 /// 1408 ///
1458 /// The entity is then scanned and each tag is processed to produce the 1409 /// The entity is then scanned and each tag is processed to produce the
1459 /// appropriate inventory elements. At the end f the scan, teh XmlInventoryCollection 1410 /// appropriate inventory elements. At the end f the scan, teh XmlInventoryCollection
1460 /// will reflect the subtree described by the entity. 1411 /// will reflect the subtree described by the entity.
1461 /// 1412 ///
1462 /// This is a very flexible mechanism, the entity may contain arbitrary, 1413 /// This is a very flexible mechanism, the entity may contain arbitrary,
1463 /// discontiguous tree fragments, or may contain single element. The caller is 1414 /// discontiguous tree fragments, or may contain single element. The caller is
1464 /// responsible for integrating this collection (and ensuring that any 1415 /// responsible for integrating this collection (and ensuring that any
1465 /// missing parent IDs are resolved). 1416 /// missing parent IDs are resolved).
1466 /// </summary> 1417 /// </summary>
1467 /// <param name=rdata>HTTP service request work area</param> 1418 /// <param name=rdata>HTTP service request work area</param>
1468 1419
1469 internal XmlInventoryCollection ReconstituteEntity(InventoryRequestData rdata) 1420 internal XmlInventoryCollection ReconstituteEntity(InventoryRequestData rdata)
1470 { 1421 {
1471
1472 Rest.Log.DebugFormat("{0} Reconstituting entity", MsgId); 1422 Rest.Log.DebugFormat("{0} Reconstituting entity", MsgId);
1473 1423
1474 XmlInventoryCollection ic = new XmlInventoryCollection(); 1424 XmlInventoryCollection ic = new XmlInventoryCollection();
1475 1425
1476 if (rdata.request.HasEntityBody) 1426 if (rdata.request.HasEntityBody)
1477 { 1427 {
1478
1479 Rest.Log.DebugFormat("{0} Entity present", MsgId); 1428 Rest.Log.DebugFormat("{0} Entity present", MsgId);
1480 1429
1481 ic.init(rdata); 1430 ic.init(rdata);
@@ -1571,7 +1520,6 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
1571 Rest.Log.WarnFormat("{0} Unexpected XML parsing error: {1}", MsgId, e.Message); 1520 Rest.Log.WarnFormat("{0} Unexpected XML parsing error: {1}", MsgId, e.Message);
1572 throw e; 1521 throw e;
1573 } 1522 }
1574
1575 } 1523 }
1576 else 1524 else
1577 { 1525 {
@@ -1587,14 +1535,13 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
1587 } 1535 }
1588 1536
1589 return ic; 1537 return ic;
1590
1591 } 1538 }
1592 1539
1593 /// <summary> 1540 /// <summary>
1594 /// This method creates an inventory Folder from the 1541 /// This method creates an inventory Folder from the
1595 /// information supplied in the request's entity. 1542 /// information supplied in the request's entity.
1596 /// A folder instance is created and initialized to reflect 1543 /// A folder instance is created and initialized to reflect
1597 /// default values. These values are then overridden 1544 /// default values. These values are then overridden
1598 /// by information supplied in the entity. 1545 /// by information supplied in the entity.
1599 /// If context was not explicitly provided, then the 1546 /// If context was not explicitly provided, then the
1600 /// appropriate ID values are determined. 1547 /// appropriate ID values are determined.
@@ -1602,7 +1549,6 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
1602 1549
1603 private void CollectFolder(XmlInventoryCollection ic) 1550 private void CollectFolder(XmlInventoryCollection ic)
1604 { 1551 {
1605
1606 Rest.Log.DebugFormat("{0} Interpret folder element", MsgId); 1552 Rest.Log.DebugFormat("{0} Interpret folder element", MsgId);
1607 1553
1608 InventoryFolderBase result = new InventoryFolderBase(); 1554 InventoryFolderBase result = new InventoryFolderBase();
@@ -1614,7 +1560,7 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
1614 result.Owner = ic.UserID; 1560 result.Owner = ic.UserID;
1615 result.ParentID = LLUUID.Zero; // Context 1561 result.ParentID = LLUUID.Zero; // Context
1616 result.Type = (short) AssetType.Folder; 1562 result.Type = (short) AssetType.Folder;
1617 result.Version = 1; 1563 result.Version = 1;
1618 1564
1619 if (ic.xml.HasAttributes) 1565 if (ic.xml.HasAttributes)
1620 { 1566 {
@@ -1642,7 +1588,7 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
1642 result.Version = UInt16.Parse(ic.xml.Value); 1588 result.Version = UInt16.Parse(ic.xml.Value);
1643 break; 1589 break;
1644 default : 1590 default :
1645 Rest.Log.DebugFormat("{0} Folder: unrecognized attribute: {1}:{2}", 1591 Rest.Log.DebugFormat("{0} Folder: unrecognized attribute: {1}:{2}",
1646 MsgId, ic.xml.Name, ic.xml.Value); 1592 MsgId, ic.xml.Name, ic.xml.Value);
1647 ic.Fail(Rest.HttpStatusCodeBadRequest, String.Format("unrecognized attribute <{0}>", 1593 ic.Fail(Rest.HttpStatusCodeBadRequest, String.Format("unrecognized attribute <{0}>",
1648 ic.xml.Name)); 1594 ic.xml.Name));
@@ -1664,7 +1610,6 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
1664 } 1610 }
1665 else 1611 else
1666 { 1612 {
1667
1668 bool found = false; 1613 bool found = false;
1669 1614
1670 foreach (InventoryFolderBase parent in ic.rdata.folders) 1615 foreach (InventoryFolderBase parent in ic.rdata.folders)
@@ -1678,11 +1623,10 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
1678 1623
1679 if (!found) 1624 if (!found)
1680 { 1625 {
1681 Rest.Log.ErrorFormat("{0} Invalid parent ID ({1}) in folder {2}", 1626 Rest.Log.ErrorFormat("{0} Invalid parent ID ({1}) in folder {2}",
1682 MsgId, ic.Item.Folder, result.ID); 1627 MsgId, ic.Item.Folder, result.ID);
1683 ic.Fail(Rest.HttpStatusCodeBadRequest, "invalid parent"); 1628 ic.Fail(Rest.HttpStatusCodeBadRequest, "invalid parent");
1684 } 1629 }
1685
1686 } 1630 }
1687 1631
1688 // This is a new folder, so no existing UUID is available 1632 // This is a new folder, so no existing UUID is available
@@ -1697,15 +1641,14 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
1697 // obsolete as a consequence. 1641 // obsolete as a consequence.
1698 1642
1699 ic.Push(result); 1643 ic.Push(result);
1700
1701 } 1644 }
1702 1645
1703 /// <summary> 1646 /// <summary>
1704 /// This method is called to handle the construction of an Item 1647 /// This method is called to handle the construction of an Item
1705 /// instance from the supplied request entity. It is called 1648 /// instance from the supplied request entity. It is called
1706 /// whenever an Item start tag is detected. 1649 /// whenever an Item start tag is detected.
1707 /// An instance of an Item is created and initialized to default 1650 /// An instance of an Item is created and initialized to default
1708 /// values. These values are then overridden from values supplied 1651 /// values. These values are then overridden from values supplied
1709 /// as attributes to the Item element. 1652 /// as attributes to the Item element.
1710 /// This item is then stored in the XmlInventoryCollection and 1653 /// This item is then stored in the XmlInventoryCollection and
1711 /// will be verified by Validate. 1654 /// will be verified by Validate.
@@ -1715,7 +1658,6 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
1715 1658
1716 private void CollectItem(XmlInventoryCollection ic) 1659 private void CollectItem(XmlInventoryCollection ic)
1717 { 1660 {
1718
1719 Rest.Log.DebugFormat("{0} Interpret item element", MsgId); 1661 Rest.Log.DebugFormat("{0} Interpret item element", MsgId);
1720 1662
1721 InventoryItemBase result = new InventoryItemBase(); 1663 InventoryItemBase result = new InventoryItemBase();
@@ -1736,7 +1678,6 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
1736 { 1678 {
1737 for (int i = 0; i < ic.xml.AttributeCount; i++) 1679 for (int i = 0; i < ic.xml.AttributeCount; i++)
1738 { 1680 {
1739
1740 ic.xml.MoveToAttribute(i); 1681 ic.xml.MoveToAttribute(i);
1741 1682
1742 switch (ic.xml.Name) 1683 switch (ic.xml.Name)
@@ -1785,37 +1726,36 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
1785 break; 1726 break;
1786 1727
1787 default : 1728 default :
1788 Rest.Log.DebugFormat("{0} Item: Unrecognized attribute: {1}:{2}", 1729 Rest.Log.DebugFormat("{0} Item: Unrecognized attribute: {1}:{2}",
1789 MsgId, ic.xml.Name, ic.xml.Value); 1730 MsgId, ic.xml.Name, ic.xml.Value);
1790 ic.Fail(Rest.HttpStatusCodeBadRequest, String.Format("unrecognized attribute", 1731 ic.Fail(Rest.HttpStatusCodeBadRequest, String.Format("unrecognized attribute",
1791 ic.xml.Name)); 1732 ic.xml.Name));
1792 break; 1733 break;
1793 } 1734 }
1794 } 1735 }
1795 } 1736 }
1796 1737
1797 ic.xml.MoveToElement(); 1738 ic.xml.MoveToElement();
1798 1739
1799 ic.Push(result); 1740 ic.Push(result);
1800
1801 } 1741 }
1802 1742
1803 /// <summary> 1743 /// <summary>
1804 /// This method assembles an asset instance from the 1744 /// This method assembles an asset instance from the
1805 /// information supplied in the request's entity. It is 1745 /// information supplied in the request's entity. It is
1806 /// called as a result of detecting a start tag for a 1746 /// called as a result of detecting a start tag for a
1807 /// type of Asset. 1747 /// type of Asset.
1808 /// The information is collected locally, and an asset 1748 /// The information is collected locally, and an asset
1809 /// instance is created only if the basic XML parsing 1749 /// instance is created only if the basic XML parsing
1810 /// completes successfully. 1750 /// completes successfully.
1811 /// Default values for all parts of the asset are 1751 /// Default values for all parts of the asset are
1812 /// established before overriding them from the supplied 1752 /// established before overriding them from the supplied
1813 /// XML. 1753 /// XML.
1814 /// If an asset has inline=true as an attribute, then 1754 /// If an asset has inline=true as an attribute, then
1815 /// the element contains the data representing the 1755 /// the element contains the data representing the
1816 /// asset. This is saved as the data component. 1756 /// asset. This is saved as the data component.
1817 /// inline=false means that the element's payload is 1757 /// inline=false means that the element's payload is
1818 /// simply the UUID of the asset referenced by the 1758 /// simply the UUID of the asset referenced by the
1819 /// item being constructed. 1759 /// item being constructed.
1820 /// An asset, if created is stored in the 1760 /// An asset, if created is stored in the
1821 /// XmlInventoryCollection 1761 /// XmlInventoryCollection
@@ -1876,9 +1816,9 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
1876 break; 1816 break;
1877 1817
1878 default : 1818 default :
1879 Rest.Log.DebugFormat("{0} Asset: Unrecognized attribute: {1}:{2}", 1819 Rest.Log.DebugFormat("{0} Asset: Unrecognized attribute: {1}:{2}",
1880 MsgId, ic.xml.Name, ic.xml.Value); 1820 MsgId, ic.xml.Name, ic.xml.Value);
1881 ic.Fail(Rest.HttpStatusCodeBadRequest, 1821 ic.Fail(Rest.HttpStatusCodeBadRequest,
1882 String.Format("unrecognized attribute <{0}>", ic.xml.Name)); 1822 String.Format("unrecognized attribute <{0}>", ic.xml.Name));
1883 break; 1823 break;
1884 } 1824 }
@@ -1889,7 +1829,7 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
1889 1829
1890 // If this is a reference to an existing asset, just store the 1830 // If this is a reference to an existing asset, just store the
1891 // asset ID into the item. 1831 // asset ID into the item.
1892 1832
1893 if (!inline) 1833 if (!inline)
1894 { 1834 {
1895 if (ic.Item != null) 1835 if (ic.Item != null)
@@ -1904,13 +1844,12 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
1904 } 1844 }
1905 } 1845 }
1906 1846
1907 // Otherwise, generate an asset ID, store that into the item, and 1847 // Otherwise, generate an asset ID, store that into the item, and
1908 // create an entry in the asset list for the inlined asset. But 1848 // create an entry in the asset list for the inlined asset. But
1909 // only if the size is non-zero. 1849 // only if the size is non-zero.
1910 1850
1911 else 1851 else
1912 { 1852 {
1913
1914 string b64string = null; 1853 string b64string = null;
1915 1854
1916 // Generate a UUID of none were given, and generally none should 1855 // Generate a UUID of none were given, and generally none should
@@ -1923,17 +1862,17 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
1923 1862
1924 // Create AssetBase entity to hold the inlined asset 1863 // Create AssetBase entity to hold the inlined asset
1925 1864
1926 asset = new AssetBase(uuid, name); 1865 asset = new AssetBase(uuid, name);
1927 1866
1928 asset.Description = desc; 1867 asset.Description = desc;
1929 asset.Type = type; // type == 0 == texture 1868 asset.Type = type; // type == 0 == texture
1930 asset.Local = local; 1869 asset.Local = local;
1931 asset.Temporary = temp; 1870 asset.Temporary = temp;
1932 1871
1933 b64string = ic.xml.ReadElementContentAsString(); 1872 b64string = ic.xml.ReadElementContentAsString();
1934 1873
1935 Rest.Log.DebugFormat("{0} Data length is {1}", MsgId, b64string.Length); 1874 Rest.Log.DebugFormat("{0} Data length is {1}", MsgId, b64string.Length);
1936 Rest.Log.DebugFormat("{0} Data content starts with: \n\t<{1}>", MsgId, 1875 Rest.Log.DebugFormat("{0} Data content starts with: \n\t<{1}>", MsgId,
1937 b64string.Substring(0, b64string.Length > 132 ? 132 : b64string.Length)); 1876 b64string.Substring(0, b64string.Length > 132 ? 132 : b64string.Length));
1938 1877
1939 asset.Data = Convert.FromBase64String(b64string); 1878 asset.Data = Convert.FromBase64String(b64string);
@@ -1952,7 +1891,6 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
1952 { 1891 {
1953 ic.Item.AssetID = uuid; 1892 ic.Item.AssetID = uuid;
1954 } 1893 }
1955
1956 } 1894 }
1957 1895
1958 ic.Push(asset); 1896 ic.Push(asset);
@@ -1961,13 +1899,12 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
1961 1899
1962 /// <summary> 1900 /// <summary>
1963 /// Store any permissions information provided by the request. 1901 /// Store any permissions information provided by the request.
1964 /// This overrides the default permissions set when the 1902 /// This overrides the default permissions set when the
1965 /// XmlInventoryCollection object was created. 1903 /// XmlInventoryCollection object was created.
1966 /// </summary> 1904 /// </summary>
1967 1905
1968 private void CollectPermissions(XmlInventoryCollection ic) 1906 private void CollectPermissions(XmlInventoryCollection ic)
1969 { 1907 {
1970
1971 if (ic.xml.HasAttributes) 1908 if (ic.xml.HasAttributes)
1972 { 1909 {
1973 for (int i = 0; i < ic.xml.AttributeCount; i++) 1910 for (int i = 0; i < ic.xml.AttributeCount; i++)
@@ -1990,7 +1927,7 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
1990 default : 1927 default :
1991 Rest.Log.DebugFormat("{0} Permissions: invalid attribute {1}:{2}", 1928 Rest.Log.DebugFormat("{0} Permissions: invalid attribute {1}:{2}",
1992 MsgId,ic.xml.Name, ic.xml.Value); 1929 MsgId,ic.xml.Name, ic.xml.Value);
1993 ic.Fail(Rest.HttpStatusCodeBadRequest, 1930 ic.Fail(Rest.HttpStatusCodeBadRequest,
1994 String.Format("invalid attribute <{0}>", ic.xml.Name)); 1931 String.Format("invalid attribute <{0}>", ic.xml.Name));
1995 break; 1932 break;
1996 } 1933 }
@@ -1998,7 +1935,6 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
1998 } 1935 }
1999 1936
2000 ic.xml.MoveToElement(); 1937 ic.xml.MoveToElement();
2001
2002 } 1938 }
2003 1939
2004 /// <summary> 1940 /// <summary>
@@ -2013,7 +1949,6 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
2013 1949
2014 private void Validate(XmlInventoryCollection ic) 1950 private void Validate(XmlInventoryCollection ic)
2015 { 1951 {
2016
2017 // There really should be an item present if we've 1952 // There really should be an item present if we've
2018 // called validate. So fail if there is not. 1953 // called validate. So fail if there is not.
2019 1954
@@ -2022,7 +1957,7 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
2022 Rest.Log.ErrorFormat("{0} Unable to parse request", MsgId); 1957 Rest.Log.ErrorFormat("{0} Unable to parse request", MsgId);
2023 ic.Fail(Rest.HttpStatusCodeBadRequest, "request parse error"); 1958 ic.Fail(Rest.HttpStatusCodeBadRequest, "request parse error");
2024 } 1959 }
2025 1960
2026 // Every item is required to have a name (via REST anyway) 1961 // Every item is required to have a name (via REST anyway)
2027 1962
2028 if (ic.Item.Name == String.Empty) 1963 if (ic.Item.Name == String.Empty)
@@ -2030,18 +1965,16 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
2030 Rest.Log.ErrorFormat("{0} An item name MUST be specified", MsgId); 1965 Rest.Log.ErrorFormat("{0} An item name MUST be specified", MsgId);
2031 ic.Fail(Rest.HttpStatusCodeBadRequest, "item name required"); 1966 ic.Fail(Rest.HttpStatusCodeBadRequest, "item name required");
2032 } 1967 }
2033 1968
2034 // An item MUST have an asset ID. AssetID should never be zero 1969 // An item MUST have an asset ID. AssetID should never be zero
2035 // here. It should always get set from the information stored 1970 // here. It should always get set from the information stored
2036 // when the Asset element was processed. 1971 // when the Asset element was processed.
2037 1972
2038 if (ic.Item.AssetID == LLUUID.Zero) 1973 if (ic.Item.AssetID == LLUUID.Zero)
2039 { 1974 {
2040
2041 Rest.Log.ErrorFormat("{0} Unable to complete request", MsgId); 1975 Rest.Log.ErrorFormat("{0} Unable to complete request", MsgId);
2042 Rest.Log.InfoFormat("{0} Asset information is missing", MsgId); 1976 Rest.Log.InfoFormat("{0} Asset information is missing", MsgId);
2043 ic.Fail(Rest.HttpStatusCodeBadRequest, "asset information required"); 1977 ic.Fail(Rest.HttpStatusCodeBadRequest, "asset information required");
2044
2045 } 1978 }
2046 1979
2047 // If the item is new, then assign it an ID 1980 // If the item is new, then assign it an ID
@@ -2054,14 +1987,13 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
2054 // If the context is being implied, obtain the current 1987 // If the context is being implied, obtain the current
2055 // folder item's ID. If it was specified explicitly, make 1988 // folder item's ID. If it was specified explicitly, make
2056 // sure that theparent folder exists. 1989 // sure that theparent folder exists.
2057 1990
2058 if (ic.Item.Folder == LLUUID.Zero) 1991 if (ic.Item.Folder == LLUUID.Zero)
2059 { 1992 {
2060 ic.Item.Folder = ic.Parent(); 1993 ic.Item.Folder = ic.Parent();
2061 } 1994 }
2062 else 1995 else
2063 { 1996 {
2064
2065 bool found = false; 1997 bool found = false;
2066 1998
2067 foreach (InventoryFolderBase parent in ic.rdata.folders) 1999 foreach (InventoryFolderBase parent in ic.rdata.folders)
@@ -2075,11 +2007,10 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
2075 2007
2076 if (!found) 2008 if (!found)
2077 { 2009 {
2078 Rest.Log.ErrorFormat("{0} Invalid parent ID ({1}) in item {2}", 2010 Rest.Log.ErrorFormat("{0} Invalid parent ID ({1}) in item {2}",
2079 MsgId, ic.Item.Folder, ic.Item.ID); 2011 MsgId, ic.Item.Folder, ic.Item.ID);
2080 ic.Fail(Rest.HttpStatusCodeBadRequest, "parent information required"); 2012 ic.Fail(Rest.HttpStatusCodeBadRequest, "parent information required");
2081 } 2013 }
2082
2083 } 2014 }
2084 2015
2085 // If this is an inline asset being constructed in the context 2016 // If this is an inline asset being constructed in the context
@@ -2101,13 +2032,12 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
2101 ic.Item.NextPermissions = ic.NextPermissions; 2032 ic.Item.NextPermissions = ic.NextPermissions;
2102 2033
2103 // If no type was specified for this item, we can attempt to 2034 // If no type was specified for this item, we can attempt to
2104 // infer something from the file type maybe. This is NOT as 2035 // infer something from the file type maybe. This is NOT as
2105 // good as having type be specified in the XML. 2036 // good as having type be specified in the XML.
2106 2037
2107 if (ic.Item.AssetType == (int) AssetType.Unknown || 2038 if (ic.Item.AssetType == (int) AssetType.Unknown ||
2108 ic.Item.InvType == (int) AssetType.Unknown) 2039 ic.Item.InvType == (int) AssetType.Unknown)
2109 { 2040 {
2110
2111 Rest.Log.DebugFormat("{0} Attempting to infer item type", MsgId); 2041 Rest.Log.DebugFormat("{0} Attempting to infer item type", MsgId);
2112 2042
2113 string[] parts = ic.Item.Name.Split(Rest.CA_PERIOD); 2043 string[] parts = ic.Item.Name.Split(Rest.CA_PERIOD);
@@ -2127,7 +2057,7 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
2127 2057
2128 if (parts.Length > 1) 2058 if (parts.Length > 1)
2129 { 2059 {
2130 Rest.Log.DebugFormat("{0} File type is {1}", 2060 Rest.Log.DebugFormat("{0} File type is {1}",
2131 MsgId, parts[parts.Length - 1]); 2061 MsgId, parts[parts.Length - 1]);
2132 switch (parts[parts.Length - 1]) 2062 switch (parts[parts.Length - 1])
2133 { 2063 {
@@ -2135,7 +2065,7 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
2135 case "jpeg-2000" : 2065 case "jpeg-2000" :
2136 case "jpg2000" : 2066 case "jpg2000" :
2137 case "jpg-2000" : 2067 case "jpg-2000" :
2138 Rest.Log.DebugFormat("{0} Type {1} inferred", 2068 Rest.Log.DebugFormat("{0} Type {1} inferred",
2139 MsgId, parts[parts.Length-1]); 2069 MsgId, parts[parts.Length-1]);
2140 if (ic.Item.AssetType == (int) AssetType.Unknown) 2070 if (ic.Item.AssetType == (int) AssetType.Unknown)
2141 ic.Item.AssetType = (int) AssetType.ImageJPEG; 2071 ic.Item.AssetType = (int) AssetType.ImageJPEG;
@@ -2144,7 +2074,7 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
2144 break; 2074 break;
2145 case "jpg" : 2075 case "jpg" :
2146 case "jpeg" : 2076 case "jpeg" :
2147 Rest.Log.DebugFormat("{0} Type {1} inferred", 2077 Rest.Log.DebugFormat("{0} Type {1} inferred",
2148 MsgId, parts[parts.Length - 1]); 2078 MsgId, parts[parts.Length - 1]);
2149 if (ic.Item.AssetType == (int) AssetType.Unknown) 2079 if (ic.Item.AssetType == (int) AssetType.Unknown)
2150 ic.Item.AssetType = (int) AssetType.ImageJPEG; 2080 ic.Item.AssetType = (int) AssetType.ImageJPEG;
@@ -2168,7 +2098,7 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
2168 } 2098 }
2169 break; 2099 break;
2170 default : 2100 default :
2171 Rest.Log.DebugFormat("{0} Asset/Inventory type could not be inferred for {1}", 2101 Rest.Log.DebugFormat("{0} Asset/Inventory type could not be inferred for {1}",
2172 MsgId,ic.Item.Name); 2102 MsgId,ic.Item.Name);
2173 break; 2103 break;
2174 } 2104 }
@@ -2186,16 +2116,14 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
2186 temp = OpenJPEGNet.LoadTGAClass.LoadTGA(tgadata); 2116 temp = OpenJPEGNet.LoadTGAClass.LoadTGA(tgadata);
2187 ic.Asset.Data = OpenJPEGNet.OpenJPEG.EncodeFromImage(temp, true); 2117 ic.Asset.Data = OpenJPEGNet.OpenJPEG.EncodeFromImage(temp, true);
2188 } 2118 }
2189
2190 ic.reset();
2191 2119
2120 ic.reset();
2192 } 2121 }
2193 2122
2194 #region Inventory RequestData extension 2123 #region Inventory RequestData extension
2195 2124
2196 internal class InventoryRequestData : RequestData 2125 internal class InventoryRequestData : RequestData
2197 { 2126 {
2198
2199 /// <summary> 2127 /// <summary>
2200 /// These are the inventory specific request/response state 2128 /// These are the inventory specific request/response state
2201 /// extensions. 2129 /// extensions.
@@ -2214,7 +2142,7 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
2214 } 2142 }
2215 2143
2216 /// <summary> 2144 /// <summary>
2217 /// This is the callback method required by inventory services. The 2145 /// This is the callback method required by inventory services. The
2218 /// requestor issues an inventory request and then blocks until this 2146 /// requestor issues an inventory request and then blocks until this
2219 /// method signals the monitor. 2147 /// method signals the monitor.
2220 /// </summary> 2148 /// </summary>
@@ -2230,7 +2158,6 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
2230 Monitor.Pulse(this); 2158 Monitor.Pulse(this);
2231 } 2159 }
2232 } 2160 }
2233
2234 } 2161 }
2235 2162
2236 #endregion Inventory RequestData extension 2163 #endregion Inventory RequestData extension
@@ -2243,7 +2170,6 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
2243 2170
2244 internal class XmlInventoryCollection : InventoryCollection 2171 internal class XmlInventoryCollection : InventoryCollection
2245 { 2172 {
2246
2247 internal InventoryRequestData rdata; 2173 internal InventoryRequestData rdata;
2248 private Stack<InventoryFolderBase> stk; 2174 private Stack<InventoryFolderBase> stk;
2249 2175
@@ -2336,7 +2262,6 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
2336 { 2262 {
2337 rdata.Fail(code, addendum); 2263 rdata.Fail(code, addendum);
2338 } 2264 }
2339
2340 } 2265 }
2341 } 2266 }
2342} 2267}
diff --git a/OpenSim/ApplicationPlugins/Rest/Inventory/tests/Remote.cs b/OpenSim/ApplicationPlugins/Rest/Inventory/tests/Remote.cs
index c50a945..1cbe38f 100644
--- a/OpenSim/ApplicationPlugins/Rest/Inventory/tests/Remote.cs
+++ b/OpenSim/ApplicationPlugins/Rest/Inventory/tests/Remote.cs
@@ -23,7 +23,6 @@
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 *
27 */ 26 */
28 27
29using libsecondlife; 28using libsecondlife;
@@ -41,10 +40,8 @@ using OpenSim.Framework.Communications.Cache;
41 40
42namespace OpenSim.ApplicationPlugins.Rest.Inventory.Tests 41namespace OpenSim.ApplicationPlugins.Rest.Inventory.Tests
43{ 42{
44
45 public class Remote : ITest 43 public class Remote : ITest
46 { 44 {
47
48 private static readonly int PARM_TESTID = 0; 45 private static readonly int PARM_TESTID = 0;
49 private static readonly int PARM_COMMAND = 1; 46 private static readonly int PARM_COMMAND = 1;
50 47
@@ -72,7 +69,7 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory.Tests
72 } 69 }
73 70
74 // Called by the plug-in to halt REST processing. Local processing is 71 // Called by the plug-in to halt REST processing. Local processing is
75 // disabled, and control blocks until all current processing has 72 // disabled, and control blocks until all current processing has
76 // completed. No new processing will be started 73 // completed. No new processing will be started
77 74
78 public void Close() 75 public void Close()
@@ -91,11 +88,10 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory.Tests
91 // Remote Handler 88 // Remote Handler
92 // Key information of interest here is the Parameters array, each 89 // Key information of interest here is the Parameters array, each
93 // entry represents an element of the URI, with element zero being 90 // entry represents an element of the URI, with element zero being
94 // the 91 // the
95 92
96 public void Execute(RequestData rdata) 93 public void Execute(RequestData rdata)
97 { 94 {
98
99 if (!enabled) return; 95 if (!enabled) return;
100 96
101 // If we can't relate to what's there, leave it for others. 97 // If we can't relate to what's there, leave it for others.
@@ -125,7 +121,7 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory.Tests
125 { 121 {
126 DoHelp(rdata); 122 DoHelp(rdata);
127 } 123 }
128 } 124 }
129 125
130 private void DoHelp(RequestData rdata) 126 private void DoHelp(RequestData rdata)
131 { 127 {
@@ -138,7 +134,6 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory.Tests
138 { 134 {
139 if (rdata.Parameters.Length >= 6) 135 if (rdata.Parameters.Length >= 6)
140 { 136 {
141
142 string[] names = rdata.Parameters[PARM_MOVE_AVATAR].Split(Rest.CA_SPACE); 137 string[] names = rdata.Parameters[PARM_MOVE_AVATAR].Split(Rest.CA_SPACE);
143 ScenePresence avatar = null; 138 ScenePresence avatar = null;
144 Scene scene = null; 139 Scene scene = null;
@@ -149,7 +144,7 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory.Tests
149 String.Format("invalid avatar name: <{0}>",rdata.Parameters[PARM_MOVE_AVATAR])); 144 String.Format("invalid avatar name: <{0}>",rdata.Parameters[PARM_MOVE_AVATAR]));
150 } 145 }
151 146
152 Rest.Log.WarnFormat("{0} '{1}' command received for {2} {3}", 147 Rest.Log.WarnFormat("{0} '{1}' command received for {2} {3}",
153 MsgId, rdata.Parameters[0], names[0], names[1]); 148 MsgId, rdata.Parameters[0], names[0], names[1]);
154 149
155 // The first parameter should be an avatar name, look for the 150 // The first parameter should be an avatar name, look for the
@@ -171,8 +166,7 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory.Tests
171 166
172 if (avatar != null) 167 if (avatar != null)
173 { 168 {
174 169 Rest.Log.DebugFormat("{0} Move : Avatar {1} located in region {2}",
175 Rest.Log.DebugFormat("{0} Move : Avatar {1} located in region {2}",
176 MsgId, rdata.Parameters[PARM_MOVE_AVATAR], scene.RegionInfo.RegionName); 170 MsgId, rdata.Parameters[PARM_MOVE_AVATAR], scene.RegionInfo.RegionName);
177 171
178 try 172 try
@@ -185,16 +179,16 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory.Tests
185 } 179 }
186 catch (Exception e) 180 catch (Exception e)
187 { 181 {
188 rdata.Fail(Rest.HttpStatusCodeBadRequest, 182 rdata.Fail(Rest.HttpStatusCodeBadRequest,
189 String.Format("invalid parameters: {0}", e.Message)); 183 String.Format("invalid parameters: {0}", e.Message));
190 } 184 }
191 185
192 } 186 }
193 else 187 else
194 { 188 {
195 rdata.Fail(Rest.HttpStatusCodeBadRequest, 189 rdata.Fail(Rest.HttpStatusCodeBadRequest,
196 String.Format("avatar {0} not present", rdata.Parameters[PARM_MOVE_AVATAR])); 190 String.Format("avatar {0} not present", rdata.Parameters[PARM_MOVE_AVATAR]));
197 } 191 }
198 192
199 rdata.Complete(); 193 rdata.Complete();
200 rdata.Respond("OK"); 194 rdata.Respond("OK");
@@ -205,7 +199,6 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory.Tests
205 Rest.Log.WarnFormat("{0} Move: No movement information provided", MsgId); 199 Rest.Log.WarnFormat("{0} Move: No movement information provided", MsgId);
206 rdata.Fail(Rest.HttpStatusCodeBadRequest, "no movement information provided"); 200 rdata.Fail(Rest.HttpStatusCodeBadRequest, "no movement information provided");
207 } 201 }
208
209 } 202 }
210 203
211 private static readonly string Help = 204 private static readonly string Help =
@@ -220,6 +213,5 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory.Tests
220 + "</body>" 213 + "</body>"
221 + "</html>" 214 + "</html>"
222 ; 215 ;
223
224 } 216 }
225} 217}