RestAppearanceServices.cs 37 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860
  1. /*
  2. * Copyright (c) Contributors, http://opensimulator.org/
  3. * See CONTRIBUTORS.TXT for a full list of copyright holders.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions are met:
  7. * * Redistributions of source code must retain the above copyright
  8. * notice, this list of conditions and the following disclaimer.
  9. * * Redistributions in binary form must reproduce the above copyright
  10. * notice, this list of conditions and the following disclaimer in the
  11. * documentation and/or other materials provided with the distribution.
  12. * * Neither the name of the OpenSimulator Project nor the
  13. * names of its contributors may be used to endorse or promote products
  14. * derived from this software without specific prior written permission.
  15. *
  16. * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
  17. * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  18. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  19. * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
  20. * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  21. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  22. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  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
  25. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  26. */
  27. using System;
  28. using System.Collections;
  29. using System.Collections.Generic;
  30. using System.Xml;
  31. using OpenMetaverse;
  32. using OpenSim.Framework;
  33. using OpenSim.Framework.Servers;
  34. using OpenSim.Framework.Servers.HttpServer;
  35. using OpenSim.Services.Interfaces;
  36. namespace OpenSim.ApplicationPlugins.Rest.Inventory
  37. {
  38. public class RestAppearanceServices : IRest
  39. {
  40. // private static readonly int PARM_USERID = 0;
  41. // private static readonly int PARM_PATH = 1;
  42. // private bool enabled = false;
  43. private string qPrefix = "appearance";
  44. /// <summary>
  45. /// The constructor makes sure that the service prefix is absolute
  46. /// and the registers the service handler and the allocator.
  47. /// </summary>
  48. public RestAppearanceServices()
  49. {
  50. Rest.Log.InfoFormat("{0} User appearance services initializing", MsgId);
  51. Rest.Log.InfoFormat("{0} Using REST Implementation Version {1}", MsgId, Rest.Version);
  52. // If a relative path was specified for the handler's domain,
  53. // add the standard prefix to make it absolute, e.g. /admin
  54. if (!qPrefix.StartsWith(Rest.UrlPathSeparator))
  55. {
  56. Rest.Log.InfoFormat("{0} Domain is relative, adding absolute prefix", MsgId);
  57. qPrefix = String.Format("{0}{1}{2}", Rest.Prefix, Rest.UrlPathSeparator, qPrefix);
  58. qPrefix = String.Format("{0}{1}{2}", Rest.Prefix, Rest.UrlPathSeparator, qPrefix);
  59. Rest.Log.InfoFormat("{0} Domain is now <{1}>", MsgId, qPrefix);
  60. }
  61. // Register interface using the absolute URI.
  62. Rest.Plugin.AddPathHandler(DoAppearance,qPrefix,Allocate);
  63. // Activate if everything went OK
  64. // enabled = true;
  65. Rest.Log.InfoFormat("{0} User appearance services initialization complete", MsgId);
  66. }
  67. /// <summary>
  68. /// Post-construction, pre-enabled initialization opportunity
  69. /// Not currently exploited.
  70. /// </summary>
  71. public void Initialize()
  72. {
  73. }
  74. /// <summary>
  75. /// Called by the plug-in to halt service processing. Local processing is
  76. /// disabled.
  77. /// </summary>
  78. public void Close()
  79. {
  80. // enabled = false;
  81. Rest.Log.InfoFormat("{0} User appearance services closing down", MsgId);
  82. }
  83. /// <summary>
  84. /// This property is declared locally because it is used a lot and
  85. /// brevity is nice.
  86. /// </summary>
  87. internal string MsgId
  88. {
  89. get { return Rest.MsgId; }
  90. }
  91. #region Interface
  92. /// <summary>
  93. /// The plugin (RestHandler) calls this method to allocate the request
  94. /// state carrier for a new request. It is destroyed when the request
  95. /// completes. All request-instance specific state is kept here. This
  96. /// is registered when this service provider is registered.
  97. /// </summary>
  98. /// <param name=request>Inbound HTTP request information</param>
  99. /// <param name=response>Outbound HTTP request information</param>
  100. /// <param name=qPrefix>REST service domain prefix</param>
  101. /// <returns>A RequestData instance suitable for this service</returns>
  102. private RequestData Allocate(OSHttpRequest request, OSHttpResponse response, string prefix)
  103. {
  104. return (RequestData) new AppearanceRequestData(request, response, prefix);
  105. }
  106. /// <summary>
  107. /// This method is registered with the handler when this service provider
  108. /// is initialized. It is called whenever the plug-in identifies this service
  109. /// provider as the best match for a given request.
  110. /// It handles all aspects of inventory REST processing, i.e. /admin/inventory
  111. /// </summary>
  112. /// <param name=hdata>A consolidated HTTP request work area</param>
  113. private void DoAppearance(RequestData hdata)
  114. {
  115. // !!! REFACTORIMG PROBLEM. This needs rewriting for 0.7
  116. //AppearanceRequestData rdata = (AppearanceRequestData) hdata;
  117. //Rest.Log.DebugFormat("{0} DoAppearance ENTRY", MsgId);
  118. //// If we're disabled, do nothing.
  119. //if (!enabled)
  120. //{
  121. // return;
  122. //}
  123. //// Now that we know this is a serious attempt to
  124. //// access inventory data, we should find out who
  125. //// is asking, and make sure they are authorized
  126. //// to do so. We need to validate the caller's
  127. //// identity before revealing anything about the
  128. //// status quo. Authenticate throws an exception
  129. //// via Fail if no identity information is present.
  130. ////
  131. //// With the present HTTP server we can't use the
  132. //// builtin authentication mechanisms because they
  133. //// would be enforced for all in-bound requests.
  134. //// Instead we look at the headers ourselves and
  135. //// handle authentication directly.
  136. //try
  137. //{
  138. // if (!rdata.IsAuthenticated)
  139. // {
  140. // rdata.Fail(Rest.HttpStatusCodeNotAuthorized,String.Format("user \"{0}\" could not be authenticated", rdata.userName));
  141. // }
  142. //}
  143. //catch (RestException e)
  144. //{
  145. // if (e.statusCode == Rest.HttpStatusCodeNotAuthorized)
  146. // {
  147. // Rest.Log.WarnFormat("{0} User not authenticated", MsgId);
  148. // Rest.Log.DebugFormat("{0} Authorization header: {1}", MsgId, rdata.request.Headers.Get("Authorization"));
  149. // }
  150. // else
  151. // {
  152. // Rest.Log.ErrorFormat("{0} User authentication failed", MsgId);
  153. // Rest.Log.DebugFormat("{0} Authorization header: {1}", MsgId, rdata.request.Headers.Get("Authorization"));
  154. // }
  155. // throw (e);
  156. //}
  157. //Rest.Log.DebugFormat("{0} Authenticated {1}", MsgId, rdata.userName);
  158. //// We can only get here if we are authorized
  159. ////
  160. //// The requestor may have specified an UUID or
  161. //// a conjoined FirstName LastName string. We'll
  162. //// try both. If we fail with the first, UUID,
  163. //// attempt, we try the other. As an example, the
  164. //// URI for a valid inventory request might be:
  165. ////
  166. //// http://<host>:<port>/admin/inventory/Arthur Dent
  167. ////
  168. //// Indicating that this is an inventory request for
  169. //// an avatar named Arthur Dent. This is ALL that is
  170. //// required to designate a GET for an entire
  171. //// inventory.
  172. ////
  173. //// Do we have at least a user agent name?
  174. //if (rdata.Parameters.Length < 1)
  175. //{
  176. // Rest.Log.WarnFormat("{0} Appearance: No user agent identifier specified", MsgId);
  177. // rdata.Fail(Rest.HttpStatusCodeBadRequest, "no user identity specified");
  178. //}
  179. //// The first parameter MUST be the agent identification, either an UUID
  180. //// or a space-separated First-name Last-Name specification. We check for
  181. //// an UUID first, if anyone names their character using a valid UUID
  182. //// that identifies another existing avatar will cause this a problem...
  183. //try
  184. //{
  185. // rdata.uuid = new UUID(rdata.Parameters[PARM_USERID]);
  186. // Rest.Log.DebugFormat("{0} UUID supplied", MsgId);
  187. // rdata.userProfile = Rest.UserServices.GetUserProfile(rdata.uuid);
  188. //}
  189. //catch
  190. //{
  191. // string[] names = rdata.Parameters[PARM_USERID].Split(Rest.CA_SPACE);
  192. // if (names.Length == 2)
  193. // {
  194. // Rest.Log.DebugFormat("{0} Agent Name supplied [2]", MsgId);
  195. // rdata.userProfile = Rest.UserServices.GetUserProfile(names[0],names[1]);
  196. // }
  197. // else
  198. // {
  199. // Rest.Log.WarnFormat("{0} A Valid UUID or both first and last names must be specified", MsgId);
  200. // rdata.Fail(Rest.HttpStatusCodeBadRequest, "invalid user identity");
  201. // }
  202. //}
  203. //// If the user profile is null then either the server is broken, or the
  204. //// user is not known. We always assume the latter case.
  205. //if (rdata.userProfile != null)
  206. //{
  207. // Rest.Log.DebugFormat("{0} User profile obtained for agent {1} {2}",
  208. // MsgId, rdata.userProfile.FirstName, rdata.userProfile.SurName);
  209. //}
  210. //else
  211. //{
  212. // Rest.Log.WarnFormat("{0} No user profile for {1}", MsgId, rdata.path);
  213. // rdata.Fail(Rest.HttpStatusCodeNotFound, "unrecognized user identity");
  214. //}
  215. //// If we get to here, then we have effectively validated the user's
  216. //switch (rdata.method)
  217. //{
  218. // case Rest.HEAD : // Do the processing, set the status code, suppress entity
  219. // DoGet(rdata);
  220. // rdata.buffer = null;
  221. // break;
  222. // case Rest.GET : // Do the processing, set the status code, return entity
  223. // DoGet(rdata);
  224. // break;
  225. // case Rest.PUT : // Update named element
  226. // DoUpdate(rdata);
  227. // break;
  228. // case Rest.POST : // Add new information to identified context.
  229. // DoExtend(rdata);
  230. // break;
  231. // case Rest.DELETE : // Delete information
  232. // DoDelete(rdata);
  233. // break;
  234. // default :
  235. // Rest.Log.WarnFormat("{0} Method {1} not supported for {2}",
  236. // MsgId, rdata.method, rdata.path);
  237. // rdata.Fail(Rest.HttpStatusCodeMethodNotAllowed,
  238. // String.Format("{0} not supported", rdata.method));
  239. // break;
  240. //}
  241. }
  242. #endregion Interface
  243. #region method-specific processing
  244. /// <summary>
  245. /// This method implements GET processing for user's appearance.
  246. /// </summary>
  247. /// <param name=rdata>HTTP service request work area</param>
  248. // private void DoGet(AppearanceRequestData rdata)
  249. // {
  250. // AvatarData adata = Rest.AvatarServices.GetAvatar(rdata.userProfile.ID);
  251. //
  252. // if (adata == null)
  253. // {
  254. // rdata.Fail(Rest.HttpStatusCodeNoContent,
  255. // String.Format("appearance data not found for user {0} {1}",
  256. // rdata.userProfile.FirstName, rdata.userProfile.SurName));
  257. // }
  258. // rdata.userAppearance = adata.ToAvatarAppearance(rdata.userProfile.ID);
  259. //
  260. // rdata.initXmlWriter();
  261. //
  262. // FormatUserAppearance(rdata);
  263. //
  264. // // Indicate a successful request
  265. //
  266. // rdata.Complete();
  267. //
  268. // // Send the response to the user. The body will be implicitly
  269. // // constructed from the result of the XML writer.
  270. //
  271. // rdata.Respond(String.Format("Appearance {0} Normal completion", rdata.method));
  272. // }
  273. /// <summary>
  274. /// POST adds NEW information to the user profile database.
  275. /// This effectively resets the appearance before applying those
  276. /// characteristics supplied in the request.
  277. /// </summary>
  278. // private void DoExtend(AppearanceRequestData rdata)
  279. // {
  280. //
  281. // bool created = false;
  282. // bool modified = false;
  283. // string newnode = String.Empty;
  284. //
  285. // Rest.Log.DebugFormat("{0} POST ENTRY", MsgId);
  286. //
  287. // //AvatarAppearance old = Rest.AvatarServices.GetUserAppearance(rdata.userProfile.ID);
  288. //
  289. // rdata.userAppearance = new AvatarAppearance();
  290. //
  291. // // Although the following behavior is admitted by HTTP I am becoming
  292. // // increasingly doubtful that it is appropriate for REST. If I attempt to
  293. // // add a new record, and it already exists, then it seems to me that the
  294. // // attempt should fail, rather than update the existing record.
  295. // AvatarData adata = null;
  296. // if (GetUserAppearance(rdata))
  297. // {
  298. // modified = rdata.userAppearance != null;
  299. // created = !modified;
  300. // adata = new AvatarData(rdata.userAppearance);
  301. // Rest.AvatarServices.SetAvatar(rdata.userProfile.ID, adata);
  302. // // Rest.UserServices.UpdateUserProfile(rdata.userProfile);
  303. // }
  304. // else
  305. // {
  306. // created = true;
  307. // adata = new AvatarData(rdata.userAppearance);
  308. // Rest.AvatarServices.SetAvatar(rdata.userProfile.ID, adata);
  309. // // Rest.UserServices.UpdateUserProfile(rdata.userProfile);
  310. // }
  311. //
  312. // if (created)
  313. // {
  314. // newnode = String.Format("{0} {1}", rdata.userProfile.FirstName,
  315. // rdata.userProfile.SurName);
  316. // // Must include a location header with a URI that identifies the new resource.
  317. //
  318. // rdata.AddHeader(Rest.HttpHeaderLocation,String.Format("http://{0}{1}:{2}{3}{4}",
  319. // rdata.hostname,rdata.port,rdata.path,Rest.UrlPathSeparator, newnode));
  320. // rdata.Complete(Rest.HttpStatusCodeCreated);
  321. //
  322. // }
  323. // else
  324. // {
  325. // if (modified)
  326. // {
  327. // rdata.Complete(Rest.HttpStatusCodeOK);
  328. // }
  329. // else
  330. // {
  331. // rdata.Complete(Rest.HttpStatusCodeNoContent);
  332. // }
  333. // }
  334. //
  335. // rdata.Respond(String.Format("Appearance {0} : Normal completion", rdata.method));
  336. //
  337. // }
  338. /// <summary>
  339. /// This updates the user's appearance. not all aspects need to be provided,
  340. /// only those supplied will be changed.
  341. /// </summary>
  342. // private void DoUpdate(AppearanceRequestData rdata)
  343. // {
  344. //
  345. // // REFACTORING PROBLEM This was commented out. It doesn't work for 0.7
  346. //
  347. // //bool created = false;
  348. // //bool modified = false;
  349. //
  350. //
  351. // //rdata.userAppearance = Rest.AvatarServices.GetUserAppearance(rdata.userProfile.ID);
  352. //
  353. // //// If the user exists then this is considered a modification regardless
  354. // //// of what may, or may not be, specified in the payload.
  355. //
  356. // //if (rdata.userAppearance != null)
  357. // //{
  358. // // modified = true;
  359. // // Rest.AvatarServices.UpdateUserAppearance(rdata.userProfile.ID, rdata.userAppearance);
  360. // // Rest.UserServices.UpdateUserProfile(rdata.userProfile);
  361. // //}
  362. //
  363. // //if (created)
  364. // //{
  365. // // rdata.Complete(Rest.HttpStatusCodeCreated);
  366. // //}
  367. // //else
  368. // //{
  369. // // if (modified)
  370. // // {
  371. // // rdata.Complete(Rest.HttpStatusCodeOK);
  372. // // }
  373. // // else
  374. // // {
  375. // // rdata.Complete(Rest.HttpStatusCodeNoContent);
  376. // // }
  377. // //}
  378. //
  379. // rdata.Respond(String.Format("Appearance {0} : Normal completion", rdata.method));
  380. //
  381. // }
  382. /// <summary>
  383. /// Delete the specified user's appearance. This actually performs a reset
  384. /// to the default avatar appearance, if the info is already there.
  385. /// Existing ownership is preserved. All prior updates are lost and can not
  386. /// be recovered.
  387. /// </summary>
  388. // private void DoDelete(AppearanceRequestData rdata)
  389. // {
  390. // AvatarData adata = Rest.AvatarServices.GetAvatar(rdata.userProfile.ID);
  391. //
  392. // if (adata != null)
  393. // {
  394. // AvatarAppearance old = adata.ToAvatarAppearance(rdata.userProfile.ID);
  395. // rdata.userAppearance = new AvatarAppearance();
  396. // rdata.userAppearance.Owner = old.Owner;
  397. // adata = new AvatarData(rdata.userAppearance);
  398. //
  399. // Rest.AvatarServices.SetAvatar(rdata.userProfile.ID, adata);
  400. //
  401. // rdata.Complete();
  402. // }
  403. // else
  404. // {
  405. //
  406. // rdata.Complete(Rest.HttpStatusCodeNoContent);
  407. // }
  408. //
  409. // rdata.Respond(String.Format("Appearance {0} : Normal completion", rdata.method));
  410. // }
  411. #endregion method-specific processing
  412. private bool GetUserAppearance(AppearanceRequestData rdata)
  413. {
  414. XmlReader xml;
  415. bool indata = false;
  416. rdata.initXmlReader();
  417. xml = rdata.reader;
  418. while (xml.Read())
  419. {
  420. switch (xml.NodeType)
  421. {
  422. case XmlNodeType.Element :
  423. switch (xml.Name)
  424. {
  425. case "Appearance" :
  426. if (xml.MoveToAttribute("Height"))
  427. {
  428. rdata.userAppearance.AvatarHeight = (float) Convert.ToDouble(xml.Value);
  429. indata = true;
  430. }
  431. if (xml.MoveToAttribute("Owner"))
  432. {
  433. rdata.userAppearance.Owner = (UUID)xml.Value;
  434. indata = true;
  435. }
  436. if (xml.MoveToAttribute("Serial"))
  437. {
  438. rdata.userAppearance.Serial = Convert.ToInt32(xml.Value);
  439. indata = true;
  440. }
  441. break;
  442. /*
  443. case "Body" :
  444. if (xml.MoveToAttribute("Item"))
  445. {
  446. rdata.userAppearance.BodyItem = (UUID)xml.Value;
  447. indata = true;
  448. }
  449. if (xml.MoveToAttribute("Asset"))
  450. {
  451. rdata.userAppearance.BodyAsset = (UUID)xml.Value;
  452. indata = true;
  453. }
  454. break;
  455. case "Skin" :
  456. if (xml.MoveToAttribute("Item"))
  457. {
  458. rdata.userAppearance.SkinItem = (UUID)xml.Value;
  459. indata = true;
  460. }
  461. if (xml.MoveToAttribute("Asset"))
  462. {
  463. rdata.userAppearance.SkinAsset = (UUID)xml.Value;
  464. indata = true;
  465. }
  466. break;
  467. case "Hair" :
  468. if (xml.MoveToAttribute("Item"))
  469. {
  470. rdata.userAppearance.HairItem = (UUID)xml.Value;
  471. indata = true;
  472. }
  473. if (xml.MoveToAttribute("Asset"))
  474. {
  475. rdata.userAppearance.HairAsset = (UUID)xml.Value;
  476. indata = true;
  477. }
  478. break;
  479. case "Eyes" :
  480. if (xml.MoveToAttribute("Item"))
  481. {
  482. rdata.userAppearance.EyesItem = (UUID)xml.Value;
  483. indata = true;
  484. }
  485. if (xml.MoveToAttribute("Asset"))
  486. {
  487. rdata.userAppearance.EyesAsset = (UUID)xml.Value;
  488. indata = true;
  489. }
  490. break;
  491. case "Shirt" :
  492. if (xml.MoveToAttribute("Item"))
  493. {
  494. rdata.userAppearance.ShirtItem = (UUID)xml.Value;
  495. indata = true;
  496. }
  497. if (xml.MoveToAttribute("Asset"))
  498. {
  499. rdata.userAppearance.ShirtAsset = (UUID)xml.Value;
  500. indata = true;
  501. }
  502. break;
  503. case "Pants" :
  504. if (xml.MoveToAttribute("Item"))
  505. {
  506. rdata.userAppearance.PantsItem = (UUID)xml.Value;
  507. indata = true;
  508. }
  509. if (xml.MoveToAttribute("Asset"))
  510. {
  511. rdata.userAppearance.PantsAsset = (UUID)xml.Value;
  512. indata = true;
  513. }
  514. break;
  515. case "Shoes" :
  516. if (xml.MoveToAttribute("Item"))
  517. {
  518. rdata.userAppearance.ShoesItem = (UUID)xml.Value;
  519. indata = true;
  520. }
  521. if (xml.MoveToAttribute("Asset"))
  522. {
  523. rdata.userAppearance.ShoesAsset = (UUID)xml.Value;
  524. indata = true;
  525. }
  526. break;
  527. case "Socks" :
  528. if (xml.MoveToAttribute("Item"))
  529. {
  530. rdata.userAppearance.SocksItem = (UUID)xml.Value;
  531. indata = true;
  532. }
  533. if (xml.MoveToAttribute("Asset"))
  534. {
  535. rdata.userAppearance.SocksAsset = (UUID)xml.Value;
  536. indata = true;
  537. }
  538. break;
  539. case "Jacket" :
  540. if (xml.MoveToAttribute("Item"))
  541. {
  542. rdata.userAppearance.JacketItem = (UUID)xml.Value;
  543. indata = true;
  544. }
  545. if (xml.MoveToAttribute("Asset"))
  546. {
  547. rdata.userAppearance.JacketAsset = (UUID)xml.Value;
  548. indata = true;
  549. }
  550. break;
  551. case "Gloves" :
  552. if (xml.MoveToAttribute("Item"))
  553. {
  554. rdata.userAppearance.GlovesItem = (UUID)xml.Value;
  555. indata = true;
  556. }
  557. if (xml.MoveToAttribute("Asset"))
  558. {
  559. rdata.userAppearance.GlovesAsset = (UUID)xml.Value;
  560. indata = true;
  561. }
  562. break;
  563. case "UnderShirt" :
  564. if (xml.MoveToAttribute("Item"))
  565. {
  566. rdata.userAppearance.UnderShirtItem = (UUID)xml.Value;
  567. indata = true;
  568. }
  569. if (xml.MoveToAttribute("Asset"))
  570. {
  571. rdata.userAppearance.UnderShirtAsset = (UUID)xml.Value;
  572. indata = true;
  573. }
  574. break;
  575. case "UnderPants" :
  576. if (xml.MoveToAttribute("Item"))
  577. {
  578. rdata.userAppearance.UnderPantsItem = (UUID)xml.Value;
  579. indata = true;
  580. }
  581. if (xml.MoveToAttribute("Asset"))
  582. {
  583. rdata.userAppearance.UnderPantsAsset = (UUID)xml.Value;
  584. indata = true;
  585. }
  586. break;
  587. case "Skirt" :
  588. if (xml.MoveToAttribute("Item"))
  589. {
  590. rdata.userAppearance.SkirtItem = (UUID)xml.Value;
  591. indata = true;
  592. }
  593. if (xml.MoveToAttribute("Asset"))
  594. {
  595. rdata.userAppearance.SkirtAsset = (UUID)xml.Value;
  596. indata = true;
  597. }
  598. break;
  599. */
  600. case "Attachment" :
  601. {
  602. int ap;
  603. UUID asset;
  604. UUID item;
  605. if (xml.MoveToAttribute("AtPoint"))
  606. {
  607. ap = Convert.ToInt32(xml.Value);
  608. if (xml.MoveToAttribute("Asset"))
  609. {
  610. asset = new UUID(xml.Value);
  611. if (xml.MoveToAttribute("Asset"))
  612. {
  613. item = new UUID(xml.Value);
  614. rdata.userAppearance.SetAttachment(ap, item, asset);
  615. indata = true;
  616. }
  617. }
  618. }
  619. }
  620. break;
  621. case "Texture" :
  622. if (xml.MoveToAttribute("Default"))
  623. {
  624. rdata.userAppearance.Texture = new Primitive.TextureEntry(new UUID(xml.Value));
  625. indata = true;
  626. }
  627. break;
  628. case "Face" :
  629. {
  630. uint index;
  631. if (xml.MoveToAttribute("Index"))
  632. {
  633. index = Convert.ToUInt32(xml.Value);
  634. if (xml.MoveToAttribute("Id"))
  635. {
  636. rdata.userAppearance.Texture.CreateFace(index).TextureID = new UUID(xml.Value);
  637. indata = true;
  638. }
  639. }
  640. }
  641. break;
  642. case "VisualParameters" :
  643. {
  644. xml.ReadContentAsBase64(rdata.userAppearance.VisualParams,
  645. 0, rdata.userAppearance.VisualParams.Length);
  646. indata = true;
  647. }
  648. break;
  649. }
  650. break;
  651. }
  652. }
  653. return indata;
  654. }
  655. private void FormatPart(AppearanceRequestData rdata, string part, UUID item, UUID asset)
  656. {
  657. if (item != UUID.Zero || asset != UUID.Zero)
  658. {
  659. rdata.writer.WriteStartElement(part);
  660. if (item != UUID.Zero)
  661. {
  662. rdata.writer.WriteAttributeString("Item",item.ToString());
  663. }
  664. if (asset != UUID.Zero)
  665. {
  666. rdata.writer.WriteAttributeString("Asset",asset.ToString());
  667. }
  668. rdata.writer.WriteEndElement();
  669. }
  670. }
  671. private void FormatUserAppearance(AppearanceRequestData rdata)
  672. {
  673. Rest.Log.DebugFormat("{0} FormatUserAppearance", MsgId);
  674. if (rdata.userAppearance != null)
  675. {
  676. Rest.Log.DebugFormat("{0} FormatUserAppearance: appearance object exists", MsgId);
  677. rdata.writer.WriteStartElement("Appearance");
  678. rdata.writer.WriteAttributeString("Height", rdata.userAppearance.AvatarHeight.ToString());
  679. if (rdata.userAppearance.Owner != UUID.Zero)
  680. rdata.writer.WriteAttributeString("Owner", rdata.userAppearance.Owner.ToString());
  681. rdata.writer.WriteAttributeString("Serial", rdata.userAppearance.Serial.ToString());
  682. /*
  683. FormatPart(rdata, "Body", rdata.userAppearance.BodyItem, rdata.userAppearance.BodyAsset);
  684. FormatPart(rdata, "Skin", rdata.userAppearance.SkinItem, rdata.userAppearance.SkinAsset);
  685. FormatPart(rdata, "Hair", rdata.userAppearance.HairItem, rdata.userAppearance.HairAsset);
  686. FormatPart(rdata, "Eyes", rdata.userAppearance.EyesItem, rdata.userAppearance.EyesAsset);
  687. FormatPart(rdata, "Shirt", rdata.userAppearance.ShirtItem, rdata.userAppearance.ShirtAsset);
  688. FormatPart(rdata, "Pants", rdata.userAppearance.PantsItem, rdata.userAppearance.PantsAsset);
  689. FormatPart(rdata, "Skirt", rdata.userAppearance.SkirtItem, rdata.userAppearance.SkirtAsset);
  690. FormatPart(rdata, "Shoes", rdata.userAppearance.ShoesItem, rdata.userAppearance.ShoesAsset);
  691. FormatPart(rdata, "Socks", rdata.userAppearance.SocksItem, rdata.userAppearance.SocksAsset);
  692. FormatPart(rdata, "Jacket", rdata.userAppearance.JacketItem, rdata.userAppearance.JacketAsset);
  693. FormatPart(rdata, "Gloves", rdata.userAppearance.GlovesItem, rdata.userAppearance.GlovesAsset);
  694. FormatPart(rdata, "UnderShirt", rdata.userAppearance.UnderShirtItem, rdata.userAppearance.UnderShirtAsset);
  695. FormatPart(rdata, "UnderPants", rdata.userAppearance.UnderPantsItem, rdata.userAppearance.UnderPantsAsset);
  696. */
  697. Rest.Log.DebugFormat("{0} FormatUserAppearance: Formatting attachments", MsgId);
  698. rdata.writer.WriteStartElement("Attachments");
  699. List<AvatarAttachment> attachments = rdata.userAppearance.GetAttachments();
  700. foreach (AvatarAttachment attach in attachments)
  701. {
  702. rdata.writer.WriteStartElement("Attachment");
  703. rdata.writer.WriteAttributeString("AtPoint", attach.AttachPoint.ToString());
  704. rdata.writer.WriteAttributeString("Item", attach.ItemID.ToString());
  705. rdata.writer.WriteAttributeString("Asset", attach.AssetID.ToString());
  706. rdata.writer.WriteEndElement();
  707. }
  708. rdata.writer.WriteEndElement();
  709. Primitive.TextureEntry texture = rdata.userAppearance.Texture;
  710. if (texture != null && (texture.DefaultTexture != null || texture.FaceTextures != null))
  711. {
  712. Rest.Log.DebugFormat("{0} FormatUserAppearance: Formatting textures", MsgId);
  713. rdata.writer.WriteStartElement("Texture");
  714. if (texture.DefaultTexture != null)
  715. {
  716. Rest.Log.DebugFormat("{0} FormatUserAppearance: Formatting default texture", MsgId);
  717. rdata.writer.WriteAttributeString("Default",
  718. texture.DefaultTexture.TextureID.ToString());
  719. }
  720. if (texture.FaceTextures != null)
  721. {
  722. Rest.Log.DebugFormat("{0} FormatUserAppearance: Formatting face textures", MsgId);
  723. for (int i=0; i<texture.FaceTextures.Length;i++)
  724. {
  725. if (texture.FaceTextures[i] != null)
  726. {
  727. rdata.writer.WriteStartElement("Face");
  728. rdata.writer.WriteAttributeString("Index", i.ToString());
  729. rdata.writer.WriteAttributeString("Id",
  730. texture.FaceTextures[i].TextureID.ToString());
  731. rdata.writer.WriteEndElement();
  732. }
  733. }
  734. }
  735. rdata.writer.WriteEndElement();
  736. }
  737. Rest.Log.DebugFormat("{0} FormatUserAppearance: Formatting visual parameters", MsgId);
  738. rdata.writer.WriteStartElement("VisualParameters");
  739. rdata.writer.WriteBase64(rdata.userAppearance.VisualParams,0,
  740. rdata.userAppearance.VisualParams.Length);
  741. rdata.writer.WriteEndElement();
  742. rdata.writer.WriteFullEndElement();
  743. }
  744. Rest.Log.DebugFormat("{0} FormatUserAppearance: completed", MsgId);
  745. return;
  746. }
  747. #region appearance RequestData extension
  748. internal class AppearanceRequestData : RequestData
  749. {
  750. /// <summary>
  751. /// These are the inventory specific request/response state
  752. /// extensions.
  753. /// </summary>
  754. internal UUID uuid = UUID.Zero;
  755. internal UserProfileData userProfile = null;
  756. internal AvatarAppearance userAppearance = null;
  757. internal AppearanceRequestData(OSHttpRequest request, OSHttpResponse response, string prefix)
  758. : base(request, response, prefix)
  759. {
  760. }
  761. }
  762. #endregion Appearance RequestData extension
  763. }
  764. }