[XML-SIG] Useless fun thing for XML - comments or helpers?

Fredrik Lundh fredrik@pythonware.com
Thu, 3 Sep 1998 11:28:02 +0100


>MSIE has the concept of "Favorites" (Bookmarks in Netscape speak) built in
>at the Operating System level.  It is really quite trivial - a special
>folder (directory) called "Favorites" exists, and this is filled with normal
>Windows95 "shortcuts".  If this folder contains sub-folders, then these are
>shown as sub-menus on the favorites menu.
>
>It has bothered me for a while that this makes it quite hard to "publish"
>(or even archive) the Favourites.
>
>So my idea for a mini project is:
>* Python code can locate and traverse this "favorites" directory.  It can
>use the Windows "shortcuts" API to determine the underlying URL, and other
>attributes (such as the time the link was last updated, etc).
>* The above code can generate XML - the attributes for each shortcut can
>appear in the XML.
>* Code can be written to format the XML into pretty HTML, so people could
>publish their favorites, as seemed to be common a while ago
>* Later code could be written to parse an existing XML file, and update the
>favorites themselves.  This would allow me to send my favorites to someone
>else, and have them imported locally, for example.

Here's a first stab.  This is tested with MSIE 5.0 on a Swedish NT installation
(so you definitely need to change the directory to run it -- a production version
should of course use the registry to find out where the directory is located).

Don't know if earlier versions used shell shortcuts; if that's the case, the
"geturl" stuff needs to be rewritten.

Cheers /F

#
# convert "favourites" directory to an XML file
#

import os, string
from cgi import escape

DIR = "Favoriter" # swedish version

class Node:

    def __init__(self, name):
        self.name = name
        self.data = []

    def append(self, item):
        self.data.append(item)

    def dump(self, level=0):
        
        if not level:
            print "<?xml version='1.0' standalone='yes'?>"

        prefix = level * " "

        print prefix + "<node>"
        if self.name:
            print prefix, "<name>" + escape(self.name) + "</name>"

        for item in self.data:
            if isinstance(item, Node):
                item.dump(level+1)
            else:
                name, url = item
                print prefix, "<bookmark>"
                print prefix, " <name>" + escape(name) + "</name>"
                print prefix, " <url>" + escape(url) + "</url>"
                print prefix, "</bookmark>"

        print prefix + "</node>"


class Bookmarks:

    def dump(self):
        self.root.dump()


class MSIE(Bookmarks):
    # internet explorer

    def __init__(self):
        # FIXME: use registry for this!

        self.root = Node(None)
        self.path = os.path.join(os.environ["USERPROFILE"], DIR)

        self.__walk(self.root)

    def __walk(self, this, subpath=[]):
        # traverse favourites folder
        path = os.path.join(self.path, string.join(subpath, os.sep))
        for file in os.listdir(path):
            fullname = os.path.join(path, file)
            if os.path.isdir(fullname):
                node = Node(file)
                this.append(node)
                self.__walk(node, subpath + [file])
            else:
                url = self.__geturl(fullname)
                if url:
                    this.append((os.path.splitext(file)[0], url))

    def __geturl(self, file):
        try:
            fp = open(file)
            if fp.readline() != "[InternetShortcut]\n":
                return None
            while 1:
                s = fp.readline()
                if not s:
                    break
                if s[:4] == "URL=":
                    return s[4:-1]
        except IOError:
            pass
        return None


bookmarks = MSIE()
bookmarks.dump()