comparison web/archive.cgi @ 0:5ba2123d2c20

Put this project under version control, finally. Scripts for rlgallery.org, using a PostgreSQL backend. The recorder system is in py/, CGI scripts are in web/.
author John "Elwin" Edwards <elwin@sdf.org>
date Wed, 25 Jul 2012 21:59:42 -0700
parents
children 8f49df4074d7
comparison
equal deleted inserted replaced
-1:000000000000 0:5ba2123d2c20
1 #!/usr/bin/python
2
3 import cgi
4 import os
5 import sys
6 import re
7 import time
8 import calendar
9 import rlgalldb as rlgall
10 import cgitb
11
12 cgitb.enable()
13
14 infop = """<p>Looking for ttyrec files? Don't like digging through Web directory listings, converting time zones in your head, or guessing how many files
15 the game was spread across? The Archivist can find them all for you.</p>
16 """
17
18 ttyrecbase = "/var/dgl/dgldir/ttyrec/"
19 recre = r"(\d{4,4})-(\d{2,2})-(\d{2,2})\.(\d{2,2}):(\d{2,2}):(\d{2,2})\.ttyrec"
20 recrec = re.compile(recre)
21
22 def name_in_time(filename, timerange):
23 "Checks whether filename is a ttyrec with time between Unix times \
24 timerange[0] and timerange[1]."
25 nmatch = recrec.match(filename)
26 if not nmatch:
27 return False
28 ntime = calendar.timegm([int(val) for val in nmatch.groups()])
29 if ntime > timerange[0] and ntime <= timerange[1]:
30 return True
31 else:
32 return False
33
34 def input_game(outf, selected=None):
35 "Prints the form components for selecting a game."
36 selstr = '<option label="{0}" value="{1}" selected="selected">{0}</option>\n'
37 unselstr = '<option label="{0}" value="{1}">{0}</option>\n'
38 outf.write('<div>Dungeon name: <select name="game">\n')
39 for game in rlgall.gamelist:
40 # This will cause trouble if someone puts games with identical names
41 # into rlgall.
42 if selected and selected == game.uname:
43 outf.write(selstr.format(game.name, game.uname))
44 else:
45 outf.write(unselstr.format(game.name, game.uname))
46 outf.write('</select></div>\n')
47 return
48
49 def input_name(outf, defaultval=None):
50 defstr = '<div>Adventurer\'s name: <input type="text" name="name" value="{0}"></div>\n'
51 if defaultval:
52 outf.write(defstr.format(defaultval))
53 else:
54 outf.write('<div>Adventurer\'s Name: <input type="text" name="name"></div>\n')
55 return
56
57 def input_time(outf, defaultval=None):
58 defstr = '<div>Time: <input type="text" name="time" value="{0}"></div>\n'
59 if defaultval:
60 outf.write(defstr.format(defaultval))
61 else:
62 outf.write('<div>Time: <input type="text" name="time"></div>\n')
63 return
64
65 def input_datetime(outf, dvals=[None, None, None, None, None, None]):
66 optstr = '<option value="{0}" label="{1}">{1}</option>\n'
67 soptstr = '<option value="{0}" label="{1}" selected="selected">{1}</option>\n'
68 tf = '<input type="text" size="2" maxlength="2" name="{0}" value="{1:02}">'
69 emptf = '<input type="text" size="2" maxlength="2" name="{0}">'
70 sstr = '<div>Date: <select name="year">\n'
71 # Default to today
72 now = time.gmtime()
73 for dindex in range(3):
74 if not dvals[dindex]:
75 dvals[dindex] = now[dindex]
76 for year in range(2010, now[0] + 1):
77 if year == dvals[0]:
78 sstr += soptstr.format(year, year)
79 else:
80 sstr += optstr.format(year, year)
81 sstr += '</select>\n'
82 outf.write(sstr)
83 sstr = '<select name="month">\n'
84 for month in range(1, 13):
85 if month == dvals[1]:
86 sstr += soptstr.format(month, calendar.month_name[month])
87 else:
88 sstr += optstr.format(month, calendar.month_name[month])
89 sstr += '</select>\n'
90 outf.write(sstr)
91 sstr = '<select name="day">\n'
92 for day in range(1, 32):
93 if day == dvals[2]:
94 sstr += soptstr.format(day, day)
95 else:
96 sstr += optstr.format(day, day)
97 sstr += '</select></div>\n'
98 outf.write(sstr)
99 sstr = '<div>Approximate time: '
100 if dvals[3] != None:
101 sstr += tf.format("hour", dvals[3])
102 else:
103 sstr += emptf.format("hour")
104 sstr += " : "
105 if dvals[4] != None:
106 sstr += tf.format("minute", dvals[4])
107 else:
108 sstr += emptf.format("minute")
109 sstr += " : "
110 if dvals[5] != None:
111 sstr += tf.format("second", dvals[5])
112 else:
113 sstr += emptf.format("second")
114 sstr += ' (optional)</div>\n'
115 outf.write(sstr)
116 return
117
118 def checkempty(cgidata):
119 exkeys = set(cgidata.keys())
120 wanted = set(["name", "game", "time", "year", "month", "day", "hour",
121 "minute", "second"])
122 return wanted.isdisjoint(exkeys)
123
124 def processname(fdata, errlist):
125 "Takes a CGI data object, extracts the player name, checks its validity, \
126 and returns it. If errors are encountered, they are appended to errlist."
127 cantfind = "I have no record of an adventurer called {0}."
128 if "name" not in fdata:
129 errlist.append("You didn\'t tell me the adventurer\'s name.")
130 return None
131 # Just in case someone supplies something nasty, make sure they can't go
132 # digging all over the filesystem.
133 formname = fdata.getfirst("name").rpartition("/")[2]
134 try:
135 os.stat(ttyrecbase + formname)
136 except OSError:
137 errlist.append(cantfind.format(cgi.escape(formname)))
138 return None
139 return formname
140
141 def processgame(fdata, errlist):
142 "Takes a CGI data object and returns the game from rlgall.gamelist that \
143 it asks for. Errors appended to errlist."
144 cantfind = "I've never heard of a dungeon called {0}."
145 if "game" not in fdata:
146 errlist.append('You didn\'t choose a dungeon.')
147 return None
148 formgame = fdata.getfirst("game")
149 for agame in rlgall.gamelist:
150 if agame.uname == formgame:
151 return agame
152 errlist.append(cantfind.format(cgi.escape(formgame)))
153 return None
154
155 def processtime(fdata, errlist, hlist):
156 "Takes a CGI data object and converts to a Unix timestamp by finding fields \
157 called year, month, etc. Any errors get appended to errlist. hlist \
158 should contain 6 components, for ymd-hms fields."
159
160 # Timestamp overrides human-readable, even if it's invalid.
161 badtime = 'The time field is for Unix clocks, which never say anything \
162 like {0}. Try the form instead.'
163 utime = None
164 formtime = fdata.getfirst("time")
165 if formtime:
166 try:
167 utime = int(formtime)
168 except ValueError:
169 errlist.append(badtime.format(cgi.escape(formtime)))
170 return None
171 else:
172 if utime < 0:
173 utime = 0
174 if utime != None:
175 chtime = time.gmtime(utime)
176 for i in range(6):
177 hlist[i] = chtime[i]
178 return utime
179
180 # Now try to get a human-readable specification.
181 lerrors = []
182 year = month = day = hour = minute = second = None
183 fyear = fdata.getfirst("year")
184 if not fyear:
185 lerrors.append("No year was provided.")