/// <summary>Forward OnNext</summary> public void OnNext(IEvent @event) { // A component observer registers in. if (@event is IStartEvent) { Interlocked.Increment(ref feedingObserverCount); return; } // If observer dispose has completed, don't forward events. if (this.IsDisposing) { return; } // Get child's state object StateInfo state = @event.Observer.State as StateInfo; IPathConverter pathConverter = state?.pathConverter; // Convert paths string newOldPath, newNewPath = null; if (pathConverter == null) { newOldPath = @event.Path; if (@event is IRenameEvent re) { newNewPath = re.NewPath; } } else { if (!pathConverter.ChildToParent(@event.Path, out newOldPath)) { return; } if (@event is IRenameEvent re) { if (!pathConverter.ChildToParent(re.NewPath, out newNewPath)) { return; } } } // Try to decorate event @event = EventDecoration.DecorateObserverAndPath(@event, this, newOldPath, newNewPath, false); // Forward event in this thread, which should be dispatcher's thread Observer.OnNext(@event); }
/// <summary> /// Reads through html <paramref name="html"/> and scans for anchor elements with "href" attributes. /// Validates local or global links that refer to a subfile or subdirectory. /// </summary> /// <param name="baseUri">The uri where the document was loaded. Used for creating absolute uris from relative uris.</param> /// <param name="html">document data as stream</param> /// <param name="pathConverter">convert child urls (the real URIs) back to parent (API caller's) path format</param> /// <returns>array of files</returns> /// <exception cref="Exception"></exception> public virtual IEnumerable <IEntry> ReadEntries(string baseUri, string html, IPathConverter pathConverter) { // Result set HashSet <string> yielded = new HashSet <string>(); // Parse base uri Uri _baseUri = new Uri(baseUri); // Get absolute uri string baseUriAbsolute = _baseUri.GetComponents(UriComponents.Scheme | UriComponents.UserInfo | UriComponents.Host | UriComponents.Port | UriComponents.Path, UriFormat.Unescaped); // Search achors foreach (Match m in anchorPattern.Matches(html)) { // Get href string href = m.Groups[1].Value; // Test not empty if (String.IsNullOrEmpty(href)) { continue; } // Parse attribute href = HttpUtility.HtmlDecode(href); // Entry IEntry entry = null; try { // Parse uri Uri uri = new Uri(_baseUri, href); // Get absolute uri string absoluteUri = uri.GetComponents(UriComponents.Scheme | UriComponents.UserInfo | UriComponents.Host | UriComponents.Port | UriComponents.Path, UriFormat.Unescaped); // Test that is child of baseUri if (absoluteUri.Length <= baseUriAbsolute.Length || !absoluteUri.StartsWith(baseUriAbsolute)) { continue; } // Test only one slash after baseUriAbsolute int slashCount = 0; int startIx = baseUriAbsolute.EndsWith("/") ? baseUriAbsolute.Length : baseUriAbsolute.Length + 1; for (int i = startIx; i < absoluteUri.Length - 1; i++) { // Not slash if (absoluteUri[i] != '/') { continue; } // Add slash slashCount++; break; } // Too many slashes "<baseuri>/Dir/Dir/file", thereof not immediate child if (slashCount >= 1) { continue; } // Already yielded? if (!yielded.Add(absoluteUri)) { continue; } // Extract name String name = GetEntryName(absoluteUri); // Convert path string parentUri; if (!pathConverter.ChildToParent(absoluteUri, out parentUri)) { continue; } // Is directory if (absoluteUri.EndsWith("/")) { entry = new DirectoryEntry(this, parentUri, name, DateTimeOffset.MinValue, DateTimeOffset.MinValue, null); } // Is unknown if is file or directory, so report as both else { entry = new DirectoryAndFileEntry(this, parentUri, name, DateTimeOffset.MinValue, DateTimeOffset.MinValue, -1L, null); } } catch (Exception) { // bad uri continue; } // Yield entry if (entry != null) { yield return(entry); } } }