/// <summary> /// This method is called whenever an Item has been successfully /// reconstituted from the request's entity. /// It uses the information curren tin the XmlInventoryCollection /// to complete the item's specification, including any implied /// context and asset associations. /// It fails the request if any necessary item or asset information /// is missing. /// </summary> private void Validate(XmlInventoryCollection ic) { // There really should be an item present if we've // called validate. So fail if there is not. if (ic.Item == null) { Rest.Log.ErrorFormat("{0} Unable to parse request", MsgId); ic.Fail(Rest.HttpStatusCodeBadRequest, "request parse error"); } // Every item is required to have a name (via REST anyway) if (ic.Item.Name == String.Empty) { Rest.Log.ErrorFormat("{0} An item name MUST be specified", MsgId); ic.Fail(Rest.HttpStatusCodeBadRequest, "item name required"); } // An item MUST have an asset ID. AssetID should never be zero // here. It should always get set from the information stored // when the Asset element was processed. if (ic.Item.AssetID == UUID.Zero) { Rest.Log.ErrorFormat("{0} Unable to complete request", MsgId); Rest.Log.InfoFormat("{0} Asset information is missing", MsgId); ic.Fail(Rest.HttpStatusCodeBadRequest, "asset information required"); } // If the item is new, then assign it an ID if (ic.Item.ID == UUID.Zero) { ic.Item.ID = UUID.Random(); } // If the context is being implied, obtain the current // folder item's ID. If it was specified explicitly, make // sure that theparent folder exists. if (ic.Item.Folder == UUID.Zero) { ic.Item.Folder = ic.Parent(); } else { bool found = false; foreach (InventoryFolderBase parent in ic.rdata.folders) { if (parent.ID == ic.Item.Folder) { found = true; break; } } if (!found) { Rest.Log.ErrorFormat("{0} Invalid parent ID ({1}) in item {2}", MsgId, ic.Item.Folder, ic.Item.ID); ic.Fail(Rest.HttpStatusCodeBadRequest, "parent information required"); } } // If this is an inline asset being constructed in the context // of a new Item, then use the itm's name here too. if (ic.Asset != null) { if (ic.Asset.Name == String.Empty) ic.Asset.Name = ic.Item.Name; if (ic.Asset.Description == String.Empty) ic.Asset.Description = ic.Item.Description; } // Assign permissions ic.Item.CurrentPermissions = ic.CurrentPermissions; ic.Item.EveryOnePermissions = ic.EveryOnePermissions; ic.Item.BasePermissions = ic.BasePermissions; ic.Item.GroupPermissions = ic.GroupPermissions; ic.Item.NextPermissions = ic.NextPermissions; // If no type was specified for this item, we can attempt to // infer something from the file type maybe. This is NOT as // good as having type be specified in the XML. if (ic.Item.AssetType == (int) AssetType.Unknown || ic.Item.InvType == (int) InventoryType.Unknown) { Rest.Log.DebugFormat("{0} Attempting to infer item type", MsgId); string[] parts = ic.Item.Name.Split(Rest.CA_PERIOD); if (Rest.DEBUG) { for (int i = 0; i < parts.Length; i++) { Rest.Log.DebugFormat("{0} Name part {1} : {2}", MsgId, i, parts[i]); } } // If the associated item name is multi-part, then maybe // the last part will indicate the item type - if we're // lucky. if (parts.Length > 1) { Rest.Log.DebugFormat("{0} File type is {1}", MsgId, parts[parts.Length - 1]); switch (parts[parts.Length - 1]) { case "jpeg2000" : case "jpeg-2000" : case "jpg2000" : case "jpg-2000" : Rest.Log.DebugFormat("{0} Type {1} inferred", MsgId, parts[parts.Length-1]); if (ic.Item.AssetType == (int) AssetType.Unknown) ic.Item.AssetType = (int) AssetType.ImageJPEG; if (ic.Item.InvType == (int) InventoryType.Unknown) ic.Item.InvType = (int) InventoryType.Texture; break; case "jpg" : case "jpeg" : Rest.Log.DebugFormat("{0} Type {1} inferred", MsgId, parts[parts.Length - 1]); if (ic.Item.AssetType == (int) AssetType.Unknown) ic.Item.AssetType = (int) AssetType.ImageJPEG; if (ic.Item.InvType == (int) InventoryType.Unknown) ic.Item.InvType = (int) InventoryType.Texture; break; case "tga" : if (parts[parts.Length - 2].IndexOf("_texture") != -1) { if (ic.Item.AssetType == (int) AssetType.Unknown) ic.Item.AssetType = (int) AssetType.TextureTGA; if (ic.Item.InvType == (int) AssetType.Unknown) ic.Item.InvType = (int) InventoryType.Texture; } else { if (ic.Item.AssetType == (int) AssetType.Unknown) ic.Item.AssetType = (int) AssetType.ImageTGA; if (ic.Item.InvType == (int) InventoryType.Unknown) ic.Item.InvType = (int) InventoryType.Snapshot; } break; default : Rest.Log.DebugFormat("{0} Asset/Inventory type could not be inferred for {1}", MsgId,ic.Item.Name); break; } } } /// If this is a TGA remember the fact if (ic.Item.AssetType == (int) AssetType.TextureTGA || ic.Item.AssetType == (int) AssetType.ImageTGA) { Bitmap temp; Stream tgadata = new MemoryStream(ic.Asset.Data); temp = LoadTGAClass.LoadTGA(tgadata); try { ic.Asset.Data = OpenJPEG.EncodeFromImage(temp, true); } catch (DllNotFoundException) { Rest.Log.ErrorFormat("OpenJpeg is not installed correctly on this system. Asset Data is emtpy for {0}", ic.Item.Name); ic.Asset.Data = new Byte[0]; } catch (IndexOutOfRangeException) { Rest.Log.ErrorFormat("OpenJpeg was unable to encode this. Asset Data is emtpy for {0}", ic.Item.Name); ic.Asset.Data = new Byte[0]; } catch (Exception) { Rest.Log.ErrorFormat("OpenJpeg was unable to encode this. Asset Data is emtpy for {0}", ic.Item.Name); ic.Asset.Data = new Byte[0]; } } ic.reset(); }
/// <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); }