#!/usr/bin/env python """ Bookmarker - A bookmarks CGI, like delicious and such. License: GPL 2; share and enjoy! Author: Sean B. Palmer, inamidst.com """ import cgitb; cgitb.enable() import sys, os, re, cgi, time, urllib r_line = re.compile(r'^([^"<>\s]+) (?:- )?(.*?)(?: +\(([^()]+)\))?$') r_title = re.compile(r'(?ims)([^<]+)') method = os.environ.get('REQUEST_METHOD') bufsize = 2048 class Grab(urllib.URLopener): def __init__(self, *args): self.version = "Mozilla/5.0 (Bookmarker)" urllib.URLopener.__init__(self, *args) def http_error_default(self, url, fp, errcode, errmsg, headers): return urllib.addinfourl(fp, [headers, errcode], "http:" + url) urllib._urlopener = Grab() if method == 'POST': form = cgi.FieldStorage() form.__call__ = lambda s: form[s].value def serve(status, body, mime=None): mime = mime or 'text/html' sys.stdout.write("Status: %s\r\n" % status) sys.stdout.write("Content-Type: %s; charset=utf-8\r\n\r\n" % mime) sys.stdout.write(body) sys.exit() def getTitle(uri): try: u = urllib.urlopen(uri) except: return uri else: info = u.info() if isinstance(info, list): return uri if not info.get('Content-Type').count('text/html'): u.close() return uri html = '' while 1: s = u.read(bufsize) if not s: break html += s m = r_title.search(html) if m: u.close() title = m.group(1) return title.replace('\n', ' ').replace('\r', ' ') u.close() return uri def add(): # @@ get SCRIPT_NAME and munge it serve(200, """
""") def mkindex(): b = {} f = open('raw-bookmarks.txt') while 1: line = f.readline() if not line: break line = line.rstrip('\r\n') t, uri, title, desc = line.split('\t') if b.has_key(t[:10]): b[t[:10]].append((t[-8:], uri, title, desc)) else: b[t[:10]] = [(t[-8:], uri, title, desc)] f.close() days = b.keys() days.sort() days.reverse() result = ['Some Bookmarks'] link = '' result.append(link) result.append('

Some Bookmarks

') for day in days: pages = b[day] pages.sort() result.append('

%s:

' % day) result.append('') result.append('
') result.append('Sean B. Palmer') result.append('
') f = open('bookmarks.html', 'w') f.write('\n'.join(result)) f.close() def post(): if not form.has_key('text'): serve(500, '

Form must have key "text".

\n') text = form('text') if not text.strip(): mkindex() serve(200, "Rebuilt!\n", "text/plain") lines = text.splitlines() t = time.strftime('%Y-%m-%dT%H:%M:%S', time.gmtime()) f = open('raw-bookmarks.txt', 'a') for line in lines: line = line.strip() if not line: continue if line.find(' ') < 0: uri = line title = getTitle(uri) desc = '' else: m = r_line.match(line) if m: uri, title, desc = m.groups() else: serve(500, '

Invalid line: %r

\n' % line) uri = uri.replace('\t', '%09') title = (title or '').strip().replace('\t', ' ') desc = (desc or '').strip().replace('\t', ' ') f.write(t + '\t' + uri + '\t' + title + '\t' + desc + '\n') f.close() mkindex() serve(200, "Added!\n", "text/plain") def main(args=None): if method == 'GET': add() elif method == 'POST': post() else: serve(501, "

Method must be either GET or POST

\n") if __name__=="__main__": main()