/// <summary> /// De-serialization constructor for the InventoryNode Class /// </summary> public InventoryNode(InventoryBase data, InventoryNode parent) { this.data = data; this.parent = parent; if (parent != null) { // Add this node to the collection of parent nodes lock (parent.Nodes.SyncRoot) parent.Nodes.Add(data.UUID, this); } }
public InventoryBackup(RadegastInstance instance, UUID rootFolder) { InitializeComponent(); Disposed += new System.EventHandler(InventoryBackup_Disposed); this.instance = instance; inv = client.Inventory.Store; rootNode = inv.RootNode; if (inv.Items.ContainsKey(rootFolder) && inv.Items[rootFolder].Data is InventoryFolder) { rootNode = inv.GetNodeFor(rootFolder); } }
public static InventoryNode FindNodeMyName(InventoryNode root, string name) { if (root.Data.Name == name) { return root; } foreach (var node in root.Nodes.Values) { var ret = FindNodeMyName(node, name); if (ret != null) { return ret; } } return null; }
protected InventoryNode FindFolderInternal(InventoryNode currentNode, string currentPath, string desiredPath) { if (desiredPath == currentPath) { return currentNode; } foreach (var n in currentNode.Nodes.Values) { if (n.Data.Name.StartsWith(".")) continue; var res = FindFolderInternal(n, (currentPath == "/" ? currentPath : currentPath + "/") + n.Data.Name.ToLower(), desiredPath); if (res != null) { return res; } } return null; }
public InventoryNode FindFolder(string folder, InventoryNode start) { if (start.Data.Name == folder) { return start; } foreach (var node in start.Nodes.Values) { if (node.Data is InventoryFolder) { var n = FindFolder(folder, node); if (n != null) { return n; } } } return null; }
private void TraverseDir(InventoryNode node, string path) { var nodes = new List<InventoryNode>(node.Nodes.Values); foreach (InventoryNode n in nodes) { traversed++; try { if (IsHandleCreated && (traversed % 13 == 0)) { BeginInvoke(new MethodInvoker(() => { lblStatus.Text = string.Format("Traversed {0} nodes...", traversed); })); } if (n.Data is InventoryFolder) { WriteCSVLine("Folder", path, n.Data.Name, "", "", "", ""); TraverseDir(n, Path.Combine(path, RadegastInstance.SafeFileName(n.Data.Name))); } else { InventoryItem item = (InventoryItem)n.Data; string creator = item.CreatorID == UUID.Zero ? string.Empty : instance.Names.Get(item.CreatorID, true); string lastOwner = item.LastOwnerID == UUID.Zero ? string.Empty : instance.Names.Get(item.LastOwnerID, true); string type = item.AssetType.ToString(); if (item.InventoryType == InventoryType.Wearable) type = ((WearableType)item.Flags).ToString(); string created = item.CreationDate.ToString("yyyy-MM-dd HH:mm:ss"); WriteCSVLine(type, path, item.Name, item.Description, created, creator, lastOwner); PermissionMask fullPerm = PermissionMask.Modify | PermissionMask.Copy | PermissionMask.Transfer; if ((item.Permissions.OwnerMask & fullPerm) != fullPerm) continue; string filePartial = Path.Combine(path, RadegastInstance.SafeFileName(n.Data.Name)); string fullName = folderName + filePartial; switch (item.AssetType) { case AssetType.LSLText: client.Settings.USE_ASSET_CACHE = false; fullName += ".lsl"; break; case AssetType.Notecard: fullName += ".txt"; break; case AssetType.Texture: fullName += ".png"; break; default: fullName += ".bin"; break; } string dirName = Path.GetDirectoryName(fullName); bool dateOK = item.CreationDate > new DateTime(1970, 1, 2); if ( (item.AssetType == AssetType.LSLText && cbScripts.Checked) || (item.AssetType == AssetType.Notecard && cbNoteCards.Checked) || (item.AssetType == AssetType.Texture && cbImages.Checked) ) { ListViewItem lvi = new ListViewItem(); lvi.Text = n.Data.Name; lvi.Tag = n.Data; lvi.Name = n.Data.UUID.ToString(); ListViewItem.ListViewSubItem fileName = new ListViewItem.ListViewSubItem(lvi, filePartial); lvi.SubItems.Add(fileName); ListViewItem.ListViewSubItem status = new ListViewItem.ListViewSubItem(lvi, "Fetching asset"); lvi.SubItems.Add(status); //bool cached = dateOK && File.Exists(fullName) && File.GetCreationTimeUtc(fullName) == item.CreationDate; //if (cached) //{ // status.Text = "Cached"; //} BeginInvoke(new MethodInvoker(() => { lvwFiles.Items.Add(lvi); lvwFiles.EnsureVisible(lvwFiles.Items.Count - 1); })); //if (cached) continue; Asset receivedAsset = null; using (AutoResetEvent done = new AutoResetEvent(false)) { if (item.AssetType == AssetType.Texture) { client.Assets.RequestImage(item.AssetUUID, (state, asset) => { if (state == TextureRequestState.Finished && asset != null && asset.Decode()) { receivedAsset = asset; done.Set(); } }); } else { client.Assets.RequestInventoryAsset(item, true, (AssetDownload transfer, Asset asset) => { if (transfer.Success) { receivedAsset = asset; } done.Set(); } ); } done.WaitOne(30 * 1000, false); } client.Settings.USE_ASSET_CACHE = true; if (receivedAsset == null) { BeginInvoke(new MethodInvoker(() => status.Text = "Failed to fetch asset")); } else { BeginInvoke(new MethodInvoker(() => status.Text = "Saving...")); try { if (!Directory.Exists(dirName)) { Directory.CreateDirectory(dirName); } switch (item.AssetType) { case AssetType.Notecard: AssetNotecard note = (AssetNotecard)receivedAsset; if (note.Decode()) { File.WriteAllText(fullName, note.BodyText, System.Text.Encoding.UTF8); if (dateOK) { File.SetCreationTimeUtc(fullName, item.CreationDate); File.SetLastWriteTimeUtc(fullName, item.CreationDate); } } else { Logger.Log(string.Format("Falied to decode asset for '{0}' - {1}", item.Name, receivedAsset.AssetID), Helpers.LogLevel.Warning, client); } break; case AssetType.LSLText: AssetScriptText script = (AssetScriptText)receivedAsset; if (script.Decode()) { File.WriteAllText(fullName, script.Source, System.Text.Encoding.UTF8); if (dateOK) { File.SetCreationTimeUtc(fullName, item.CreationDate); File.SetLastWriteTimeUtc(fullName, item.CreationDate); } } else { Logger.Log(string.Format("Falied to decode asset for '{0}' - {1}", item.Name, receivedAsset.AssetID), Helpers.LogLevel.Warning, client); } break; case AssetType.Texture: AssetTexture imgAsset = (AssetTexture)receivedAsset; var img = LoadTGAClass.LoadTGA(new MemoryStream(imgAsset.Image.ExportTGA())); img.Save(fullName, System.Drawing.Imaging.ImageFormat.Png); if (dateOK) { File.SetCreationTimeUtc(fullName, item.CreationDate); File.SetLastWriteTimeUtc(fullName, item.CreationDate); } break; } BeginInvoke(new MethodInvoker(() => { fileName.Text = fullName; status.Text = "Saved"; lblStatus.Text = string.Format("Saved {0} items", ++fetched); })); } catch (Exception ex) { BeginInvoke(new MethodInvoker(() => status.Text = "Failed to save " + Path.GetFileName(fullName) + ": " + ex.Message)); } } } } } catch { } } }
public void Add(UUID key, InventoryNode value) { value.Parent = parent; lock (syncRoot) this.Dictionary.Add(key, value); }
private void TraverseAndQueueNodes(InventoryNode start) { bool has_items = false; foreach (InventoryNode node in start.Nodes.Values) { if (node.Data is InventoryItem) { has_items = true; break; } } if (!has_items || start.NeedsUpdate) { lock (QueuedFolders) { lock (FolderFetchRetries) { int retries = 0; FolderFetchRetries.TryGetValue(start.Data.UUID, out retries); if (retries < 3) { if (!QueuedFolders.Contains(start.Data.UUID)) { QueuedFolders.Add(start.Data.UUID); } } FolderFetchRetries[start.Data.UUID] = retries + 1; } } } foreach (InventoryBase item in Inventory.GetContents((InventoryFolder)start.Data)) { if (item is InventoryFolder) { TraverseAndQueueNodes(Inventory.GetNodeFor(item.UUID)); } } }
/// <summary> /// BackupFolder - recurse through the inventory nodes sending scripts and notecards to the transfer queue /// </summary> /// <param name="folder">The current leaf in the inventory tree</param> /// <param name="sPathSoFar">path so far, in the form @"c:\here" -- this needs to be "clean" for the current filesystem</param> private void BackupFolder(InventoryNode folder, string sPathSoFar) { // FIXME: //Client.Inventory.RequestFolderContents(folder.Data.UUID, Client.Self.AgentID, true, true, false, // InventorySortOrder.ByName); // first scan this folder for text foreach (InventoryNode iNode in folder.Nodes.Values) { if (BackupWorker.CancellationPending) return; if (iNode.Data is OpenMetaverse.InventoryItem) { InventoryItem ii = iNode.Data as InventoryItem; if (ii.AssetType == AssetType.LSLText || ii.AssetType == AssetType.Notecard) { // check permissions on scripts if (ii.AssetType == AssetType.LSLText) { if ((ii.Permissions.OwnerMask & PermissionMask.Modify) == PermissionMask.None) { // skip this one continue; } } string sExtension = (ii.AssetType == AssetType.LSLText) ? ".lsl" : ".txt"; // make the output file string sPath = sPathSoFar + @"\" + MakeValid(ii.Name.Trim()) + sExtension; // create the new qdi QueuedDownloadInfo qdi = new QueuedDownloadInfo(sPath, ii.AssetUUID, iNode.Data.UUID, UUID.Zero, Client.Self.AgentID, ii.AssetType); // add it to the queue lock (PendingDownloads) { TextItemsFound++; PendingDownloads.Enqueue(qdi); } } } } // now run any subfolders foreach (InventoryNode i in folder.Nodes.Values) { if (BackupWorker.CancellationPending) return; else if (i.Data is OpenMetaverse.InventoryFolder) BackupFolder(i, sPathSoFar + @"\" + MakeValid(i.Data.Name.Trim())); } }
/// <summary> /// Updates the state of the InventoryNode and inventory data structure that /// is responsible for the InventoryObject. If the item was previously not added to inventory, /// it adds the item, and updates structure accordingly. If it was, it updates the /// InventoryNode, changing the parent node if <code>item.parentUUID</code> does /// not match <code>node.Parent.Data.UUID</code>. /// /// You can not set the inventory root folder using this method /// </summary> /// <param name="item">The InventoryObject to store</param> public void UpdateNodeFor(InventoryBase item) { lock (Items) { InventoryNode itemParent = null; if (item.ParentUUID != UUID.Zero && !Items.TryGetValue(item.ParentUUID, out itemParent)) { // OK, we have no data on the parent, let's create a fake one. InventoryFolder fakeParent = new InventoryFolder(item.ParentUUID); fakeParent.DescendentCount = 1; // Dear god, please forgive me. itemParent = new InventoryNode(fakeParent); Items[item.ParentUUID] = itemParent; // Unfortunately, this breaks the nice unified tree // while we're waiting for the parent's data to come in. // As soon as we get the parent, the tree repairs itself. Logger.DebugLog("Attempting to update inventory child of " + item.ParentUUID.ToString() + " when we have no local reference to that folder", Client); if (Client.Settings.FETCH_MISSING_INVENTORY) { // Fetch the parent List<UUID> fetchreq = new List<UUID>(1); fetchreq.Add(item.ParentUUID); //Manager.FetchInventory(fetchreq); // we cant fetch folder data! :-O } } InventoryNode itemNode; if (Items.TryGetValue(item.UUID, out itemNode)) // We're updating. { InventoryNode oldParent = itemNode.Parent; // Handle parent change if (oldParent == null || itemParent == null || itemParent.Data.UUID != oldParent.Data.UUID) { if (oldParent != null) { lock (oldParent.Nodes.SyncRoot) oldParent.Nodes.Remove(item.UUID); } if (itemParent != null) { lock (itemParent.Nodes.SyncRoot) itemParent.Nodes[item.UUID] = itemNode; } } itemNode.Parent = itemParent; FireOnInventoryObjectUpdated(itemNode.Data, item); itemNode.Data = item; } else // We're adding. { itemNode = new InventoryNode(item, itemParent); Items.Add(item.UUID, itemNode); FireOnInventoryObjectAdded(item); } } }
public string FindFullInventoryPath(InventoryNode input, string pathConstruct) { if (input.Parent == null) { return pathConstruct.TrimEnd('/'); } else { pathConstruct = input.Data.Name + "/" + pathConstruct; return FindFullInventoryPath (input.Parent, pathConstruct); } }
public void TraverseNodes(InventoryNode start, TimeSpan maxTime) { TraverseNodesUnsorted(start, maxTime); start.Sort(); }
public void TraverseNodes(InventoryNode start) { TraverseNodes(start,TimeSpan.FromSeconds(10)); }
public InventoryNodeDictionary(InventoryNode parentNode) { parent = parentNode; }
private void TraverseAndQueueNodes(InventoryNode start) { if (start.NeedsUpdate) { lock (QueuedFolders) { lock (FolderFetchRetries) { int retries = 0; FolderFetchRetries.TryGetValue(start.Data.UUID, out retries); if (retries < 3) { if (!QueuedFolders.Contains(start.Data.UUID)) { QueuedFolders.Add(start.Data.UUID); } } FolderFetchRetries[start.Data.UUID] = retries + 1; } } } foreach (InventoryBase item in Inventory.GetContents((InventoryFolder)start.Data)) { if (item is InventoryFolder) { TraverseAndQueueNodes(Inventory.GetNodeFor(item.UUID)); } } }
protected InventoryNode FindFolderKeywordsInternal(InventoryNode currentNode, string[] keywords) { bool mustSkip = false; foreach(string kw in keywords) { if (!mustSkip) { if (!currentNode.Data.Name.ToLower().Contains(kw.ToLower())) { mustSkip = true; break; } } } if (!mustSkip) { return currentNode; } foreach (var n in currentNode.Nodes.Values) { if (n.Data.Name.StartsWith(".")) continue; var res = FindFolderKeywordsInternal(n, keywords); if (res != null) { return res; } } return null; }
private void TraverseDir(InventoryNode node, string path) { foreach (InventoryNode n in node.Nodes.Values) { if (n.Data is InventoryFolder) { TraverseDir(n, Path.Combine(path, RadegastInstance.SafeFileName(n.Data.Name))); } else { InventoryItem item = (InventoryItem)n.Data; PermissionMask fullPerm = PermissionMask.Modify | PermissionMask.Copy | PermissionMask.Transfer; if ((item.Permissions.OwnerMask & fullPerm) != fullPerm) continue; if (item.AssetType == AssetType.LSLText || item.AssetType == AssetType.Notecard) { ListViewItem lvi = new ListViewItem(); lvi.Text = n.Data.Name; lvi.Tag = n.Data; lvi.Name = n.Data.UUID.ToString(); string filePartial = Path.Combine(path, RadegastInstance.SafeFileName(n.Data.Name)); ListViewItem.ListViewSubItem fileName = new ListViewItem.ListViewSubItem(lvi, filePartial); lvi.SubItems.Add(fileName); ListViewItem.ListViewSubItem status = new ListViewItem.ListViewSubItem(lvi, "Fetching asset"); lvi.SubItems.Add(status); BeginInvoke(new MethodInvoker(() => { lvwFiles.Items.Add(lvi); lvwFiles.EnsureVisible(lvwFiles.Items.Count - 1); })); Asset receivedAsset = null; using (AutoResetEvent done = new AutoResetEvent(false)) { client.Assets.RequestInventoryAsset(item, true, (AssetDownload transfer, Asset asset) => { if (transfer.Success) { receivedAsset = asset; } done.Set(); } ); done.WaitOne(30 * 1000, false); } if (receivedAsset == null) { BeginInvoke(new MethodInvoker(() => status.Text = "Failed to fetch asset")); } else { BeginInvoke(new MethodInvoker(() => status.Text = "Saving...")); string fullName = string.Empty; string dirName = string.Empty; try { switch (item.AssetType) { case AssetType.Notecard: fullName = folderName + filePartial + ".txt"; dirName = Path.GetDirectoryName(fullName); if (!Directory.Exists(dirName)) { Directory.CreateDirectory(dirName); } AssetNotecard note = (AssetNotecard)receivedAsset; if (note.Decode()) { File.WriteAllText(fullName, note.BodyText, System.Text.Encoding.UTF8); } else { Logger.Log(string.Format("Falied to decode asset for '{0}' - {1}", item.Name, receivedAsset.AssetID), Helpers.LogLevel.Warning, client); } break; case AssetType.LSLText: fullName = folderName + filePartial + ".lsl"; dirName = Path.GetDirectoryName(fullName); if (!Directory.Exists(dirName)) { Directory.CreateDirectory(dirName); } AssetScriptText script = (AssetScriptText)receivedAsset; if (script.Decode()) { File.WriteAllText(fullName, script.Source, System.Text.Encoding.UTF8); } else { Logger.Log(string.Format("Falied to decode asset for '{0}' - {1}", item.Name, receivedAsset.AssetID), Helpers.LogLevel.Warning, client); } break; } BeginInvoke(new MethodInvoker(() => { fileName.Text = fullName; status.Text = "Saved"; lblStatus.Text = string.Format("Saved {0} items", ++fetched); })); } catch (Exception ex) { BeginInvoke(new MethodInvoker(() => status.Text = "Failed to save " + Path.GetFileName(fullName) + ": " + ex.Message)); } } } } } }
private string Fullpath(InventoryManager manager, InventoryNode item) { if (item == null) return ""; return Fullpath(manager, item.Parent) + "/" + item.Data.Name; }
private List<InventoryNode> TraverseDir(InventoryNode node) { List<InventoryNode> nodes = new List<InventoryNode>(node.Nodes.Values); List<InventoryNode> textures = new List<InventoryNode>(); foreach(InventoryNode n in nodes) { if (n.Data is InventoryFolder) { List<InventoryNode> nn = TraverseDir(n); foreach(InventoryNode i in nn) textures.Add(i); } else { InventoryItem item = (InventoryItem)n.Data; if (item.InventoryType == InventoryType.Texture) textures.Add(n); } } return textures; }
public void AllSubfolderWearables(InventoryNode root, ref List<InventoryItem> WearableItems) { foreach (var n in root.Nodes.Values) { if (!n.Data.Name.StartsWith(".")) { if (n.Data is InventoryFolder) { AllSubfolderWearables(n, ref WearableItems); } else { WearableItems.Add((InventoryItem)n.Data); } } } }
/// <summary> /// Updates the state of the InventoryNode and inventory data structure that /// is responsible for the InventoryObject. If the item was previously not added to inventory, /// it adds the item, and updates structure accordingly. If it was, it updates the /// InventoryNode, changing the parent node if <code>item.parentUUID</code> does /// not match <code>node.Parent.Data.UUID</code>. /// /// You can not set the inventory root folder using this method /// </summary> /// <param name="item">The InventoryObject to store</param> public void UpdateNodeFor(InventoryBase item) { lock (Items) { InventoryNode itemParent = null; if (item.ParentUUID != UUID.Zero && !Items.TryGetValue(item.ParentUUID, out itemParent)) { // OK, we have no data on the parent, let's create a fake one. InventoryFolder fakeParent = new InventoryFolder(item.ParentUUID); fakeParent.DescendentCount = 1; // Dear god, please forgive me. itemParent = new InventoryNode(fakeParent); Items[item.ParentUUID] = itemParent; // Unfortunately, this breaks the nice unified tree // while we're waiting for the parent's data to come in. // As soon as we get the parent, the tree repairs itself. //Logger.DebugLog("Attempting to update inventory child of " + // item.ParentUUID.ToString() + " when we have no local reference to that folder", Client); if (Client.Settings.FETCH_MISSING_INVENTORY) { // Fetch the parent List <UUID> fetchreq = new List <UUID>(1); fetchreq.Add(item.ParentUUID); } } InventoryNode itemNode; if (Items.TryGetValue(item.UUID, out itemNode)) // We're updating. { InventoryNode oldParent = itemNode.Parent; // Handle parent change if (oldParent == null || itemParent == null || itemParent.Data.UUID != oldParent.Data.UUID) { if (oldParent != null) { lock (oldParent.Nodes.SyncRoot) oldParent.Nodes.Remove(item.UUID); } if (itemParent != null) { lock (itemParent.Nodes.SyncRoot) itemParent.Nodes[item.UUID] = itemNode; } } itemNode.Parent = itemParent; if (m_InventoryObjectUpdated != null) { OnInventoryObjectUpdated(new InventoryObjectUpdatedEventArgs(itemNode.Data, item)); } itemNode.Data = item; } else // We're adding. { itemNode = new InventoryNode(item, itemParent); Items.Add(item.UUID, itemNode); if (m_InventoryObjectAdded != null) { OnInventoryObjectAdded(new InventoryObjectAddedEventArgs(item)); } } } }
protected string GetWornIndicator(InventoryNode node) { var currentOutfit = client.Appearance.GetWearables(); var currentAttachments = client.Network.CurrentSim.ObjectsPrimitives.FindAll(p => p.ParentID == client.Self.LocalID); int myItemsCount = 0; int myItemsWornCount = 0; foreach (var n in node.Nodes.Values) { if (CurrentOutfitFolder.CanBeWorn(n.Data) && !n.Data.Name.StartsWith(".")) { myItemsCount++; if ((n.Data is InventoryWearable && CurrentOutfitFolder.IsWorn(currentOutfit, (InventoryItem)n.Data)) || CurrentOutfitFolder.IsAttached(currentAttachments, (InventoryItem)n.Data)) { myItemsWornCount++; } } } List<InventoryItem> allItems = new List<InventoryItem>(); foreach (var n in node.Nodes.Values) { if (n.Data is InventoryFolder && !n.Data.Name.StartsWith(".")) { AllSubfolderWearables(n, ref allItems); } } int allItemsCount = 0; int allItemsWornCount = 0; foreach (var n in allItems) { if (CurrentOutfitFolder.CanBeWorn(n) && !n.Name.StartsWith(".")) { allItemsCount++; if ((n is InventoryWearable && CurrentOutfitFolder.IsWorn(currentOutfit, n)) || CurrentOutfitFolder.IsAttached(currentAttachments, n)) { allItemsWornCount++; } } } return WornIndicator(myItemsCount, myItemsWornCount) + WornIndicator(allItemsCount, allItemsWornCount); }
private void TraverseNodes(InventoryNode start) { bool has_items = false; foreach (InventoryNode node in start.Nodes.Values) { if (node.Data is InventoryItem) { has_items = true; break; } } if (!has_items || start.NeedsUpdate) { InventoryFolder f = (InventoryFolder)start.Data; AutoResetEvent gotFolderEvent = new AutoResetEvent(false); bool success = false; EventHandler<FolderUpdatedEventArgs> callback = delegate(object sender, FolderUpdatedEventArgs ea) { if (f.UUID == ea.FolderID) { if (((InventoryFolder)Inventory.Items[ea.FolderID].Data).DescendentCount <= Inventory.Items[ea.FolderID].Nodes.Count) { success = true; gotFolderEvent.Set(); } } }; client.Inventory.FolderUpdated += callback; fetchFolder(f.UUID, f.OwnerID, true); gotFolderEvent.WaitOne(30 * 1000, false); client.Inventory.FolderUpdated -= callback; if (!success) { Logger.Log(string.Format("Failed fetching folder {0}, got {1} items out of {2}", f.Name, Inventory.Items[f.UUID].Nodes.Count, ((InventoryFolder)Inventory.Items[f.UUID].Data).DescendentCount), Helpers.LogLevel.Error, client); } } foreach (InventoryBase item in Inventory.GetContents((InventoryFolder)start.Data)) { if (item is InventoryFolder) { TraverseNodes(Inventory.GetNodeFor(item.UUID)); } } }