Functions/GenXdev.Webbrowser/Find-BrowserBookmark.cs
// ################################################################################
// Part of PowerShell module : GenXdev.Webbrowser // Original cmdlet filename : Find-BrowserBookmark.cs // Original author : René Vaessen / GenXdev // Version : 1.302.2025 // ################################################################################ // Copyright (c) René Vaessen / GenXdev // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // ################################################################################ using System; using System.Collections; using System.Collections.Generic; using System.Linq; using System.Management.Automation; using System.Text.RegularExpressions; namespace GenXdev.Webbrowser { /// <summary> /// <para type="synopsis"> /// Finds bookmarks from one or more web browsers. /// </para> /// /// <para type="description"> /// Searches through bookmarks from Microsoft Edge, Google Chrome, or Mozilla Firefox. /// Returns bookmarks that match one or more search queries in their name, URL, or /// folder path. If no queries are provided, returns all bookmarks from the selected /// browsers. /// </para> /// /// <para type="description"> /// PARAMETERS /// </para> /// /// <para type="description"> /// -Queries <System.String[]><br/> /// One or more search terms to find matching bookmarks. Matches are found in the /// bookmark name, URL, or folder path using wildcard pattern matching.<br/> /// - <b>Aliases</b>: q, Name, Text, Query<br/> /// - <b>Position</b>: 0<br/> /// - <b>Default</b>: (null)<br/> /// </para> /// /// <para type="description"> /// -Edge <System.Management.Automation.SwitchParameter><br/> /// Switch to include Microsoft Edge bookmarks in the search.<br/> /// - <b>Aliases</b>: e<br/> /// - <b>Position</b>: Named<br/> /// - <b>Default</b>: False<br/> /// </para> /// /// <para type="description"> /// -Chrome <System.Management.Automation.SwitchParameter><br/> /// Switch to include Google Chrome bookmarks in the search.<br/> /// - <b>Aliases</b>: ch<br/> /// - <b>Position</b>: Named<br/> /// - <b>Default</b>: False<br/> /// </para> /// /// <para type="description"> /// -Firefox <System.Management.Automation.SwitchParameter><br/> /// Switch to include Mozilla Firefox bookmarks in the search.<br/> /// - <b>Aliases</b>: ff<br/> /// - <b>Position</b>: Named<br/> /// - <b>Default</b>: False<br/> /// </para> /// /// <para type="description"> /// -Count <System.Int32><br/> /// Maximum number of results to return. Must be a positive integer. /// Default is 99999999.<br/> /// - <b>Position</b>: Named<br/> /// - <b>Default</b>: 99999999<br/> /// </para> /// /// <para type="description"> /// -PassThru <System.Management.Automation.SwitchParameter><br/> /// Switch to return complete bookmark objects instead of just URLs. Each bookmark /// object contains Name, URL, and Folder properties.<br/> /// - <b>Position</b>: Named<br/> /// - <b>Default</b>: False<br/> /// </para> /// /// <example> /// <para>Find-BrowserBookmark -Query "github" -Edge -Chrome -Count 10</para> /// <para>Searches Edge and Chrome bookmarks for "github", returns first 10 URLs</para> /// <code> /// Find-BrowserBookmark -Query "github" -Edge -Chrome -Count 10 /// </code> /// </example> /// /// <example> /// <para>bookmarks powershell -e -ff -PassThru</para> /// <para>Searches Edge and Firefox bookmarks for "powershell", returns full objects</para> /// <code> /// bookmarks powershell -e -ff -PassThru /// </code> /// </example> /// </summary> [Cmdlet(VerbsCommon.Find, "BrowserBookmark")] [Alias("bookmarks")] [OutputType(typeof(PSObject))] [OutputType(typeof(string))] public class FindBrowserBookmarkCommand : PSGenXdevCmdlet { /// <summary> /// One or more search terms to find matching bookmarks. Matches are found in the /// bookmark name, URL, or folder path using wildcard pattern matching. /// </summary> [Parameter( Mandatory = false, Position = 0, ValueFromRemainingArguments = false, ValueFromPipeline = true, ValueFromPipelineByPropertyName = true, HelpMessage = "Search terms to find matching bookmarks")] [Alias("q", "Name", "Text", "Query")] [SupportsWildcards()] public string[] Queries { get; set; } /// <summary> /// Switch to include Microsoft Edge bookmarks in the search. /// </summary> [Parameter( Mandatory = false, HelpMessage = "Search through Microsoft Edge bookmarks")] [Alias("e")] public SwitchParameter Edge { get; set; } /// <summary> /// Switch to include Google Chrome bookmarks in the search. /// </summary> [Parameter( Mandatory = false, HelpMessage = "Search through Google Chrome bookmarks")] [Alias("ch")] public SwitchParameter Chrome { get; set; } /// <summary> /// Switch to include Mozilla Firefox bookmarks in the search. /// </summary> [Parameter( Mandatory = false, HelpMessage = "Search through Firefox bookmarks")] [Alias("ff")] public SwitchParameter Firefox { get; set; } /// <summary> /// Maximum number of results to return. Must be a positive integer. /// Default is 99999999. /// </summary> [Parameter( Mandatory = false, HelpMessage = "Maximum number of results to return")] [ValidateRange(1, int.MaxValue)] public int Count { get; set; } = 99999999; /// <summary> /// Switch to return complete bookmark objects instead of just URLs. Each bookmark /// object contains Name, URL, and Folder properties. /// </summary> [Parameter( Mandatory = false, HelpMessage = "Return bookmark objects instead of just URLs")] public SwitchParameter PassThru { get; set; } private PSObject[] bookmarks; /// <summary> /// Begin processing - initialization logic /// </summary> protected override void BeginProcessing() { WriteVerbose("Initializing browser bookmark search"); // Copy parameters to Get-BrowserBookmark var paramsDict = CopyIdenticalParamValues("GenXdev.Webbrowser\\Get-BrowserBookmark"); // Get bookmarks WriteVerbose("Fetching bookmarks from selected browsers"); var getBookmarksScript = ScriptBlock.Create("param($params) GenXdev.Webbrowser\\Get-BrowserBookmark @params"); var bookmarksResult = getBookmarksScript.Invoke(paramsDict); bookmarks = bookmarksResult.Select(r => (PSObject)r).ToArray(); } /// <summary> /// Process record - main cmdlet logic /// </summary> protected override void ProcessRecord() { // Handle case when no search queries provided if (Queries == null || Queries.Length == 0) { WriteVerbose("No search terms specified - returning all bookmarks"); var allBookmarks = bookmarks.Take(Count); foreach (var bookmark in allBookmarks) { WriteObject(bookmark); } return; } // Search bookmarks for matches to any query terms WriteVerbose($"Searching bookmarks for matches to {Queries.Length} queries"); var allResults = new List<PSObject>(); foreach (var query in Queries) { var processedQuery = query; if (!query.Contains("*") && !query.Contains("?")) { processedQuery = "*" + query + "*"; } WriteVerbose($"Processing query: {processedQuery}"); var pattern = WildcardToRegex(processedQuery); var regex = new Regex(pattern, RegexOptions.IgnoreCase); var matchingBookmarks = bookmarks.Where(b => regex.IsMatch(b.Properties["Folder"].Value?.ToString() ?? "") || regex.IsMatch(b.Properties["Name"].Value?.ToString() ?? "") || regex.IsMatch(b.Properties["URL"].Value?.ToString() ?? "")); allResults.AddRange(matchingBookmarks); } var results = allResults.Take(Count); // Return either full bookmark objects or just URLs if (PassThru.ToBool()) { WriteVerbose($"Returning {results.Count()} bookmark objects"); foreach (var bookmark in results) { WriteObject(bookmark); } } else { WriteVerbose($"Returning {results.Count()} bookmark URLs"); foreach (var bookmark in results) { var url = bookmark.Properties["URL"].Value?.ToString(); if (url != null) { WriteObject(url); } } } } /// <summary> /// End processing - cleanup logic /// </summary> protected override void EndProcessing() { // No cleanup needed } /// <summary> /// Converts a PowerShell wildcard pattern to a regular expression pattern /// </summary> /// <param name="pattern">The wildcard pattern to convert</param> /// <returns>The equivalent regular expression pattern</returns> private static string WildcardToRegex(string pattern) { return "^" + Regex.Escape(pattern).Replace("\\*", ".*").Replace("\\?", ".") + "$"; } } } |