#!/usr/bin/python2.5 import cgi, re, os, sys, pickle, ConfigParser from xml.sax.saxutils import escape, quoteattr from glob import glob import config, nonce from get import resize for path in glob(config.openid.code): sys.path.insert(0,path) from openid.consumer import consumer from openid.store import filestore try: store = filestore.FileOpenIDStore(config.openid.filestore) # initialize warn = '' session = None subs = [] sub_all = sub_cmt = sub_new = '' user_name = user_jid = '' # fetch id from post form fs = cgi.FieldStorage() env = os.environ id=fs.getvalue('url','') args = dict([(field.name,field.value) for field in fs.list]) test = fs.has_key('test') # if not found, try cookie if not id: import Cookie, urllib cookie = Cookie.SimpleCookie() if(env.has_key('HTTP_COOKIE')): cookie.load(env['HTTP_COOKIE']) if cookie.has_key('xmpp_id'): id = urllib.unquote(cookie['xmpp_id'].value) elif cookie.has_key('cmt_url'): id = urllib.unquote(cookie['cmt_url'].value) # if xid can be authenticated, restore the session if fs.has_key('xid'): xid = nonce.retrieve(fs.getvalue('xid')) if xid: session = pickle.loads(xid) server = consumer.Consumer(session, store) response = server.complete(args) if response.status != consumer.SUCCESS: session = None warn = '

OpenID login failed

' else: extension = response.extensionResponse('sreg',True) if extension.has_key('nickname'): user_name = extension['nickname'] if extension.has_key('fullname'): user_name = extension['fullname'] # if a session hasn't been established yet, establish one if id and not session and not test: import identity args['REQUEST_METHOD'] = env.get('REQUEST_METHOD','') redirect = identity.lookup(id, args, config.channel.registry) if redirect: print 'Status: 302 Found\r\nLocation: %s\r\n\r\nRedirecting' % redirect sys.exit() else: warn = '

URI not OpenID enabled

' # retrieve session values if session: if env.get('REQUEST_METHOD','')=='POST': session['REQUEST_METHOD'] = 'POST' else: id = session.get('url',id) user_name = session.get('name',user_name) user_jid = session.get('email',user_jid) subs = [name[4:] for name,value in session.items() if name.startswith('sub_')] if session.has_key('xall'): sub_all = ' checked="on"' if session.has_key('xcmt'): sub_cmt = ' checked="on"' if session.has_key('xnew'): sub_new = ' checked="on"' # retrieve POST values if env.get('REQUEST_METHOD','')=='POST': user_name = fs.getvalue('name',user_name) user_jid = fs.getvalue('email',user_jid) subs = [field.name[4:] for field in fs.list if field.name.startswith('sub_')] if fs.has_key('xall'): sub_all = ' checked="on"' if fs.has_key('xcmt'): sub_cmt = ' checked="on"' if fs.has_key('xnew'): sub_new = ' checked="on"' # send a test message if test and user_jid: import xnotify plain_text = "This is a plaintext message. " + \ "If you see this, your client does NOT support XHTML-IM." xhtml = "This is an %s message. " % \ 'XHTML-IM' + \ "If you see this, your client does support XHTML-IM." xnotify.send_message([user_jid], plain_text, xhtml, register=True) # map id to a filename if id: filename = id if id.startswith('http://') or id.startswith('https://'): filename = filename.split('/',2)[-1].strip('/') filename = re.sub(r'[?/:|]+', ',', filename) # if this is an authenticated POST, write out the forms values if id and session and session.get('REQUEST_METHOD','')=='POST' and not test: parser = ConfigParser.ConfigParser() parser.add_section('owner') parser.set('owner','name',user_name) parser.set('owner','jid',user_jid) parser.set('owner','id',id) parser.add_section('subscriptions') parser.set('subscriptions','entries',' '.join(subs)) parser.set('subscriptions','sub_all',bool(sub_all)) parser.set('subscriptions','sub_cmt',bool(sub_cmt)) parser.set('subscriptions','sub_new',bool(sub_new)) parser.write(open(config.directory.registry + filename,'w')) # read registration if id and session and not test: parser = ConfigParser.ConfigParser() parser.read(config.directory.registry + filename) if parser.has_option('owner','name'): user_name = parser.get('owner', 'name') or user_name if parser.has_option('owner','jid'): user_jid = parser.get('owner', 'jid') if parser.has_option('subscriptions','entries'): subs = parser.get('subscriptions','entries').split(' ') if parser.has_option('subscriptions','sub_all'): if parser.getboolean('subscriptions','sub_all'): sub_all = ' checked="on"' if parser.has_option('subscriptions','sub_new'): if parser.getboolean('subscriptions','sub_new'): sub_new = ' checked="on"' if parser.has_option('subscriptions','sub_cmt'): if parser.getboolean('subscriptions','sub_cmt'): sub_cmt = ' checked="on"' # get the ten most recent posts that have recent comments cmt_re = re.compile('\d+-(\d+)\.cmt$') os.chdir(config.directory.data) blogdir = os.listdir('.') blogdir = [(cmt_re.findall(name) or [str(os.stat(name).st_mtime)],name) for name in blogdir] blogdir.sort() blogdir.reverse() latest = [] for mtime, file in blogdir: if file.startswith('.'): continue if file.endswith('.html'): continue post = file.split('-')[0].split('.')[0] if post not in latest: latest.append(post) if len(latest) >= 10: break # ensure all active subscriptions are on the 'latest' list for sub in subs: if sub not in latest: latest.append(sub) # read routes routes = ConfigParser.ConfigParser() routes.read('/home/rubys/.xnotify') xmpp_server = {} for name in routes.sections() + ['DEFAULT']: if routes.has_option(name,'class') and \ routes.get(name,'class') == 'private': continue xmpp_server[name] = routes.get(name,'user').split('@') # save xmpp id as a cookie if id and session: import Cookie, time cookie = Cookie.SimpleCookie() cookie['xmpp_id'] = id expire = time.gmtime(time.time() + 365 * 24 * 60 * 60) expire_date = time.strftime('%a %d-%b-%Y %H:%M:%S GMT', expire) cookie['xmpp_id']['expires'] = expire_date cookie['xmpp_id']['path'] = '/' cookie['xmpp_id']['domain'] = config.channel.link.split('/')[2] print str(cookie) + '\r' except SystemExit: raise except: ####################################################################### # Format tracebacks for display # ####################################################################### import traceback tb = ''.join(apply(traceback.format_exception, sys.exc_info())) import nonce,time nonce.generate(time.time()+86400, tb) print 'Status: 500 Internal Error\r\nContent-type: text/html\r\n' from xml.sax.saxutils import escape print '' print 'CGI Failure' print '' print '

CGI Failure

' print '
traceback:' + escape(tb) + '
' print '' print '' sys.exit() ######################################################################### # Format response # ######################################################################### # conneg if env.get('HTTP_ACCEPT', '').find('application/xhtml+xml') >=0: print 'Content-type: application/xhtml+xml; charset="utf-8"\r\n\r' else: print 'Content-type: text/html; charset="utf-8"\r\n\r' # html header print """ Intertwingly Registration
%s

User Registration









Subscribe to comments via XMPP





Subscribe to comments on specific entries:

""" % (str(xmpp_server), config.channel.link, config.channel.link, config.channel.description.encode('utf-8'), str(warn), quoteattr(str(user_name)), quoteattr(str(user_jid)), quoteattr(str(id)), str(sub_all), str(sub_cmt), str(sub_new)) # insert the posts for post in latest: try: entry = open(post+".txt") title = entry.readline().strip() body = entry.read() svg = body[body.find('")+6] if svg: svg = resize(svg,0.02). \ replace('; float:right">', '; float: left; margin-right: 0.5em">') checked = '' if post in subs: checked = ' checked="on"' print ("" + "" + "") % \ (post, post, checked, post, svg, post, title) except: pass # footer print """
Press this button to receive a test XHTML-IM message from intertwingly@gmail.com.  You may need to add this id as a ‘buddy’ first.

Nav Bar

""" % (open(config.directory.data + "navbar.html").read())