diff options
Diffstat (limited to '')
8 files changed, 160 insertions, 65 deletions
diff --git a/OpenSim/ApplicationPlugins/Rest/Inventory/IRestHandler.cs b/OpenSim/ApplicationPlugins/Rest/Inventory/IRestHandler.cs index 82dc2e4..997c2d3 100644 --- a/OpenSim/ApplicationPlugins/Rest/Inventory/IRestHandler.cs +++ b/OpenSim/ApplicationPlugins/Rest/Inventory/IRestHandler.cs | |||
@@ -42,11 +42,8 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory | |||
42 | public delegate RequestData RestMethodAllocator(OSHttpRequest request, OSHttpResponse response, string path); | 42 | public delegate RequestData RestMethodAllocator(OSHttpRequest request, OSHttpResponse response, string path); |
43 | 43 | ||
44 | /// <summary> | 44 | /// <summary> |
45 | /// This interface represents the boundary between the general purpose | 45 | /// This interface exports the generic plugin-handling services |
46 | /// REST plugin handling, and the functionally specific handlers. The | 46 | /// available to each loaded REST services module (IRest implementation) |
47 | /// handler knows only to initialize and terminate all such handlers | ||
48 | /// that it finds. Implementing this interface identifies the class as | ||
49 | /// a REST handler implementation. | ||
50 | /// </summary> | 47 | /// </summary> |
51 | 48 | ||
52 | internal interface IRestHandler | 49 | internal interface IRestHandler |
diff --git a/OpenSim/ApplicationPlugins/Rest/Inventory/RequestData.cs b/OpenSim/ApplicationPlugins/Rest/Inventory/RequestData.cs index 081327e..20e619a 100644 --- a/OpenSim/ApplicationPlugins/Rest/Inventory/RequestData.cs +++ b/OpenSim/ApplicationPlugins/Rest/Inventory/RequestData.cs | |||
@@ -167,7 +167,7 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory | |||
167 | // | 167 | // |
168 | 168 | ||
169 | internal bool authenticated = false; | 169 | internal bool authenticated = false; |
170 | internal string scheme = null; | 170 | internal string scheme = Rest.Scheme; |
171 | internal string realm = Rest.Realm; | 171 | internal string realm = Rest.Realm; |
172 | internal string domain = null; | 172 | internal string domain = null; |
173 | internal string nonce = null; | 173 | internal string nonce = null; |
@@ -287,11 +287,12 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory | |||
287 | 287 | ||
288 | request = p_request; | 288 | request = p_request; |
289 | response = p_response; | 289 | response = p_response; |
290 | qprefix = p_qprefix; | 290 | qprefix = p_qprefix; |
291 | 291 | ||
292 | sbuilder.Length = 0; | 292 | sbuilder.Length = 0; |
293 | 293 | ||
294 | encoding = request.ContentEncoding; | 294 | encoding = request.ContentEncoding; |
295 | |||
295 | if (encoding == null) | 296 | if (encoding == null) |
296 | { | 297 | { |
297 | encoding = Rest.Encoding; | 298 | encoding = Rest.Encoding; |
@@ -448,9 +449,10 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory | |||
448 | 449 | ||
449 | if (realm != null) | 450 | if (realm != null) |
450 | { | 451 | { |
451 | sbuilder.Append(" realm=\""); | 452 | sbuilder.Append(" realm="); |
453 | sbuilder.Append(Rest.CS_DQUOTE); | ||
452 | sbuilder.Append(realm); | 454 | sbuilder.Append(realm); |
453 | sbuilder.Append("\""); | 455 | sbuilder.Append(Rest.CS_DQUOTE); |
454 | } | 456 | } |
455 | AddHeader(Rest.HttpHeaderWWWAuthenticate,sbuilder.ToString()); | 457 | AddHeader(Rest.HttpHeaderWWWAuthenticate,sbuilder.ToString()); |
456 | } | 458 | } |
@@ -677,7 +679,7 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory | |||
677 | 679 | ||
678 | UserProfileData udata = Rest.UserServices.GetUserProfile(first, last); | 680 | UserProfileData udata = Rest.UserServices.GetUserProfile(first, last); |
679 | 681 | ||
680 | // If we don;t recognize the user id, perhaps it is god? | 682 | // If we don't recognize the user id, perhaps it is god? |
681 | 683 | ||
682 | if (udata == null) | 684 | if (udata == null) |
683 | return pass == Rest.GodKey; | 685 | return pass == Rest.GodKey; |
@@ -800,6 +802,7 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory | |||
800 | if (!authparms.ContainsKey("cnonce")) | 802 | if (!authparms.ContainsKey("cnonce")) |
801 | { | 803 | { |
802 | Rest.Log.WarnFormat("{0} Authentication failed: cnonce missing", MsgId); | 804 | Rest.Log.WarnFormat("{0} Authentication failed: cnonce missing", MsgId); |
805 | Fail(Rest.HttpStatusCodeBadRequest); | ||
803 | break; | 806 | break; |
804 | } | 807 | } |
805 | 808 | ||
@@ -808,6 +811,7 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory | |||
808 | if (!authparms.TryGetValue("nc", out nck) || nck == null) | 811 | if (!authparms.TryGetValue("nc", out nck) || nck == null) |
809 | { | 812 | { |
810 | Rest.Log.WarnFormat("{0} Authentication failed: cnonce counter missing", MsgId); | 813 | Rest.Log.WarnFormat("{0} Authentication failed: cnonce counter missing", MsgId); |
814 | Fail(Rest.HttpStatusCodeBadRequest); | ||
811 | break; | 815 | break; |
812 | } | 816 | } |
813 | 817 | ||
@@ -820,6 +824,7 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory | |||
820 | if (Rest.Hex2Int(ncl) >= Rest.Hex2Int(nck)) | 824 | if (Rest.Hex2Int(ncl) >= Rest.Hex2Int(nck)) |
821 | { | 825 | { |
822 | Rest.Log.WarnFormat("{0} Authentication failed: bad cnonce counter", MsgId); | 826 | Rest.Log.WarnFormat("{0} Authentication failed: bad cnonce counter", MsgId); |
827 | Fail(Rest.HttpStatusCodeBadRequest); | ||
823 | break; | 828 | break; |
824 | } | 829 | } |
825 | cntable[nonce] = nck; | 830 | cntable[nonce] = nck; |
@@ -840,11 +845,13 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory | |||
840 | if (authparms.ContainsKey("cnonce")) | 845 | if (authparms.ContainsKey("cnonce")) |
841 | { | 846 | { |
842 | Rest.Log.WarnFormat("{0} Authentication failed: invalid cnonce", MsgId); | 847 | Rest.Log.WarnFormat("{0} Authentication failed: invalid cnonce", MsgId); |
848 | Fail(Rest.HttpStatusCodeBadRequest); | ||
843 | break; | 849 | break; |
844 | } | 850 | } |
845 | if (authparms.ContainsKey("nc")) | 851 | if (authparms.ContainsKey("nc")) |
846 | { | 852 | { |
847 | Rest.Log.WarnFormat("{0} Authentication failed: invalid cnonce counter[2]", MsgId); | 853 | Rest.Log.WarnFormat("{0} Authentication failed: invalid cnonce counter[2]", MsgId); |
854 | Fail(Rest.HttpStatusCodeBadRequest); | ||
848 | break; | 855 | break; |
849 | } | 856 | } |
850 | } | 857 | } |
@@ -857,6 +864,8 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory | |||
857 | while (false); | 864 | while (false); |
858 | 865 | ||
859 | } | 866 | } |
867 | else | ||
868 | Fail(Rest.HttpStatusCodeBadRequest); | ||
860 | 869 | ||
861 | } | 870 | } |
862 | 871 | ||
diff --git a/OpenSim/ApplicationPlugins/Rest/Inventory/Rest.cs b/OpenSim/ApplicationPlugins/Rest/Inventory/Rest.cs index d7935bc..badbb08 100644 --- a/OpenSim/ApplicationPlugins/Rest/Inventory/Rest.cs +++ b/OpenSim/ApplicationPlugins/Rest/Inventory/Rest.cs | |||
@@ -46,6 +46,21 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory | |||
46 | internal static bool DEBUG = Log.IsDebugEnabled; | 46 | internal static bool DEBUG = Log.IsDebugEnabled; |
47 | 47 | ||
48 | /// <summary> | 48 | /// <summary> |
49 | /// Supported authentication schemes | ||
50 | /// </summary> | ||
51 | |||
52 | public const string AS_BASIC = "Basic"; // simple user/password verification | ||
53 | public const string AS_DIGEST = "Digest"; // password safe authentication | ||
54 | |||
55 | /// Supported Digest algorithms | ||
56 | |||
57 | public const string Digest_MD5 = "MD5"; // assumed default if omitted | ||
58 | public const string Digest_MD5Sess = "MD5-sess"; // session-span - not good for REST? | ||
59 | |||
60 | public const string Qop_Auth = "auth"; // authentication only | ||
61 | public const string Qop_Int = "auth-int"; // TODO | ||
62 | |||
63 | /// <summary> | ||
49 | /// These values have a single value for the whole | 64 | /// These values have a single value for the whole |
50 | /// domain and lifetime of the plugin handler. We | 65 | /// domain and lifetime of the plugin handler. We |
51 | /// make them static for ease of reference within | 66 | /// make them static for ease of reference within |
@@ -67,9 +82,10 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory | |||
67 | internal static bool Secure = true; | 82 | internal static bool Secure = true; |
68 | internal static bool ExtendedEscape = true; | 83 | internal static bool ExtendedEscape = true; |
69 | internal static bool DumpAsset = false; | 84 | internal static bool DumpAsset = false; |
70 | internal static bool Fill = true; | 85 | internal static bool Fill = false; |
71 | internal static bool FlushEnabled = true; | 86 | internal static bool FlushEnabled = true; |
72 | internal static string Realm = "REST"; | 87 | internal static string Realm = "OpenSim REST"; |
88 | internal static string Scheme = AS_BASIC; | ||
73 | internal static int DumpLineSize = 32; // Should be a multiple of 16 or (possibly) 4 | 89 | internal static int DumpLineSize = 32; // Should be a multiple of 16 or (possibly) 4 |
74 | 90 | ||
75 | /// <summary> | 91 | /// <summary> |
@@ -383,21 +399,6 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory | |||
383 | public const string HttpHeaderWarning = "Warning"; | 399 | public const string HttpHeaderWarning = "Warning"; |
384 | public const string HttpHeaderWWWAuthenticate = "WWW-Authenticate"; | 400 | public const string HttpHeaderWWWAuthenticate = "WWW-Authenticate"; |
385 | 401 | ||
386 | /// <summary> | ||
387 | /// Supported authentication schemes | ||
388 | /// </summary> | ||
389 | |||
390 | public const string AS_BASIC = "Basic"; | ||
391 | public const string AS_DIGEST = "Digest"; | ||
392 | |||
393 | /// Supported Digest algorithms | ||
394 | |||
395 | public const string Digest_MD5 = "MD5"; // assumed default if omitted | ||
396 | public const string Digest_MD5Sess = "MD5-sess"; | ||
397 | |||
398 | public const string Qop_Auth = "auth"; | ||
399 | public const string Qop_Int = "auth-int"; | ||
400 | |||
401 | /// Utility routines | 402 | /// Utility routines |
402 | 403 | ||
403 | public static string StringToBase64(string str) | 404 | public static string StringToBase64(string str) |
diff --git a/OpenSim/ApplicationPlugins/Rest/Inventory/RestAppearanceServices.cs b/OpenSim/ApplicationPlugins/Rest/Inventory/RestAppearanceServices.cs index 6983154..11cda6e 100644 --- a/OpenSim/ApplicationPlugins/Rest/Inventory/RestAppearanceServices.cs +++ b/OpenSim/ApplicationPlugins/Rest/Inventory/RestAppearanceServices.cs | |||
@@ -63,6 +63,16 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory | |||
63 | Rest.Log.InfoFormat("{0} User appearance services initializing", MsgId); | 63 | Rest.Log.InfoFormat("{0} User appearance services initializing", MsgId); |
64 | Rest.Log.InfoFormat("{0} Using REST Implementation Version {1}", MsgId, Rest.Version); | 64 | Rest.Log.InfoFormat("{0} Using REST Implementation Version {1}", MsgId, Rest.Version); |
65 | 65 | ||
66 | // This is better than a null reference. | ||
67 | |||
68 | if (Rest.AvatarServices == null) | ||
69 | throw new Exception(String.Format("{0} OpenSim inventory services are not available", | ||
70 | MsgId)); | ||
71 | |||
72 | if (Rest.UserServices == null) | ||
73 | throw new Exception(String.Format("{0} OpenSim user profile services are not available", | ||
74 | MsgId)); | ||
75 | |||
66 | // If a relative path was specified for the handler's domain, | 76 | // If a relative path was specified for the handler's domain, |
67 | // add the standard prefix to make it absolute, e.g. /admin | 77 | // add the standard prefix to make it absolute, e.g. /admin |
68 | 78 | ||
@@ -170,9 +180,6 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory | |||
170 | 180 | ||
171 | try | 181 | try |
172 | { | 182 | { |
173 | // digest scheme seems borked: disable it for the time | ||
174 | // being | ||
175 | rdata.scheme = Rest.AS_BASIC; | ||
176 | if (!rdata.IsAuthenticated) | 183 | if (!rdata.IsAuthenticated) |
177 | { | 184 | { |
178 | rdata.Fail(Rest.HttpStatusCodeNotAuthorized,String.Format("user \"{0}\" could not be authenticated", rdata.userName)); | 185 | rdata.Fail(Rest.HttpStatusCodeNotAuthorized,String.Format("user \"{0}\" could not be authenticated", rdata.userName)); |
@@ -731,7 +738,7 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory | |||
731 | 738 | ||
732 | if (asset != UUID.Zero) | 739 | if (asset != UUID.Zero) |
733 | { | 740 | { |
734 | rdata.writer.WriteAttributeString("Item",asset.ToString()); | 741 | rdata.writer.WriteAttributeString("Asset",asset.ToString()); |
735 | } | 742 | } |
736 | rdata.writer.WriteEndElement(); | 743 | rdata.writer.WriteEndElement(); |
737 | } | 744 | } |
diff --git a/OpenSim/ApplicationPlugins/Rest/Inventory/RestAssetServices.cs b/OpenSim/ApplicationPlugins/Rest/Inventory/RestAssetServices.cs index 9af5cd0..f9abc49 100644 --- a/OpenSim/ApplicationPlugins/Rest/Inventory/RestAssetServices.cs +++ b/OpenSim/ApplicationPlugins/Rest/Inventory/RestAssetServices.cs | |||
@@ -52,6 +52,12 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory | |||
52 | Rest.Log.InfoFormat("{0} Asset services initializing", MsgId); | 52 | Rest.Log.InfoFormat("{0} Asset services initializing", MsgId); |
53 | 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); |
54 | 54 | ||
55 | // This is better than a null reference. | ||
56 | |||
57 | if (Rest.AssetServices == null) | ||
58 | throw new Exception(String.Format("{0} OpenSim asset services are not available", | ||
59 | MsgId)); | ||
60 | |||
55 | // If the handler specifies a relative path for its domain | 61 | // If the handler specifies a relative path for its domain |
56 | // then we must add the standard absolute prefix, e.g. /admin | 62 | // then we must add the standard absolute prefix, e.g. /admin |
57 | 63 | ||
@@ -130,9 +136,6 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory | |||
130 | 136 | ||
131 | try | 137 | try |
132 | { | 138 | { |
133 | // digest scheme seems borked: disable it for the time | ||
134 | // being | ||
135 | rdata.scheme = Rest.AS_BASIC; | ||
136 | if (!rdata.IsAuthenticated) | 139 | if (!rdata.IsAuthenticated) |
137 | { | 140 | { |
138 | rdata.Fail(Rest.HttpStatusCodeNotAuthorized, String.Format("user \"{0}\" could not be authenticated")); | 141 | rdata.Fail(Rest.HttpStatusCodeNotAuthorized, String.Format("user \"{0}\" could not be authenticated")); |
diff --git a/OpenSim/ApplicationPlugins/Rest/Inventory/RestHandler.cs b/OpenSim/ApplicationPlugins/Rest/Inventory/RestHandler.cs index fd4c295..c022e09 100644 --- a/OpenSim/ApplicationPlugins/Rest/Inventory/RestHandler.cs +++ b/OpenSim/ApplicationPlugins/Rest/Inventory/RestHandler.cs | |||
@@ -239,14 +239,17 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory | |||
239 | Rest.Prefix = Prefix; | 239 | Rest.Prefix = Prefix; |
240 | Rest.GodKey = GodKey; | 240 | Rest.GodKey = GodKey; |
241 | 241 | ||
242 | Rest.Authenticate = Rest.Config.GetBoolean("authenticate",true); | 242 | Rest.Authenticate = Rest.Config.GetBoolean("authenticate", Rest.Authenticate); |
243 | Rest.Secure = Rest.Config.GetBoolean("secured",true); | 243 | Rest.Scheme = Rest.Config.GetString("auth-scheme", Rest.Scheme); |
244 | Rest.ExtendedEscape = Rest.Config.GetBoolean("extended-escape",true); | 244 | Rest.Secure = Rest.Config.GetBoolean("secured", Rest.Secure); |
245 | Rest.Realm = Rest.Config.GetString("realm","OpenSim REST"); | 245 | Rest.ExtendedEscape = Rest.Config.GetBoolean("extended-escape", Rest.ExtendedEscape); |
246 | Rest.DumpAsset = Rest.Config.GetBoolean("dump-asset",false); | 246 | Rest.Realm = Rest.Config.GetString("realm", Rest.Realm); |
247 | Rest.Fill = Rest.Config.GetBoolean("path-fill",true); | 247 | Rest.DumpAsset = Rest.Config.GetBoolean("dump-asset", Rest.DumpAsset); |
248 | Rest.DumpLineSize = Rest.Config.GetInt("dump-line-size",32); | 248 | Rest.Fill = Rest.Config.GetBoolean("path-fill", Rest.Fill); |
249 | Rest.FlushEnabled = Rest.Config.GetBoolean("flush-on-error",true); | 249 | Rest.DumpLineSize = Rest.Config.GetInt("dump-line-size", Rest.DumpLineSize); |
250 | Rest.FlushEnabled = Rest.Config.GetBoolean("flush-on-error", Rest.FlushEnabled); | ||
251 | |||
252 | // Note: Odd spacing is required in the following strings | ||
250 | 253 | ||
251 | Rest.Log.InfoFormat("{0} Authentication is {1}required", MsgId, | 254 | Rest.Log.InfoFormat("{0} Authentication is {1}required", MsgId, |
252 | (Rest.Authenticate ? "" : "not ")); | 255 | (Rest.Authenticate ? "" : "not ")); |
@@ -374,13 +377,13 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory | |||
374 | 377 | ||
375 | string path = request.RawUrl.ToLower(); | 378 | string path = request.RawUrl.ToLower(); |
376 | 379 | ||
377 | Rest.Log.DebugFormat("{0} Match ENTRY", MsgId); | 380 | // Rest.Log.DebugFormat("{0} Match ENTRY", MsgId); |
378 | 381 | ||
379 | try | 382 | try |
380 | { | 383 | { |
381 | foreach (string key in pathHandlers.Keys) | 384 | foreach (string key in pathHandlers.Keys) |
382 | { | 385 | { |
383 | Rest.Log.DebugFormat("{0} Match testing {1} against agent prefix <{2}>", MsgId, path, key); | 386 | // Rest.Log.DebugFormat("{0} Match testing {1} against agent prefix <{2}>", MsgId, path, key); |
384 | 387 | ||
385 | // Note that Match will not necessarily find the handler that will | 388 | // Note that Match will not necessarily find the handler that will |
386 | // actually be used - it does no test for the "closest" fit. It | 389 | // actually be used - it does no test for the "closest" fit. It |
@@ -388,7 +391,7 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory | |||
388 | 391 | ||
389 | if (path.StartsWith(key)) | 392 | if (path.StartsWith(key)) |
390 | { | 393 | { |
391 | Rest.Log.DebugFormat("{0} Matched prefix <{1}>", MsgId, key); | 394 | // Rest.Log.DebugFormat("{0} Matched prefix <{1}>", MsgId, key); |
392 | 395 | ||
393 | // This apparently odd evaluation is needed to prevent a match | 396 | // This apparently odd evaluation is needed to prevent a match |
394 | // on anything other than a URI token boundary. Otherwise we | 397 | // on anything other than a URI token boundary. Otherwise we |
@@ -404,7 +407,7 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory | |||
404 | 407 | ||
405 | foreach (string key in streamHandlers.Keys) | 408 | foreach (string key in streamHandlers.Keys) |
406 | { | 409 | { |
407 | Rest.Log.DebugFormat("{0} Match testing {1} against stream prefix <{2}>", MsgId, path, key); | 410 | // Rest.Log.DebugFormat("{0} Match testing {1} against stream prefix <{2}>", MsgId, path, key); |
408 | 411 | ||
409 | // Note that Match will not necessarily find the handler that will | 412 | // Note that Match will not necessarily find the handler that will |
410 | // actually be used - it does no test for the "closest" fit. It | 413 | // actually be used - it does no test for the "closest" fit. It |
@@ -412,7 +415,7 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory | |||
412 | 415 | ||
413 | if (path.StartsWith(key)) | 416 | if (path.StartsWith(key)) |
414 | { | 417 | { |
415 | Rest.Log.DebugFormat("{0} Matched prefix <{1}>", MsgId, key); | 418 | // Rest.Log.DebugFormat("{0} Matched prefix <{1}>", MsgId, key); |
416 | 419 | ||
417 | // This apparently odd evaluation is needed to prevent a match | 420 | // This apparently odd evaluation is needed to prevent a match |
418 | // on anything other than a URI token boundary. Otherwise we | 421 | // on anything other than a URI token boundary. Otherwise we |
@@ -434,7 +437,7 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory | |||
434 | 437 | ||
435 | /// <summary> | 438 | /// <summary> |
436 | /// This is called by the HTTP server once the handler has indicated | 439 | /// This is called by the HTTP server once the handler has indicated |
437 | /// that t is able to handle the request. | 440 | /// that it is able to handle the request. |
438 | /// Preconditions: | 441 | /// Preconditions: |
439 | /// [1] request != null and is a valid request object | 442 | /// [1] request != null and is a valid request object |
440 | /// [2] response != null and is a valid response object | 443 | /// [2] response != null and is a valid response object |
@@ -474,7 +477,11 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory | |||
474 | { | 477 | { |
475 | // A raw exception indicates that something we weren't expecting has | 478 | // A raw exception indicates that something we weren't expecting has |
476 | // happened. This should always reflect a shortcoming in the plugin, | 479 | // happened. This should always reflect a shortcoming in the plugin, |
477 | // or a failure to satisfy the preconditions. | 480 | // or a failure to satisfy the preconditions. It should not reflect |
481 | // an error in the request itself. Under such circumstances the state | ||
482 | // of the request cannot be determined and we are obliged to mark it | ||
483 | // as 'handled'. | ||
484 | |||
478 | Rest.Log.ErrorFormat("{0} Plugin error: {1}", MsgId, e.Message); | 485 | Rest.Log.ErrorFormat("{0} Plugin error: {1}", MsgId, e.Message); |
479 | handled = true; | 486 | handled = true; |
480 | } | 487 | } |
@@ -497,7 +504,7 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory | |||
497 | { | 504 | { |
498 | RequestData rdata = new RequestData(request, response, String.Empty); | 505 | RequestData rdata = new RequestData(request, response, String.Empty); |
499 | 506 | ||
500 | string bestMatch = null; | 507 | string bestMatch = String.Empty; |
501 | string path = String.Format("{0}:{1}", rdata.method, rdata.path).ToLower(); | 508 | string path = String.Format("{0}:{1}", rdata.method, rdata.path).ToLower(); |
502 | 509 | ||
503 | Rest.Log.DebugFormat("{0} Checking for stream handler for <{1}>", MsgId, path); | 510 | Rest.Log.DebugFormat("{0} Checking for stream handler for <{1}>", MsgId, path); |
@@ -511,7 +518,7 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory | |||
511 | { | 518 | { |
512 | if (path.StartsWith(pattern)) | 519 | if (path.StartsWith(pattern)) |
513 | { | 520 | { |
514 | if (String.IsNullOrEmpty(bestMatch) || pattern.Length > bestMatch.Length) | 521 | if (pattern.Length > bestMatch.Length) |
515 | { | 522 | { |
516 | bestMatch = pattern; | 523 | bestMatch = pattern; |
517 | } | 524 | } |
@@ -520,7 +527,7 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory | |||
520 | 527 | ||
521 | // Handle using the best match available | 528 | // Handle using the best match available |
522 | 529 | ||
523 | if (!String.IsNullOrEmpty(bestMatch)) | 530 | if (bestMatch.Length > 0) |
524 | { | 531 | { |
525 | Rest.Log.DebugFormat("{0} Stream-based handler matched with <{1}>", MsgId, bestMatch); | 532 | Rest.Log.DebugFormat("{0} Stream-based handler matched with <{1}>", MsgId, bestMatch); |
526 | RestStreamHandler handler = streamHandlers[bestMatch]; | 533 | RestStreamHandler handler = streamHandlers[bestMatch]; |
diff --git a/OpenSim/ApplicationPlugins/Rest/Inventory/RestInventoryServices.cs b/OpenSim/ApplicationPlugins/Rest/Inventory/RestInventoryServices.cs index 9cbbf0c..003c6ee 100644 --- a/OpenSim/ApplicationPlugins/Rest/Inventory/RestInventoryServices.cs +++ b/OpenSim/ApplicationPlugins/Rest/Inventory/RestInventoryServices.cs | |||
@@ -31,6 +31,7 @@ using System.IO; | |||
31 | using System.Threading; | 31 | using System.Threading; |
32 | using System.Xml; | 32 | using System.Xml; |
33 | using System.Drawing; | 33 | using System.Drawing; |
34 | using System.Timers; | ||
34 | using OpenSim.Framework; | 35 | using OpenSim.Framework; |
35 | using OpenSim.Framework.Servers; | 36 | using OpenSim.Framework.Servers; |
36 | using OpenSim.Framework.Communications; | 37 | using OpenSim.Framework.Communications; |
@@ -61,6 +62,20 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory | |||
61 | Rest.Log.InfoFormat("{0} Inventory services initializing", MsgId); | 62 | Rest.Log.InfoFormat("{0} Inventory services initializing", MsgId); |
62 | Rest.Log.InfoFormat("{0} Using REST Implementation Version {1}", MsgId, Rest.Version); | 63 | Rest.Log.InfoFormat("{0} Using REST Implementation Version {1}", MsgId, Rest.Version); |
63 | 64 | ||
65 | // This is better than a null reference. | ||
66 | |||
67 | if (Rest.InventoryServices == null) | ||
68 | throw new Exception(String.Format("{0} OpenSim inventory services are not available", | ||
69 | MsgId)); | ||
70 | |||
71 | if (Rest.UserServices == null) | ||
72 | throw new Exception(String.Format("{0} OpenSim user services are not available", | ||
73 | MsgId)); | ||
74 | |||
75 | if (Rest.AssetServices == null) | ||
76 | throw new Exception(String.Format("{0} OpenSim asset services are not available", | ||
77 | MsgId)); | ||
78 | |||
64 | // If a relative path was specified for the handler's domain, | 79 | // If a relative path was specified for the handler's domain, |
65 | // add the standard prefix to make it absolute, e.g. /admin | 80 | // add the standard prefix to make it absolute, e.g. /admin |
66 | 81 | ||
@@ -167,9 +182,6 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory | |||
167 | 182 | ||
168 | try | 183 | try |
169 | { | 184 | { |
170 | // digest scheme seems borked: disable it for the time | ||
171 | // being | ||
172 | rdata.scheme = Rest.AS_BASIC; | ||
173 | if (!rdata.IsAuthenticated) | 185 | if (!rdata.IsAuthenticated) |
174 | { | 186 | { |
175 | rdata.Fail(Rest.HttpStatusCodeNotAuthorized,String.Format("user \"{0}\" could not be authenticated", rdata.userName)); | 187 | rdata.Fail(Rest.HttpStatusCodeNotAuthorized,String.Format("user \"{0}\" could not be authenticated", rdata.userName)); |
@@ -283,12 +295,22 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory | |||
283 | Rest.Log.DebugFormat("{0} Inventory catalog requested for {1} {2}", | 295 | Rest.Log.DebugFormat("{0} Inventory catalog requested for {1} {2}", |
284 | MsgId, rdata.userProfile.FirstName, rdata.userProfile.SurName); | 296 | MsgId, rdata.userProfile.FirstName, rdata.userProfile.SurName); |
285 | 297 | ||
286 | lock (rdata) | 298 | |
299 | lock (rdata) | ||
300 | { | ||
301 | if (!rdata.HaveInventory) | ||
302 | { | ||
303 | rdata.startWD(1000); | ||
304 | rdata.timeout = false; | ||
305 | Monitor.Wait(rdata); | ||
306 | } | ||
307 | } | ||
308 | |||
309 | if (rdata.timeout) | ||
287 | { | 310 | { |
288 | if (!rdata.HaveInventory) | 311 | Rest.Log.WarnFormat("{0} Inventory not available for {1} {2}. No response from service.", |
289 | { | 312 | MsgId, rdata.userProfile.FirstName, rdata.userProfile.SurName); |
290 | Monitor.Wait(rdata); | 313 | rdata.Fail(Rest.HttpStatusCodeServerError, "inventory server not responding"); |
291 | } | ||
292 | } | 314 | } |
293 | 315 | ||
294 | if (rdata.root == null) | 316 | if (rdata.root == null) |
@@ -2145,12 +2167,50 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory | |||
2145 | internal ICollection<InventoryItemBase> items = null; | 2167 | internal ICollection<InventoryItemBase> items = null; |
2146 | internal UserProfileData userProfile = null; | 2168 | internal UserProfileData userProfile = null; |
2147 | internal InventoryFolderBase root = null; | 2169 | internal InventoryFolderBase root = null; |
2170 | internal bool timeout = false; | ||
2171 | internal System.Timers.Timer watchDog = new System.Timers.Timer(); | ||
2148 | 2172 | ||
2149 | internal InventoryRequestData(OSHttpRequest request, OSHttpResponse response, string prefix) | 2173 | internal InventoryRequestData(OSHttpRequest request, OSHttpResponse response, string prefix) |
2150 | : base(request, response, prefix) | 2174 | : base(request, response, prefix) |
2151 | { | 2175 | { |
2152 | } | 2176 | } |
2153 | 2177 | ||
2178 | internal void startWD(double interval) | ||
2179 | { | ||
2180 | Rest.Log.DebugFormat("{0} Setting watchdog", MsgId); | ||
2181 | watchDog.Elapsed += new ElapsedEventHandler(OnTimeOut); | ||
2182 | watchDog.Interval = interval; | ||
2183 | watchDog.AutoReset = false; | ||
2184 | watchDog.Enabled = true; | ||
2185 | watchDog.Start(); | ||
2186 | } | ||
2187 | |||
2188 | internal void stopWD() | ||
2189 | { | ||
2190 | Rest.Log.DebugFormat("{0} Reset watchdog", MsgId); | ||
2191 | watchDog.Stop(); | ||
2192 | } | ||
2193 | |||
2194 | /// <summary> | ||
2195 | /// This is the callback method required by the inventory watchdog. The | ||
2196 | /// requestor issues an inventory request and then blocks until the | ||
2197 | /// request completes, or this method signals the monitor. | ||
2198 | /// </summary> | ||
2199 | |||
2200 | private void OnTimeOut(object sender, ElapsedEventArgs args) | ||
2201 | { | ||
2202 | Rest.Log.DebugFormat("{0} Asynchronous inventory update timed-out", MsgId); | ||
2203 | // InventoryRequestData rdata = (InventoryRequestData) sender; | ||
2204 | lock (this) | ||
2205 | { | ||
2206 | this.folders = null; | ||
2207 | this.items = null; | ||
2208 | this.HaveInventory = false; | ||
2209 | this.timeout = true; | ||
2210 | Monitor.Pulse(this); | ||
2211 | } | ||
2212 | } | ||
2213 | |||
2154 | /// <summary> | 2214 | /// <summary> |
2155 | /// This is the callback method required by inventory services. The | 2215 | /// This is the callback method required by inventory services. The |
2156 | /// requestor issues an inventory request and then blocks until this | 2216 | /// requestor issues an inventory request and then blocks until this |
@@ -2160,11 +2220,16 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory | |||
2160 | internal void GetUserInventory(ICollection<InventoryFolderImpl> folders, ICollection<InventoryItemBase> items) | 2220 | internal void GetUserInventory(ICollection<InventoryFolderImpl> folders, ICollection<InventoryItemBase> items) |
2161 | { | 2221 | { |
2162 | Rest.Log.DebugFormat("{0} Asynchronously updating inventory data", MsgId); | 2222 | Rest.Log.DebugFormat("{0} Asynchronously updating inventory data", MsgId); |
2163 | this.folders = folders; | ||
2164 | this.items = items; | ||
2165 | this.HaveInventory = true; | ||
2166 | lock (this) | 2223 | lock (this) |
2167 | { | 2224 | { |
2225 | if (watchDog.Enabled) | ||
2226 | { | ||
2227 | this.stopWD(); | ||
2228 | } | ||
2229 | this.folders = folders; | ||
2230 | this.items = items; | ||
2231 | this.HaveInventory = true; | ||
2232 | this.timeout = false; | ||
2168 | Monitor.Pulse(this); | 2233 | Monitor.Pulse(this); |
2169 | } | 2234 | } |
2170 | } | 2235 | } |
diff --git a/OpenSim/Framework/Communications/Cache/LibraryRootFolder.cs b/OpenSim/Framework/Communications/Cache/LibraryRootFolder.cs index a33fa67..437e5e4 100644 --- a/OpenSim/Framework/Communications/Cache/LibraryRootFolder.cs +++ b/OpenSim/Framework/Communications/Cache/LibraryRootFolder.cs | |||
@@ -178,8 +178,14 @@ namespace OpenSim.Framework.Communications.Cache | |||
178 | if (libraryFolders.ContainsKey(item.Folder)) | 178 | if (libraryFolders.ContainsKey(item.Folder)) |
179 | { | 179 | { |
180 | InventoryFolderImpl parentFolder = libraryFolders[item.Folder]; | 180 | InventoryFolderImpl parentFolder = libraryFolders[item.Folder]; |
181 | 181 | try | |
182 | parentFolder.Items.Add(item.ID, item); | 182 | { |
183 | parentFolder.Items.Add(item.ID, item); | ||
184 | } | ||
185 | catch (Exception) | ||
186 | { | ||
187 | m_log.WarnFormat("[LIBRARY INVENTORY] Item {1} [{0}] not added, duplicate item", item.ID, item.Name); | ||
188 | } | ||
183 | } | 189 | } |
184 | else | 190 | else |
185 | { | 191 | { |