rev |
line source |
paulo@60
|
1 import datetime
|
paulo@60
|
2 import cgi
|
paulo@60
|
3 import urlparse
|
paulo@60
|
4 import csv
|
paulo@60
|
5 import traceback
|
paulo@60
|
6
|
paulo@60
|
7 import html
|
paulo@60
|
8
|
paulo@60
|
9
|
paulo@60
|
10 DEBUG = True
|
paulo@60
|
11 STRTIME_FMT = "%Y-%m-%d %H:%M:%S"
|
paulo@60
|
12 MY_PIN = "qworpy"
|
paulo@60
|
13
|
paulo@60
|
14
|
paulo@60
|
15 class LLDialect(csv.Dialect):
|
paulo@60
|
16 delimiter = '\t'
|
paulo@60
|
17 quoting = csv.QUOTE_NONE
|
paulo@60
|
18 lineterminator = '\n'
|
paulo@60
|
19
|
paulo@60
|
20
|
paulo@60
|
21 LLDIALECT = LLDialect()
|
paulo@60
|
22 LLDB_FN = "lldb.tsv"
|
paulo@60
|
23 LLDB_UNREAD_FN = "lldb_unread.tsv"
|
paulo@60
|
24
|
paulo@60
|
25
|
paulo@60
|
26 class LLError(Exception):
|
paulo@60
|
27 pass
|
paulo@60
|
28
|
paulo@60
|
29 class PinFailError(LLError):
|
paulo@60
|
30 def __str__(self):
|
paulo@60
|
31 return "PIN FAIL!"
|
paulo@60
|
32
|
paulo@60
|
33 class MissingFieldsError(LLError):
|
paulo@60
|
34 def __str__(self):
|
paulo@60
|
35 return "MISSING FIELD(s)!"
|
paulo@60
|
36
|
paulo@60
|
37
|
paulo@60
|
38 def lldb_unread_load():
|
paulo@60
|
39 return csv.reader(open(LLDB_UNREAD_FN), LLDIALECT)
|
paulo@60
|
40
|
paulo@60
|
41
|
paulo@60
|
42 def lldb_add(inp):
|
paulo@60
|
43 try:
|
paulo@60
|
44 title = inp["title"][0]
|
paulo@60
|
45 url = inp["url"][0]
|
paulo@60
|
46 except (KeyError, IndexError):
|
paulo@60
|
47 raise MissingFieldsError()
|
paulo@60
|
48
|
paulo@60
|
49 dt_str = datetime.datetime.now().strftime(STRTIME_FMT)
|
paulo@60
|
50 with open(LLDB_FN, 'a') as lldb_f:
|
paulo@60
|
51 csv.writer(lldb_f, LLDIALECT).writerow([title, url, dt_str])
|
paulo@60
|
52 with open(LLDB_UNREAD_FN, 'a') as lldb_f:
|
paulo@60
|
53 csv.writer(lldb_f, LLDIALECT).writerow([title, url, dt_str])
|
paulo@60
|
54
|
paulo@60
|
55
|
paulo@60
|
56 def lldb_unread_delete(inp):
|
paulo@60
|
57 try:
|
paulo@60
|
58 delete = inp["delete"]
|
paulo@60
|
59 except KeyError:
|
paulo@60
|
60 raise MissingFieldsError()
|
paulo@60
|
61
|
paulo@60
|
62 lldb_unread = [i for i in lldb_unread_load()]
|
paulo@60
|
63 lldb_unread_f = open(LLDB_UNREAD_FN, 'w')
|
paulo@60
|
64
|
paulo@60
|
65
|
paulo@60
|
66 try:
|
paulo@60
|
67 for i in delete:
|
paulo@60
|
68 for j in lldb_unread:
|
paulo@60
|
69 dt_str = j[2]
|
paulo@60
|
70 if i == dt_str:
|
paulo@60
|
71 lldb_unread.remove(j)
|
paulo@60
|
72 finally:
|
paulo@60
|
73 csv.writer(lldb_unread_f, LLDIALECT).writerows(lldb_unread)
|
paulo@60
|
74 lldb_unread_f.close()
|
paulo@60
|
75
|
paulo@60
|
76
|
paulo@60
|
77
|
paulo@60
|
78 def parse_wsgi_input(environ):
|
paulo@60
|
79 return urlparse.parse_qs(environ["wsgi.input"].read())
|
paulo@60
|
80
|
paulo@60
|
81
|
paulo@60
|
82 def get_pin(inp):
|
paulo@60
|
83 if "pin" not in inp:
|
paulo@60
|
84 raise PinFailError()
|
paulo@60
|
85
|
paulo@60
|
86 pin = inp["pin"][0]
|
paulo@60
|
87 if pin != MY_PIN:
|
paulo@60
|
88 raise PinFailError()
|
paulo@60
|
89
|
paulo@60
|
90 return pin
|
paulo@60
|
91
|
paulo@60
|
92
|
paulo@60
|
93 def main(environ):
|
paulo@60
|
94 pin = ''
|
paulo@60
|
95 is_post = (environ["REQUEST_METHOD"] == "POST")
|
paulo@60
|
96 inp = parse_wsgi_input(environ)
|
paulo@60
|
97
|
paulo@60
|
98 if is_post:
|
paulo@60
|
99 pin = get_pin(inp)
|
paulo@60
|
100 if inp["submit"][0] == "Add":
|
paulo@60
|
101 lldb_add(inp)
|
paulo@60
|
102 elif inp["submit"][0] == "Delete":
|
paulo@60
|
103 lldb_unread_delete(inp)
|
paulo@60
|
104
|
paulo@60
|
105 title = "later links..."
|
paulo@60
|
106 root = html.HTML("html")
|
paulo@60
|
107
|
paulo@60
|
108 header = root.header
|
paulo@60
|
109 header.link(rel="stylesheet", type="text/css", href="index.css")
|
paulo@60
|
110 header.title(title)
|
paulo@60
|
111
|
paulo@60
|
112 body = root.body
|
paulo@60
|
113 body.h1(title)
|
paulo@60
|
114
|
paulo@60
|
115
|
paulo@60
|
116 if (DEBUG):
|
paulo@60
|
117 debug = body.pre
|
paulo@60
|
118 for i in environ.items():
|
paulo@60
|
119 debug += cgi.escape("%s = %s \n" % i)
|
paulo@60
|
120
|
paulo@60
|
121 debug += cgi.escape("wsgi.input.read = %s" % inp)
|
paulo@60
|
122
|
paulo@60
|
123 form = body.form(action="index.fcgi", method="post")
|
paulo@60
|
124
|
paulo@60
|
125 table = form.table
|
paulo@60
|
126 hrow = table.tr
|
paulo@60
|
127 hrow.th("Link")
|
paulo@60
|
128 hrow.th("Created")
|
paulo@60
|
129 hrow.th.input(type="submit", name="submit", value="Delete")
|
paulo@60
|
130
|
paulo@60
|
131 for i in lldb_unread_load():
|
paulo@60
|
132 (title, url, dt_str) = (j.decode("utf-8") for j in i)
|
paulo@60
|
133 row = table.tr
|
paulo@60
|
134 row.td.a(title, href=url)
|
paulo@60
|
135 row.td(dt_str)
|
paulo@60
|
136 row.td.input(type="checkbox", name="delete", value=dt_str)
|
paulo@60
|
137
|
paulo@60
|
138 p1 = form.p
|
paulo@60
|
139 p1.label("Title").input(type="text", name="title", size="64")
|
paulo@60
|
140 p1.br
|
paulo@60
|
141 p1.label("URL").input(type="text", name="url", size="64")
|
paulo@60
|
142 p1.br
|
paulo@60
|
143 p1.input(type="submit", name="submit", value="Add")
|
paulo@60
|
144
|
paulo@60
|
145 p2 = form.p
|
paulo@60
|
146 p2.input(type="password", name="pin", value=pin)
|
paulo@60
|
147
|
paulo@60
|
148 return unicode(root).encode("utf-8")
|
paulo@60
|
149
|
paulo@60
|
150
|
paulo@60
|
151 def app(environ, start_response):
|
paulo@60
|
152 response_code = "500 Internal Server Error"
|
paulo@60
|
153 response_type = "text/plain; charset=UTF-8"
|
paulo@60
|
154
|
paulo@60
|
155 try:
|
paulo@60
|
156 response_body = main(environ)
|
paulo@67
|
157 response_code = "200 OK"
|
paulo@60
|
158 response_type = "text/html; charset=UTF-8"
|
paulo@60
|
159 except LLError as e:
|
paulo@60
|
160 response_body = str(e)
|
paulo@60
|
161 except:
|
paulo@60
|
162 response_body = traceback.format_exc()
|
paulo@60
|
163
|
paulo@60
|
164 response_headers = [
|
paulo@60
|
165 ("Content-Type", response_type),
|
paulo@60
|
166 ("Content-Length", str(len(response_body))),
|
paulo@60
|
167 ]
|
paulo@60
|
168 start_response(response_code, response_headers)
|
paulo@60
|
169
|
paulo@60
|
170 return [response_body]
|