/// <summary> /// This method is called to handle the construction of an Item /// instance from the supplied request entity. It is called /// whenever an Item start tag is detected. /// An instance of an Item is created and initialized to default /// values. These values are then overridden from values supplied /// as attributes to the Item element. /// This item is then stored in the XmlInventoryCollection and /// will be verified by Validate. /// All context is reset whenever the effective folder changes /// or an item is successfully validated. /// </summary> private void CollectItem(XmlInventoryCollection ic) { Rest.Log.DebugFormat("{0} Interpret item element", MsgId); InventoryItemBase result = new InventoryItemBase(); result.Name = String.Empty; result.Description = String.Empty; result.ID = UUID.Zero; result.Folder = UUID.Zero; result.Owner = ic.UserID; result.CreatorId = ic.UserID.ToString(); result.AssetID = UUID.Zero; result.GroupID = UUID.Zero; result.GroupOwned = false; result.InvType = (int) InventoryType.Unknown; result.AssetType = (int) AssetType.Unknown; if (ic.xml.HasAttributes) { for (int i = 0; i < ic.xml.AttributeCount; i++) { ic.xml.MoveToAttribute(i); switch (ic.xml.Name) { case "name": result.Name = ic.xml.Value; break; case "desc": result.Description = ic.xml.Value; break; case "uuid": result.ID = new UUID(ic.xml.Value); break; case "folder": result.Folder = new UUID(ic.xml.Value); break; case "owner": result.Owner = new UUID(ic.xml.Value); break; case "invtype": result.InvType = Int32.Parse(ic.xml.Value); break; case "creator": result.CreatorId = ic.xml.Value; break; case "assettype": result.AssetType = Int32.Parse(ic.xml.Value); break; case "groupowned": result.GroupOwned = Boolean.Parse(ic.xml.Value); break; case "groupid": result.GroupID = new UUID(ic.xml.Value); break; case "flags": result.Flags = UInt32.Parse(ic.xml.Value); break; case "creationdate": result.CreationDate = Int32.Parse(ic.xml.Value); break; case "saletype": result.SaleType = Byte.Parse(ic.xml.Value); break; case "saleprice": result.SalePrice = Int32.Parse(ic.xml.Value); break; default: Rest.Log.DebugFormat("{0} Item: Unrecognized attribute: {1}:{2}", MsgId, ic.xml.Name, ic.xml.Value); ic.Fail(Rest.HttpStatusCodeBadRequest, String.Format("unrecognized attribute", ic.xml.Name)); break; } } } ic.xml.MoveToElement(); ic.Push(result); }
/// <summary> /// This method assembles an asset instance from the /// information supplied in the request's entity. It is /// called as a result of detecting a start tag for a /// type of Asset. /// The information is collected locally, and an asset /// instance is created only if the basic XML parsing /// completes successfully. /// Default values for all parts of the asset are /// established before overriding them from the supplied /// XML. /// If an asset has inline=true as an attribute, then /// the element contains the data representing the /// asset. This is saved as the data component. /// inline=false means that the element's payload is /// simply the UUID of the asset referenced by the /// item being constructed. /// An asset, if created is stored in the /// XmlInventoryCollection /// </summary> private void CollectAsset(XmlInventoryCollection ic) { Rest.Log.DebugFormat("{0} Interpret asset element", MsgId); string name = String.Empty; string desc = String.Empty; sbyte type = (sbyte) AssetType.Unknown; bool temp = false; bool local = false; // This is not a persistent attribute bool inline = false; UUID uuid = UUID.Zero; // Attribute is optional if (ic.xml.HasAttributes) { for (int i = 0; i < ic.xml.AttributeCount; i++) { ic.xml.MoveToAttribute(i); switch (ic.xml.Name) { case "name" : name = ic.xml.Value; break; case "type" : type = SByte.Parse(ic.xml.Value); break; case "description" : desc = ic.xml.Value; break; case "temporary" : temp = Boolean.Parse(ic.xml.Value); break; case "uuid" : uuid = new UUID(ic.xml.Value); break; case "inline" : inline = Boolean.Parse(ic.xml.Value); break; case "local" : local = Boolean.Parse(ic.xml.Value); break; default : Rest.Log.DebugFormat("{0} Asset: Unrecognized attribute: {1}:{2}", MsgId, ic.xml.Name, ic.xml.Value); ic.Fail(Rest.HttpStatusCodeBadRequest, String.Format("unrecognized attribute <{0}>", ic.xml.Name)); break; } } } ic.xml.MoveToElement(); // If this is a reference to an existing asset, just store the // asset ID into the item. if (!inline) { if (ic.Item != null) { ic.Item.AssetID = new UUID(ic.xml.ReadElementContentAsString()); Rest.Log.DebugFormat("{0} Asset ID supplied: {1}", MsgId, ic.Item.AssetID); } else { Rest.Log.DebugFormat("{0} LLUID unimbedded asset must be inline", MsgId); ic.Fail(Rest.HttpStatusCodeBadRequest, "no context for asset"); } } // Otherwise, generate an asset ID, store that into the item, and // create an entry in the asset list for the inlined asset. But // only if the size is non-zero. else { AssetBase asset = null; string b64string = null; // Generate a UUID if none were given, and generally none should // be. Ever. if (uuid == UUID.Zero) { uuid = UUID.Random(); } // Create AssetBase entity to hold the inlined asset asset = new AssetBase(uuid, name, type, UUID.Zero.ToString()); asset.Description = desc; asset.Local = local; asset.Temporary = temp; b64string = ic.xml.ReadElementContentAsString(); Rest.Log.DebugFormat("{0} Data length is {1}", MsgId, b64string.Length); Rest.Log.DebugFormat("{0} Data content starts with: \n\t<{1}>", MsgId, b64string.Substring(0, b64string.Length > 132 ? 132 : b64string.Length)); asset.Data = Convert.FromBase64String(b64string); // Ensure the asset always has some kind of data component if (asset.Data == null) { asset.Data = new byte[1]; } // If this is in the context of an item, establish // a link with the item in context. if (ic.Item != null && ic.Item.AssetID == UUID.Zero) { ic.Item.AssetID = uuid; } ic.Push(asset); } }
/// <summary> /// This method creates an inventory Folder from the /// information supplied in the request's entity. /// A folder instance is created and initialized to reflect /// default values. These values are then overridden /// by information supplied in the entity. /// If context was not explicitly provided, then the /// appropriate ID values are determined. /// </summary> private void CollectFolder(XmlInventoryCollection ic) { Rest.Log.DebugFormat("{0} Interpret folder element", MsgId); InventoryFolderBase result = new InventoryFolderBase(); // Default values result.Name = String.Empty; result.ID = UUID.Zero; result.Owner = ic.UserID; result.ParentID = UUID.Zero; // Context result.Type = (short) AssetType.Folder; result.Version = 1; if (ic.xml.HasAttributes) { for (int i = 0; i < ic.xml.AttributeCount; i++) { ic.xml.MoveToAttribute(i); switch (ic.xml.Name) { case "name": result.Name = ic.xml.Value; break; case "uuid": result.ID = new UUID(ic.xml.Value); break; case "parent": result.ParentID = new UUID(ic.xml.Value); break; case "owner": result.Owner = new UUID(ic.xml.Value); break; case "type": result.Type = Int16.Parse(ic.xml.Value); break; case "version": result.Version = UInt16.Parse(ic.xml.Value); break; default: Rest.Log.DebugFormat("{0} Folder: unrecognized attribute: {1}:{2}", MsgId, ic.xml.Name, ic.xml.Value); ic.Fail(Rest.HttpStatusCodeBadRequest, String.Format("unrecognized attribute <{0}>", ic.xml.Name)); break; } } } ic.xml.MoveToElement(); // The client is relying upon the reconstitution process // to determine the parent's UUID based upon context. This // is necessary where a new folder may have been // introduced. if (result.ParentID == UUID.Zero) { result.ParentID = ic.Parent(); } else { bool found = false; foreach (InventoryFolderBase parent in ic.rdata.folders) { if (parent.ID == result.ParentID) { found = true; break; } } if (!found) { Rest.Log.ErrorFormat("{0} Invalid parent ID ({1}) in folder {2}", MsgId, ic.Item.Folder, result.ID); ic.Fail(Rest.HttpStatusCodeBadRequest, "invalid parent"); } } // This is a new folder, so no existing UUID is available // or appropriate if (result.ID == UUID.Zero) { result.ID = UUID.Random(); } // Treat this as a new context. Any other information is // obsolete as a consequence. ic.Push(result); }