Backup of David's Livejournal

Rockin' The Geek-Fu, or Not On Your Cloud

I use Foxmarks to keep different computers' bookmarks sync'ed to each other. I have one set of bookmarks for use on home computers, and another set for use at work computers. (I also use delicious for low usage bookmarks I know I want available everywhere.)

With Foxmarks, you can sync your bookmarks to their servers, or you can sync to your own webdav server. I prefer to host my own stuff, so I sync to my own webdav server. The bookmarks are stored in JavaScript's json file format.

But, that doesn't give me the option to browse to the server and easily see the other set of bookmarks. (If I sync'ed to Foxmarks' servers, then I could see them at if I login with my other username.)

What's a Pythonista to do? Write a script that displays the bookmarks as URLs on a webpage! Sweet! Now I host my own repository for my bookmarks, and they're available online in case I need to see the other set's bookmarks. Here's the script:

# by David Blume

import urllib
import simplejson #
import types

urls = ( ('Home Computer', r''),
         ('Work Computer', r'')

def do_insert(folders, command):
    if 'nid' in command:
        args = command['args']
        if args.has_key('ntype'):
            if args['ntype'] == 'folder':
                my_folder = []
                folders[command['nid']] = my_folder
                if command['nid'] != 'ROOT':
                    parent = folders[args['pnid']]
                    parent.append((args['name'], my_folder))
            elif args['ntype'] == 'separator':
                parent = folders[args['pnid']]
            else: # 'bookmark'
                parent = folders[args['pnid']]
                parent.append('<a href="%s">%s</a>' % (args['url'], args['name']))

def print_folders(folders, indent):
    for item in folders:
        if type(item) == types.ListType or type(item) == types.TupleType:
            print '%s%s' % ('  '*(indent * 4), item[0].encode('iso-8859-1', 'replace'))
            print_folders(item[1], indent + 1)
            print '%s%s' % ('  '*(indent * 4), item.encode('iso-8859-1', 'replace'))

if __name__=='__main__':
    print "Content-type: text/html; charset=ISO-8859-1\n\n"
    print '<pre>'
    for url in urls:
        print '<h2>%s</h2>' % url[0]
        sock = urllib.urlopen(url[1])
        json = simplejson.load(sock)
        folders = {}
        for command in json[u'commands']:
            do_insert(folders, command)
        print_folders(folders['ROOT'], 0)
    print '</pre>'
Tags: code, python, web


 (no name) on Jul 24th 2008 at 12:02 AM
Hi, This is exactly what I was looking for! I wonder whether it is possible to have a modified version of the script which accesses the foxmarks.json file from the same directory where the script is, without going through http. In this way I don't need to have my password stored in clear in a DAV server. My proficiency in Python is zero... cheers --e. PS: the OpenID from Yahoo apparently doesn't work for this site :-(

 dblume on Jul 24th 2008 at 12:18 AM
Did you know that FoxMarks is now providing profiles, too, so that you can sync work bookmarks to work, and home bookmarks to home? Then if you go to, you can see either profile. Still, if you insist on syncing to your own webdav server, like I do, you can. The foxmarks.json file will be written to a webdav server. The python script above could be run from anywhere, it doesn't have to on the server. You could run it from C:\ or /home/username/ depending on your OS. The script opens the url file just like your web browser does. So if you run it locally and you don't want to see the html formatting, just delete the parts that say: print "Content-type: text/html; charset=ISO-8859-1\n\n" print '<pre>' and print '</pre>' There you go! It'll just print out your bookmarks without the formatting cruft.

 (no name) on Jul 24th 2008 at 12:29 AM
Thanks for the quick response. However, I meant something else :-) I am going to have both the foxmarks.json file and the python script in the same directory in a protected dav accessible directory handled by a web server, say "https://myserver/dav/foxmarks/". I'd like to invoke the python script from a browser as "https://myserver/dav/foxmarks/" and I'd like to see the outcome as a web page. So far, so good - your script is meant to do exactly this. However, I don't really like the idea that within the script my password is written in clear in a DMZ server (actually it is explicitly forbidden by our rules). I guess that the script could access the foxmarks.json file directly as a file, instead to go through the URL "https://user:pass@myserver/dav/foxmarks/foxmarks.json". I tried to use "file://foxmarks.json" but it didn't work. Any suggestion on how to do this? cheers --e.

 dblume on Jul 24th 2008 at 3:06 AM
Oh! At the top, you'd want to additionally
import sys
import os
Then, urls would be something like:
files = ( ('Home Computer', r'foxmarks/foxmarks.json'),
         ('Work Computer', r'foxmarks_work/foxmarks.json')
Then the main section becomes:
if __name__=='__main__':
    for f in files:
        print '%s' % (f[0],)
        f = open(os.path.join(os.path.dirname(sys.argv[0]), f[1]), 'r')
        json = simplejson.load(f)
        folders = {}
        for command in json[u'commands']:
            do_insert(folders, command)
        print_folders(folders['ROOT'], 0)

 (no name) on Nov 23rd 2008 at 2:31 PM
Dear All, I have in vain tried to the script. I run FC9 and did install the simplejson module. Still I get only the code of the py script echoed to the script. I am not conversant with python, but something tells me this must be something simple. As usual, any help is most appreciated. Cheers, Paul MUnters