paulo@60: import datetime paulo@60: import cgi paulo@60: import urlparse paulo@60: import csv paulo@60: import traceback paulo@60: paulo@60: import html paulo@60: paulo@78: import pinlib paulo@78: paulo@60: paulo@60: DEBUG = True paulo@60: STRTIME_FMT = "%Y-%m-%d %H:%M:%S" paulo@60: paulo@60: paulo@60: class LLDialect(csv.Dialect): paulo@60: delimiter = '\t' paulo@60: quoting = csv.QUOTE_NONE paulo@60: lineterminator = '\n' paulo@60: paulo@60: paulo@60: LLDIALECT = LLDialect() paulo@60: LLDB_FN = "lldb.tsv" paulo@60: LLDB_UNREAD_FN = "lldb_unread.tsv" paulo@60: paulo@60: paulo@60: class LLError(Exception): paulo@60: pass paulo@60: paulo@60: class PinFailError(LLError): paulo@60: def __str__(self): paulo@60: return "PIN FAIL!" paulo@60: paulo@60: class MissingFieldsError(LLError): paulo@60: def __str__(self): paulo@60: return "MISSING FIELD(s)!" paulo@60: paulo@60: paulo@60: def lldb_unread_load(): paulo@60: return csv.reader(open(LLDB_UNREAD_FN), LLDIALECT) paulo@60: paulo@60: paulo@60: def lldb_add(inp): paulo@60: try: paulo@60: title = inp["title"][0] paulo@60: url = inp["url"][0] paulo@60: except (KeyError, IndexError): paulo@60: raise MissingFieldsError() paulo@60: paulo@60: dt_str = datetime.datetime.now().strftime(STRTIME_FMT) paulo@60: with open(LLDB_FN, 'a') as lldb_f: paulo@60: csv.writer(lldb_f, LLDIALECT).writerow([title, url, dt_str]) paulo@60: with open(LLDB_UNREAD_FN, 'a') as lldb_f: paulo@60: csv.writer(lldb_f, LLDIALECT).writerow([title, url, dt_str]) paulo@60: paulo@60: paulo@60: def lldb_unread_delete(inp): paulo@60: try: paulo@60: delete = inp["delete"] paulo@60: except KeyError: paulo@60: raise MissingFieldsError() paulo@60: paulo@60: lldb_unread = [i for i in lldb_unread_load()] paulo@60: lldb_unread_f = open(LLDB_UNREAD_FN, 'w') paulo@60: paulo@60: paulo@60: try: paulo@60: for i in delete: paulo@60: for j in lldb_unread: paulo@60: dt_str = j[2] paulo@60: if i == dt_str: paulo@60: lldb_unread.remove(j) paulo@60: finally: paulo@60: csv.writer(lldb_unread_f, LLDIALECT).writerows(lldb_unread) paulo@60: lldb_unread_f.close() paulo@60: paulo@60: paulo@60: paulo@60: def parse_wsgi_input(environ): paulo@60: return urlparse.parse_qs(environ["wsgi.input"].read()) paulo@60: paulo@60: paulo@60: paulo@60: def main(environ): paulo@60: is_post = (environ["REQUEST_METHOD"] == "POST") paulo@78: cookies = pinlib.parse_cookies(environ) paulo@60: inp = parse_wsgi_input(environ) paulo@60: paulo@60: if is_post: paulo@78: try: paulo@82: pinlib.PinMan("llpin").check(cookies) paulo@78: except pinlib.PinFailError: paulo@78: raise PinFailError paulo@60: if inp["submit"][0] == "Add": paulo@60: lldb_add(inp) paulo@60: elif inp["submit"][0] == "Delete": paulo@60: lldb_unread_delete(inp) paulo@60: paulo@60: title = "later links..." paulo@60: root = html.HTML("html") paulo@60: paulo@60: header = root.header paulo@60: header.link(rel="stylesheet", type="text/css", href="index.css") paulo@60: header.title(title) paulo@60: paulo@60: body = root.body paulo@60: body.h1(title) paulo@60: paulo@60: paulo@60: if (DEBUG): paulo@60: debug = body.pre paulo@60: for i in environ.items(): paulo@60: debug += cgi.escape("%s = %s \n" % i) paulo@60: paulo@78: debug += cgi.escape("wsgi.input.read = %s \n" % inp) paulo@78: debug += cgi.escape("cookies = %s \n" % cookies) paulo@60: paulo@60: form = body.form(action="index.fcgi", method="post") paulo@60: paulo@60: table = form.table paulo@60: hrow = table.tr paulo@60: hrow.th("Link") paulo@60: hrow.th("Created") paulo@60: hrow.th.input(type="submit", name="submit", value="Delete") paulo@60: paulo@60: for i in lldb_unread_load(): paulo@60: (title, url, dt_str) = (j.decode("utf-8") for j in i) paulo@60: row = table.tr paulo@60: row.td.a(title, href=url) paulo@60: row.td(dt_str) paulo@60: row.td.input(type="checkbox", name="delete", value=dt_str) paulo@60: paulo@60: p1 = form.p paulo@60: p1.label("Title").input(type="text", name="title", size="64") paulo@60: p1.br paulo@60: p1.label("URL").input(type="text", name="url", size="64") paulo@60: p1.br paulo@60: p1.input(type="submit", name="submit", value="Add") paulo@60: paulo@60: return unicode(root).encode("utf-8") paulo@60: paulo@60: paulo@60: def app(environ, start_response): paulo@60: response_code = "500 Internal Server Error" paulo@60: response_type = "text/plain; charset=UTF-8" paulo@60: paulo@60: try: paulo@60: response_body = main(environ) paulo@78: response_code = "200 OK" paulo@60: response_type = "text/html; charset=UTF-8" paulo@60: except LLError as e: paulo@60: response_body = str(e) paulo@60: except: paulo@60: response_body = traceback.format_exc() paulo@60: paulo@60: response_headers = [ paulo@60: ("Content-Type", response_type), paulo@60: ("Content-Length", str(len(response_body))), paulo@60: ] paulo@60: start_response(response_code, response_headers) paulo@60: paulo@60: return [response_body]