# HG changeset patch # User paulo # Date 1405669635 25200 # Node ID 9d3a95d80defa811d64b151f068cfbd57c8e859b # Parent 6edb5112c80477c9898ea3c12d74a344f29ffa3c add laterlinks2 diff -r 6edb5112c804 -r 9d3a95d80def laterlinks2/laterlinks_app.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/laterlinks2/laterlinks_app.py Fri Jul 18 00:47:15 2014 -0700 @@ -0,0 +1,169 @@ +import datetime +import cgi +import urlparse +import csv +import traceback + +import html + + +DEBUG = True +STRTIME_FMT = "%Y-%m-%d %H:%M:%S" +MY_PIN = "qworpy" + + +class LLDialect(csv.Dialect): + delimiter = '\t' + quoting = csv.QUOTE_NONE + lineterminator = '\n' + + +LLDIALECT = LLDialect() +LLDB_FN = "lldb.tsv" +LLDB_UNREAD_FN = "lldb_unread.tsv" + + +class LLError(Exception): + pass + +class PinFailError(LLError): + def __str__(self): + return "PIN FAIL!" + +class MissingFieldsError(LLError): + def __str__(self): + return "MISSING FIELD(s)!" + + +def lldb_unread_load(): + return csv.reader(open(LLDB_UNREAD_FN), LLDIALECT) + + +def lldb_add(inp): + try: + title = inp["title"][0] + url = inp["url"][0] + except (KeyError, IndexError): + raise MissingFieldsError() + + dt_str = datetime.datetime.now().strftime(STRTIME_FMT) + with open(LLDB_FN, 'a') as lldb_f: + csv.writer(lldb_f, LLDIALECT).writerow([title, url, dt_str]) + with open(LLDB_UNREAD_FN, 'a') as lldb_f: + csv.writer(lldb_f, LLDIALECT).writerow([title, url, dt_str]) + + +def lldb_unread_delete(inp): + try: + delete = inp["delete"] + except KeyError: + raise MissingFieldsError() + + lldb_unread = [i for i in lldb_unread_load()] + lldb_unread_f = open(LLDB_UNREAD_FN, 'w') + + + try: + for i in delete: + for j in lldb_unread: + dt_str = j[2] + if i == dt_str: + lldb_unread.remove(j) + finally: + csv.writer(lldb_unread_f, LLDIALECT).writerows(lldb_unread) + lldb_unread_f.close() + + + +def parse_wsgi_input(environ): + return urlparse.parse_qs(environ["wsgi.input"].read()) + + +def get_pin(inp): + if "pin" not in inp: + raise PinFailError() + + pin = inp["pin"][0] + if pin != MY_PIN: + raise PinFailError() + + return pin + + +def main(environ): + pin = '' + is_post = (environ["REQUEST_METHOD"] == "POST") + inp = parse_wsgi_input(environ) + + if is_post: + pin = get_pin(inp) + if inp["submit"][0] == "Add": + lldb_add(inp) + elif inp["submit"][0] == "Delete": + lldb_unread_delete(inp) + + title = "later links..." + root = html.HTML("html") + + header = root.header + header.link(rel="stylesheet", type="text/css", href="index.css") + header.title(title) + + body = root.body + body.h1(title) + + + if (DEBUG): + debug = body.pre + for i in environ.items(): + debug += cgi.escape("%s = %s \n" % i) + + debug += cgi.escape("wsgi.input.read = %s" % inp) + + form = body.form(action="index.fcgi", method="post") + + table = form.table + hrow = table.tr + hrow.th("Link") + hrow.th("Created") + hrow.th.input(type="submit", name="submit", value="Delete") + + for i in lldb_unread_load(): + (title, url, dt_str) = (j.decode("utf-8") for j in i) + row = table.tr + row.td.a(title, href=url) + row.td(dt_str) + row.td.input(type="checkbox", name="delete", value=dt_str) + + p1 = form.p + p1.label("Title").input(type="text", name="title", size="64") + p1.br + p1.label("URL").input(type="text", name="url", size="64") + p1.br + p1.input(type="submit", name="submit", value="Add") + + p2 = form.p + p2.input(type="password", name="pin", value=pin) + + return unicode(root).encode("utf-8") + + +def app(environ, start_response): + response_code = "500 Internal Server Error" + response_type = "text/plain; charset=UTF-8" + + try: + response_body = main(environ) + response_type = "text/html; charset=UTF-8" + except LLError as e: + response_body = str(e) + except: + response_body = traceback.format_exc() + + response_headers = [ + ("Content-Type", response_type), + ("Content-Length", str(len(response_body))), + ] + start_response(response_code, response_headers) + + return [response_body] diff -r 6edb5112c804 -r 9d3a95d80def laterlinks2/test_server.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/laterlinks2/test_server.py Fri Jul 18 00:47:15 2014 -0700 @@ -0,0 +1,38 @@ +import os +import sys +import signal + +import cherrypy +from cherrypy import wsgiserver + +import laterlinks_app + + +def sighandler(signum, frame): + sys.stderr.write("Caught signal: %s \n" % signum) + server.stop() + + +class FileServerRoot: + def default(self, *args): + if len(args) == 0: + raise cherrypy.HTTPError(404) + + filepath = os.path.abspath(os.path.join(*args)) + return cherrypy.lib.static.serve_file(filepath) + + default.exposed = True + + +if __name__ == "__main__": + fileServerApp = cherrypy.Application(FileServerRoot()) + dispatcher = wsgiserver.WSGIPathInfoDispatcher({ + "/index.fcgi": laterlinks_app.app, + "": fileServerApp, + }) + server = wsgiserver.CherryPyWSGIServer(('0.0.0.0', 8000), dispatcher) + + signal.signal(signal.SIGINT, sighandler) + signal.signal(signal.SIGTERM, sighandler) + + server.start()