/// <summary> /// This method implements GET processing for user's appearance. /// </summary> /// <param name=rdata>HTTP service request work area</param> private void DoGet(AppearanceRequestData rdata) { rdata.userAppearance = Rest.AvatarServices.GetUserAppearance(rdata.userProfile.ID); if (rdata.userAppearance == null) { rdata.Fail(Rest.HttpStatusCodeNoContent, String.Format("appearance data not found for user {0} {1}", rdata.userProfile.FirstName, rdata.userProfile.SurName)); } rdata.initXmlWriter(); FormatUserAppearance(rdata); // Indicate a successful request rdata.Complete(); // Send the response to the user. The body will be implicitly // constructed from the result of the XML writer. rdata.Respond(String.Format("Appearance {0} Normal completion", rdata.method)); }
/// <summary> /// This method is registered with the handler when this service provider /// is initialized. It is called whenever the plug-in identifies this service /// provider as the best match for a given request. /// It handles all aspects of inventory REST processing, i.e. /admin/inventory /// </summary> /// <param name=hdata>A consolidated HTTP request work area</param> private void DoAppearance(RequestData hdata) { AppearanceRequestData rdata = (AppearanceRequestData)hdata; Rest.Log.DebugFormat("{0} DoAppearance ENTRY", MsgId); // If we're disabled, do nothing. if (!enabled) { return; } // Now that we know this is a serious attempt to // access inventory data, we should find out who // is asking, and make sure they are authorized // to do so. We need to validate the caller's // identity before revealing anything about the // status quo. Authenticate throws an exception // via Fail if no identity information is present. // // With the present HTTP server we can't use the // builtin authentication mechanisms because they // would be enforced for all in-bound requests. // Instead we look at the headers ourselves and // handle authentication directly. try { if (!rdata.IsAuthenticated) { rdata.Fail(Rest.HttpStatusCodeNotAuthorized, String.Format("user \"{0}\" could not be authenticated", rdata.userName)); } } catch (RestException e) { if (e.statusCode == Rest.HttpStatusCodeNotAuthorized) { Rest.Log.WarnFormat("{0} User not authenticated", MsgId); Rest.Log.DebugFormat("{0} Authorization header: {1}", MsgId, rdata.request.Headers.Get("Authorization")); } else { Rest.Log.ErrorFormat("{0} User authentication failed", MsgId); Rest.Log.DebugFormat("{0} Authorization header: {1}", MsgId, rdata.request.Headers.Get("Authorization")); } throw (e); } Rest.Log.DebugFormat("{0} Authenticated {1}", MsgId, rdata.userName); // We can only get here if we are authorized // // The requestor may have specified an UUID or // a conjoined FirstName LastName string. We'll // try both. If we fail with the first, UUID, // attempt, we try the other. As an example, the // URI for a valid inventory request might be: // // http://<host>:<port>/admin/inventory/Arthur Dent // // Indicating that this is an inventory request for // an avatar named Arthur Dent. This is ALL that is // required to designate a GET for an entire // inventory. // // Do we have at least a user agent name? if (rdata.Parameters.Length < 1) { Rest.Log.WarnFormat("{0} Appearance: No user agent identifier specified", MsgId); rdata.Fail(Rest.HttpStatusCodeBadRequest, "no user identity specified"); } // The first parameter MUST be the agent identification, either an UUID // or a space-separated First-name Last-Name specification. We check for // an UUID first, if anyone names their character using a valid UUID // that identifies another existing avatar will cause this a problem... try { rdata.uuid = new UUID(rdata.Parameters[PARM_USERID]); Rest.Log.DebugFormat("{0} UUID supplied", MsgId); rdata.userProfile = Rest.UserServices.GetUserProfile(rdata.uuid); } catch { string[] names = rdata.Parameters[PARM_USERID].Split(Rest.CA_SPACE); if (names.Length == 2) { Rest.Log.DebugFormat("{0} Agent Name supplied [2]", MsgId); rdata.userProfile = Rest.UserServices.GetUserProfile(names[0], names[1]); } else { Rest.Log.WarnFormat("{0} A Valid UUID or both first and last names must be specified", MsgId); rdata.Fail(Rest.HttpStatusCodeBadRequest, "invalid user identity"); } } // If the user profile is null then either the server is broken, or the // user is not known. We always assume the latter case. if (rdata.userProfile != null) { Rest.Log.DebugFormat("{0} User profile obtained for agent {1} {2}", MsgId, rdata.userProfile.FirstName, rdata.userProfile.SurName); } else { Rest.Log.WarnFormat("{0} No user profile for {1}", MsgId, rdata.path); rdata.Fail(Rest.HttpStatusCodeNotFound, "unrecognized user identity"); } // If we get to here, then we have effectively validated the user's switch (rdata.method) { case Rest.HEAD: // Do the processing, set the status code, suppress entity DoGet(rdata); rdata.buffer = null; break; case Rest.GET: // Do the processing, set the status code, return entity DoGet(rdata); break; case Rest.PUT: // Update named element DoUpdate(rdata); break; case Rest.POST: // Add new information to identified context. DoExtend(rdata); break; case Rest.DELETE: // Delete information DoDelete(rdata); break; default: Rest.Log.WarnFormat("{0} Method {1} not supported for {2}", MsgId, rdata.method, rdata.path); rdata.Fail(Rest.HttpStatusCodeMethodNotAllowed, String.Format("{0} not supported", rdata.method)); break; } }