First we process the inputs; see Section 7.19, “class Inputs: All the script's input”. We'll also open the database
file. The 'c' mode argument causes it to
be created if necessary; the 's' mode
suffix requests that operations against be synchronized
to the disk immediately. (If multiple copies of reader.cgi
are running, gdbm will take care of locking the file.)
# - - - m a i n
def main():
'''Main program.
[ if cgi.FieldStorage() requests cookie deletion ->
file DB_NAME := that file with no entry for the
user's cookie, and with all expired entries deleted
sys.stdout +:= (header to delete the cookie) +
(HTML header) + (blank line) + (deletion-successful page)
else if (the user has no cookie) or
(the user's cookie is not a key in file DB_NAME) ->
file DB_NAME := that file with a new entry whose key is a
random string and whose value is chapter 1 and an
expiration time as specified by cgi.FieldStorage(),
and with expired entries deleted
sys.stdout +:= (header to set that random string as
the cookie) + (HTML header) + (blank line) +
(page showing the chapter for that db entry)
else ->
file DB_NAME := that file with the entry for the
user's cookie, updated to the chapter number
specified by cgi.FieldStorage(), and with expired
entries deleted
sys.stdout +:= (HTML header) + (blank line) +
(page showing the chapter for that db entry) ]
'''
First we'll transform all the inputs into an instance of
the Inputs class, and open our database
file.
#-- 1 --
# [ inputs := an Inputs instance representing all form
# name-value pairs and relevant environmental variables
# sent to this script
inputs = Inputs()
For the database file name, see Section 7.6.13, “DB_NAME”; see also Section 7.21, “class UserDatabase”.
#-- 2 --
# [ if DB_NAME can be opened as a gdbm file ->
# db := a UserDatabase instance representing that file
# else ->
# file DB_NAME := a new, empty gdbm file
# db := a UserDatabase instance representing that file ]
db = UserDatabase()
If the user wants the cookie deleted, that's a special
case with a different output page; see Section 7.8, “deleteCase(): Delete the cookie”. Otherwise we generate the
usual page.
#-- 3 --
# [ if inputs.forget ->
# db := db with the entry for key inputs.userId deleted
# sys.stdout +:= (header to delete the cookie) +
# (HTML header) + (blank line) +
# (deletion-successful page)
# else if (inputs.userId is None) or (inputs.userId is not
# a key in db)->
# db := db with a new entry whose key is a random
# string and whose value is chapter 1 and an expiration time
# as specified by inputs
# sys.stdout +:= (header to set that random string as
# the cookie) + (HTML header) + (blank line) +
# (page showing the chapter for that db entry)
# else ->
# db := db with the entry for inputs.userId updated
# to the page number specified by inputs
# sys.stdout +:= (HTML header) + (blank line) +
# (page showing the chapter for that db entry) ]
if inputs.forget:
deleteCase(inputs, db)
else:
chapterCase(inputs, db)
Finally, to prevent the database from growing without
limit, we'll delete expired entries; see Section 7.26, “UserDatabase.cleanup()”.
#-- 4 --
# [ db := db with all expired entries deleted ]
db.cleanup()
db.close()