Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Firefox Bookmark Manager by C# and XML

0.00/5 (No votes)
24 Sep 2008 1  
With KingMark you can exchange your bookmarks between Firefox and IE
Firefox bookmark manager

Firefox bookmark manager

Introduction

This is a simple Firefox bookmark manager. With KingMark you can import, manage and export Firefox bookmarks as a HTML or *.url or XML file. KingMark works with XML, first converts the Firefox bookmark file into the XML file and then converts it into the HTML file.

Using the Code

Creating XML file

KingMark creates an XML file with unique names for each node. For example, this is a node in the XML file:

<NODE9 NAME="FireFox" ADD_DATE="1213909970" 
		LAST_MODIFIED="1220234375" DESC="">
    <BOOKMARK10 NAME="Mozilla - Home" 
		HREF="http://en-us.www.mozilla.com/en-US/" 
		  SHORTCUTURL="mozila" DESC="" 
        ADD_DATE="1183006386" LAST_MODIFIED="1220234476" 
        ICON_URI="" ICON="" />

    <BOOKMARK11 NAME="mozillaZine Forums" 
		HREF="http://forums.mozillazine.org/index.php" 
        SHORTCUTURL="" DESC="" ADD_DATE="1214351419" LAST_MODIFIED="1220233809" 
        ICON_URI="" ICON="" />

    <BOOKMARK12 NAME="Mozilla Support" 
		HREF="http://support.mozilla.com/tiki-my_tiki.php#content_forum" 
        SHORTCUTURL="" DESC="" ADD_DATE="1214143305" LAST_MODIFIED="1220233808" 
        ICON_URI="" ICON="" />

    <BOOKMARK13 NAME="AfzoneHaye FF" 
		HREF="http://addons.mozillafirefox.ir/" SHORTCUTURL="" 
        DESC="" ADD_DATE="1218070432" LAST_MODIFIED="1219953174" 
        ICON_URI="" ICON="" />

</NODE9>

As you can see, each node has a unique name so I used these names for denominating TreeView nodes' names. Well by this denomination we can find each node in an XML file and TreeView control easily.

I saved the biggest node number (for example : <BOOKMARK13 ... />) in an attribute (ELEMENTS) in the root node. With this attribute we can find the latest number used in denomination and we start denominating after it. And with OPTIMIZE XML FILE, KingMark arranges the XML elements .

First: KingMark converts the FF BookMark file (HTML file) to the List<string> object (intermediate code)

You can see the intermediate code with checking Trace in Settings.

When you check Trace, the private void trace(List<string> list) method creates trace.txt beside your FF bookmark file that includes intermediate code for generating an XML file.

After KingMark converts the List<string> object to the XML file with the System.Xml.XmlWriter class and the below method:

private void ListToXml(List<string> list)
{
    string name = "";
    string href = "";
    string icon = "";
    string iconUrl = "";
    string desc = "";
    string keyWords = "";
    string addDate = "";
    string lastModified = "";
    try
    {
        XmlWriterSettings settings = new XmlWriterSettings();
        settings.Indent = true;
        //settings.NewLineOnAttributes = true;
        settings.Encoding = Encoding.UTF8;
        settings.ConformanceLevel = ConformanceLevel.Document;
        System.Xml.XmlWriter Writer;
        Writer = XmlWriter.Create(temporaryFileName, settings);
        Writer.WriteStartDocument();
        Writer.WriteComment(XmlDescription);
        Writer.WriteStartElement(rootNodeName);
        Writer.WriteAttributeString("ELEMENTS", list.Count.ToString());
        for (int i = 1; i < list.Count; i++)
        {
            //Nodes separator
            if (Regex.IsMatch(list[i], @"\<HR\>"))
            {
                //Writer.WriteStartElement("HR");
                //Writer.WriteEndElement();
                continue;
            }
            else if (Regex.IsMatch(list[i], @"\<NODE\>"))
            {
                //node's NAME
                name = Regex.Match(list[i - 1].Trim(), "NAME=\"[^\"]*\"").ToString();
                name = Regex.Replace(name, "NAME|\"|=", "");
                //node's DESC
                desc = Regex.Match(list[i - 1].Trim(), 
					"DESC=\"[^\"]*\"").ToString();
                desc = Regex.Replace(desc, "DESC|\"|=", "");
                //node's ADD_DATE
                addDate = Regex.Match(list[i - 1].Trim(), 
					"ADD_DATE=\"[^\"]*\"").ToString();
                addDate = Regex.Replace(addDate, "ADD_DATE|\"|=", "");
                //node's LAST_MODIFIED
                lastModified = Regex.Match(list[i - 1].Trim(), 
					"LAST_MODIFIED=\"[^\"]*\"").ToString();
                lastModified = Regex.Replace(lastModified, 
					"LAST_MODIFIED|\"|=", "");
                //\\
                Writer.WriteStartElement("NODE" + i.ToString());
                Writer.WriteAttributeString("NAME", name);
                Writer.WriteAttributeString("ADD_DATE", addDate);
                Writer.WriteAttributeString("LAST_MODIFIED", lastModified);
                Writer.WriteAttributeString("DESC", desc);
            }
            else if (list[i].Trim() == "</NODE>")
            {
                if (i + 1 != list.Count)
                Writer.WriteEndElement();
            }
            else if (!Regex.IsMatch(list[i + 1], @"\<NODE\>"))
            {
                //bookmark's name extracting
                name = Regex.Match(list[i], "NAME=\"[^\"]*\"").ToString();
                name = Regex.Replace(name, "NAME|\"|=", "");
                //bookmark's address extracting
                href = Regex.Match(list[i].Trim(), 
					"HREF=\"[^\"]*\"").ToString();
                href = Regex.Replace(href, "HREF|\"|=", "");
                //bookmark's icon's URL extracting
                iconUrl = Regex.Match(list[i].Trim(), 
					"ICON_URI=\"[^\"]*\"").ToString();
                iconUrl = Regex.Replace(iconUrl, 
					"ICON_URI|\"|=", "");
                //bookmark's icon extracting
                icon = Regex.Match(list[i].Trim(), 
					"ICON=\"[^\"]*\"").ToString();
                icon = Regex.Replace(icon, 
					"\"|ICON|=", "");
                //bookmark's description extracting
                desc = Regex.Match(list[i].Trim(), 
					"DESC=\"[^\"]*\"").ToString();
                desc = Regex.Replace(desc, "DESC|\"|=", "");
                //bookmark's SHORTCUTURL extracting
                keyWords = Regex.Match(list[i].Trim(), 
					"SHORTCUTURL=\"[^\"]*\"").ToString();
                keyWords = Regex.Replace(keyWords, 
					"SHORTCUTURL|\"|=", "");
                //ADD_DATE
                addDate = Regex.Match(list[i].Trim(), 
					"ADD_DATE=\"[^\"]*\"").ToString();
                addDate = Regex.Replace(addDate, "ADD_DATE|\"|=", "");
                //LAST_MODIFIED
                lastModified = Regex.Match(list[i].Trim(), 
					"LAST_MODIFIED=\"[^\"]*\"").ToString();
                lastModified = Regex.Replace(lastModified, 
					"LAST_MODIFIED|\"|=", "");
                //\\
                /////////////////////////////////////////////////////////////
                //write above data in XML file
                Writer.WriteStartElement("BOOKMARK" + i.ToString());
                Writer.WriteAttributeString("NAME", name.Trim());
                Writer.WriteAttributeString("HREF", href.Trim());
                Writer.WriteAttributeString("SHORTCUTURL", keyWords.Trim());
                Writer.WriteAttributeString("DESC", desc.Trim());
                Writer.WriteAttributeString("ADD_DATE", addDate.Trim());
                Writer.WriteAttributeString("LAST_MODIFIED", lastModified.Trim());
                Writer.WriteAttributeString("ICON_URI", iconUrl.Trim());
                Writer.WriteAttributeString("ICON", icon.Trim());
                Writer.WriteEndElement();
            }
        }
        //Writing close tag for the root element.
        Writer.WriteEndDocument();
        Writer.Flush();
        Writer.Close();
        X_Element = XElement.Load(temporaryFileName);
    }
    catch (Exception ex)
    {
        StackFrame file_info = new StackFrame(true);
        error(ref file_info, ex.Message);
    }
}

XML File to TreeView

After creating the XML file, an XML file should be loaded in the TreeView control. (see below methods) If you check Load Icons in settings each icon of nodes will show.

/// 
/// Converts XML file to treeView
/// 
private void XmlToTree()
{
    optimize_menuItem.Enabled = exportIE_favorites.Enabled = 
			exportXML_menuItem.Enabled =
                            exportHtml_menuItem.Enabled = true;
    this.treeViewBookMark.Enabled = true;
    this.XElementClopboard = null;
    this.TreeNodeClipboard = null;

    try
    {
        // SECTION 1. Create a DOM Document and load the XML data into it.
        XmlDocument dom = new XmlDocument();
        dom.Load(this.temporaryFileName);

        // SECTION 2. Initialize the TreeView control.
        treeViewBookMark.Nodes.Clear();
        treeViewBookMark.Nodes.Add(new TreeNode(dom.DocumentElement.Name));
        TreeNode tNode = new TreeNode(rootNodeName);
        tNode = treeViewBookMark.Nodes[0];
        tNode.Name = rootNodeName;

        // SECTION 3. Populate the TreeView with the DOM nodes.
        AddNode(dom.DocumentElement, tNode);

        treeViewBookMark.SelectedNode = treeViewBookMark.Nodes[0];
        selected_node = treeViewBookMark.Nodes[0];
        treeViewBookMark.SelectedNode.Expand();
    }
    catch (Exception ex)
    {
        textBoxIconURL.Enabled = textBoxDesc.Enabled = textBoxName.Enabled 
			= buttonDelIcon.Enabled = textBoxKeyWords.Enabled 
			= textBoxHref.Enabled = false;
        optimize_menuItem.Enabled = exportIE_favorites.Enabled 
			= exportXML_menuItem.Enabled = exportHtml_menuItem.Enabled
                           = false;
        this.treeViewBookMark.Enabled = false;

        StackFrame file_info = new StackFrame(true);
        error(ref file_info, ex.Message);
        return;
    }
}

/// 
/// Creates treeView
/// References : 
/// ms-help://MS.MSDNQTR.v90.en/enu_kbnetframeworkkb/netframeworkkb/317597.htm
/// http://support.microsoft.com/kb/317597
/// 
private void AddNode(XmlNode inXmlNode, TreeNode inTreeNode)
{
    try
    {
        XmlNode xNode;
        TreeNode tNode;
        XmlNodeList nodeList;
        int i;
        int j = -1;

        // Loop through the XML nodes until the leaf is reached.
        // Add the nodes to the TreeView during the looping process.
        if (inXmlNode.HasChildNodes)
        {
            nodeList = inXmlNode.ChildNodes;
            for (i = 0; i <= nodeList.Count - 1; i++) 
            {
                if (inXmlNode.ChildNodes[i].Name.Equals("HR"))
                    continue;
                j++;

                xNode = inXmlNode.ChildNodes[i];
                TreeNode newTreeNode;
                newTreeNode = new TreeNode(xNode.Attributes["NAME"].Value);
                newTreeNode.Name = xNode.Name;
                //تعیین عکس هر گره
                //assigns icon of each node -> this code needs more process
                if (loadIcons_menuItem.Checked)
                {
                    Image icon = createIcon(xNode.Name);
                    if (Regex.IsMatch(inXmlNode.ChildNodes[i].Name, "NODE"))
                    {
                        newTreeNode.ImageIndex = 0;
                        newTreeNode.SelectedImageIndex = 0;
                    }
                    else if (icon != null && Regex.IsMatch(inXmlNode.ChildNodes[i].Name,
                        "BOOKMARK"))
                    {
                        imageList1.Images.Add(icon);
                        newTreeNode.ImageIndex = imageList1.Images.Count - 1;
                        newTreeNode.SelectedImageIndex = imageList1.Images.Count - 1;
                    }
                    else
                    {
                        newTreeNode.ImageIndex = 1;
                        newTreeNode.SelectedImageIndex = 1;
                    }
                }
                else
                {
                    if (Regex.IsMatch(inXmlNode.ChildNodes[i].Name, "NODE"))
                    {
                        newTreeNode.ImageIndex = 0;
                        newTreeNode.SelectedImageIndex = 0;
                    }
                    else if (Regex.IsMatch(inXmlNode.ChildNodes[i].Name, "BOOKMARK"))
                    {
                        newTreeNode.ImageIndex = 1;
                        newTreeNode.SelectedImageIndex = 1;
                    }
                }
                //\\
                inTreeNode.Nodes.Add(newTreeNode);
                tNode = inTreeNode.Nodes[j];
                AddNode(xNode, tNode);
            }
        }
        else
        {
            // Here you need to pull the data from the XmlNode based on the
            // type of node, whether attribute values are required, and so forth.
            inTreeNode.Text = (inXmlNode.Attributes["NAME"].Value).Trim();
        }
    }
    catch (Exception ex)
    {
        textBoxIconURL.Enabled = textBoxDesc.Enabled = 
				textBoxName.Enabled = buttonDelIcon.Enabled = 
				textBoxKeyWords.Enabled = textBoxHref.Enabled =
                                     false;
        optimize_menuItem.Enabled = exportIE_favorites.Enabled = 
				exportXML_menuItem.Enabled =
                                     exportHtml_menuItem.Enabled = false;
        treeViewBookMark.Nodes.Clear();
        this.treeViewBookMark.Enabled = false;

        StackFrame file_info = new StackFrame(true);
        error(ref file_info, ex.Message);
        return;
    }
}

KingMark Features

TreeView Drag-n-Drop

You can export IE favorite files directly, using the Drag a TreeView folder or file out to the Window.

Unlike the above, you can import IE favorite files to KingMark with drag it into the TreeView.

Also, you can import IE6 (I had IE6, maybe on IE7 or IE8 doesn't work) website addresses and FF3 (I had FF3, maybe on FF2 or FF1 doesn't work) website tabs into KingMark with dragging it in its TreeView Control.

  

Exporting Bookmarks for Internet Explorer or Firefox Browser

With KingMark you can export all or part of bookmarks for FF(HTML file) or IE(*.url file)

For exporting all bookmarks use the Export Menu:

For exporting some bookmarks use TreeView's contextMenuStrip:

Export for FF
Export for IE

Quick Search


Searching Firefox bookmark manager

I used LINQ to search the XML file (see below method)

private void textBoxSearchTxt_TextChanged(object sender, EventArgs e)
{
    string searchTxt = Regex.Replace(textBoxSearchTxt.Text.Trim(),
        @"[\$\^\{\[\(\|\)\*\+\?\\]", "");
    if (searchTxt == "")
    {
        this.listView1.Items.Clear();
        return;
    }
    try
    {
        var searchNodes = from nodes in X_Element.Descendants()
                          where
                          (nodes.Attribute("NAME") != null    
                          Regex.IsMatch(nodes.Attribute("NAME").Value, 
                          	searchTxt, RegexOptions.IgnoreCase))
                           || (nodes.Attribute("HREF") != null    
                           Regex.IsMatch(nodes.Attribute("HREF").Value, searchTxt, 
                          	 RegexOptions.IgnoreCase))
                           || (nodes.Attribute("SHORTCUTURL") != null    
                           Regex.IsMatch(nodes.Attribute("SHORTCUTURL").Value,
                               searchTxt, 
                           	RegexOptions.IgnoreCase))
                          select nodes;

        listView1.Items.Clear();

        foreach (var node in searchNodes)
        {
            try
            {
                ListViewItem item = new ListViewItem(new string[] 
                { node.Attribute("NAME").Value, node.Attribute("HREF").Value });
                item.Name = node.Name.ToString();
                listView1.Items.Add(item);
            }
            catch
            {
                continue;
            }
        }
    }
    catch { }
}

Generating Website Preview Image

You can find WebsiteThumbnailImage.cs in my project and figure out how I did it.
Firefox bookmark manager

Notify Icon

When you minimize the KingMark window, KingMark creates a contextMenuStrip with the TreeView nodes and show a notifyIcon here:

And you can access to your bookmarks easily:

How can we convert TreeView to contextMenuStrip:

I wrote these methods to do that, and these method did it well. But if you have a better way I thank you if you say it to me.

void createContextMenuStripNotifyIcon()
{
    try
    {
        if (this.treeViewBookMark.Nodes.Count <= 0) return;
        contextMenuStripNotifyIcon.Items.Clear();
        foreach (TreeNode node in this.treeViewBookMark.Nodes[0].Nodes)
        {
            ToolStripMenuItem toolStripMenuItem = new ToolStripMenuItem();
            if (node.GetNodeCount(true) > 0)
            {
                toolStripMenuItem.BackColor = contextMenuStripNotifyIcon.BackColor;
                toolStripMenuItem.Image = imageList1.Images[node.ImageIndex];
                toolStripMenuItem.Text = node.Text.Length > 30 ? 
                	node.Text.Substring(0, 30) + " ..." : node.Text;
                toolStripMenuItem.Name = node.Name;
                createContextMenuStripNotifyIcon(node, ref toolStripMenuItem);
                contextMenuStripNotifyIcon.Items.Add(toolStripMenuItem);
            }
            else
            {
                toolStripMenuItem.BackColor = contextMenuStripNotifyIcon.BackColor;
                toolStripMenuItem.Image = imageList1.Images[node.ImageIndex];
                toolStripMenuItem.Text = node.Text.Length > 30 ? 
                	node.Text.Substring(0, 30) + " ..." : node.Text;
                toolStripMenuItem.Name = node.Name;
                toolStripMenuItem.MouseDown += 
                	new MouseEventHandler(contextMenuStripNotifyIconItems_MouseDown);
                contextMenuStripNotifyIcon.Items.Add(toolStripMenuItem);
            }
        }
    }
    catch (Exception ex)
    {
        StackFrame file_info = new StackFrame(true);
        error(ref file_info, ex.Message);
    }
}

void createContextMenuStripNotifyIcon(TreeNode nodes,
    ref ToolStripMenuItem toolStripMenuItem)
{
    foreach (TreeNode node in nodes.Nodes)
    {
        if (node.GetNodeCount(true) > 0)
        {
            ToolStripMenuItem newToolStripMenuItem = new ToolStripMenuItem();
            newToolStripMenuItem.BackgroundImage = imageList1.Images[node.ImageIndex];
            newToolStripMenuItem.BackgroundImageLayout = ImageLayout.None;
            newToolStripMenuItem.Text = node.Text.Length > 30 ? 
            	node.Text.Substring(0, 30) + " ..." : node.Text;
            newToolStripMenuItem.Name = node.Name;
            createContextMenuStripNotifyIcon(node, ref newToolStripMenuItem);
            toolStripMenuItem.DropDown.Items.Add(newToolStripMenuItem);
        }
        else
        {
            ToolStripMenuItem newToolStripMenuItem = new ToolStripMenuItem();
            newToolStripMenuItem.BackgroundImage = imageList1.Images[node.ImageIndex];
            newToolStripMenuItem.BackgroundImageLayout = ImageLayout.None;
            newToolStripMenuItem.Text = node.Text.Length > 30 ? 
            	node.Text.Substring(0, 30) + " ..." : node.Text;
            newToolStripMenuItem.Name = node.Name;
            newToolStripMenuItem.MouseDown += 
            	new MouseEventHandler(contextMenuStripNotifyIconItems_MouseDown);
            toolStripMenuItem.DropDown.Items.Add(newToolStripMenuItem);
        }
    }
}

void contextMenuStripNotifyIconItems_MouseDown(object sender, MouseEventArgs e)
{
    try
    {
        if (e.Button == MouseButtons.Left)
            Process.Start(GetHref(((ToolStripMenuItem)sender).Name));
    }
    catch
    {
        StackFrame file_info = new StackFrame(true);
        error(ref file_info, "Invalid URL");
    }
}

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here