public static List <UUID> GetEmbeddedAssetIDs(byte[] data) { if (data == null || data.Length < 79) { return(null); } string note = Util.UTF8.GetString(data); if (String.IsNullOrWhiteSpace(note)) { return(null); } // waste some time checking rigid versions string tmpStr = note.Substring(0, 21); if (!tmpStr.Equals("Linden text version 2")) { return(null); } tmpStr = note.Substring(24, 25); if (!tmpStr.Equals("LLEmbeddedItems version 1")) { return(null); } tmpStr = note.Substring(52, 5); if (!tmpStr.Equals("count")) { return(null); } int limit = note.Length - 57 - 2; if (limit > 8) { limit = 8; } int indx = note.IndexOfAny(seps, 57, limit); if (indx < 0) { return(null); } if (!int.TryParse(note.Substring(57, indx - 57), out int count)) { return(null); } List <UUID> ids = new List <UUID>(); while (count > 0) { string valuestr; UUID assetID = UUID.Zero; indx = note.IndexOf('}', indx); // skip to end of permissions if (indx < 0) { return(null); } int curindx = indx; indx = getField(note, indx, "asset_id", false, out valuestr); if (indx < 0) { indx = getField(note, curindx, "shadow_id", false, out valuestr); if (indx < 0) { return(null); } if (!UUID.TryParse(valuestr, out assetID)) { return(null); } assetID = deMoronize(assetID); } else { if (!UUID.TryParse(valuestr, out assetID)) { return(null); } } ids.Add(assetID); indx = note.IndexOf('}', indx); // skip to end of sale if (indx < 0) { return(null); } indx = getField(note, indx, "name", false, out valuestr); // avoid name contents if (indx < 0) { return(null); } indx = getField(note, indx, "desc", false, out valuestr); // avoid desc contents if (indx < 0) { return(null); } if (count > 1) { indx = note.IndexOf("ext char index", indx); // skip to next if (indx < 0) { return(null); } } --count; } indx = note.IndexOf("Text length", indx); if (indx > 0) { indx += 14; List <UUID> textIDs = Util.GetUUIDsOnString(ref note, indx, note.Length - indx); if (textIDs.Count > 0) { ids.AddRange(textIDs); } } if (ids.Count == 0) { return(null); } return(ids); }