#!/usr/bin/python
xmlfile = "/www/moviesaturday/movies.xml"
people_xmlfile = "/www/moviesaturday/people.xml"
mailing_xmlfile = "/www/moviesaturday/mailing_list.xml"
cgiurl = "/moviesaturday/index.cgi"
main_template = "main.htmpl"
navbar_template = "navbar.htmpl"
default_content = "news"
content_files = ["news", "about", "people"]
expansion_strings = {"cgi": cgiurl}
import cgi, xml.dom.minidom, re, sys, os
## Enable web error reporting
import cgitb; cgitb.enable()
CGI = cgi.FieldStorage()
## Start the web page
print "Content-type: text/html\n\n";
## A buncha helper functions
def isel(node): return node.nodeType == xml.dom.minidom.Element.ELEMENT_NODE
def isel_named(name): return lambda node: isel(node) and node.localName == name
def children_named(node, name): return filter(isel_named(name), node.childNodes)
def reverse(list): rev = list; rev.reverse(); return rev
def sort(list): s = list; s.sort(); return s
def indent(string, prefix):
newstr = ""
for line in string.split("\n"):
if len(line) > 0:
newstr += prefix + line + "\n"
else:
newstr += "\n"
return newstr
def normal_name(name):
name = name.strip()
name = re.sub(r"\s*'[^']+'", "", name)
return name
def expand(key, sub_hash, fn_hash = {}):
if sub_hash.has_key(key):
return sub_hash[key]
else:
if fn_hash.has_key(key):
str = fn_hash[key]()
else:
#print "Could not expand template key \"%s\"" % key
str = ""
sub_hash[key] = str
return str
def do_expansions(string, sub_hash, fn_hash = {}):
keys = re.findall(r'%([^\s%]+)%', string)
for key in keys:
string = string.replace("%"+key+"%", expand(key, sub_hash, fn_hash))
return string
def parse(string, sub_hash, fn_hash = {}):
lines = []
for line in string.split("\n"):
lines.append(do_expansions(line, sub_hash, fn_hash))
return "\n".join(lines)
def credits(data):
string = ""
in_cast = True
for credit in children_named(data, "credit"):
if in_cast and not credit.getAttribute("job") == "Cast":
in_cast = False
string += "
| |
\n"
string += "\n"
job = ""
if credit.hasAttribute("detail"):
job = credit.getAttribute("detail")
elif credit.hasAttribute("character"):
job = credit.getAttribute("character")
else:
job = credit.getAttribute("job")
names = credit.getAttribute("name").split(",")
name_urls = []
for name in names:
name_urls.append("%s" % (cgiurl + "?c=people&n=" + normal_name(name), normal_name(name)))
string += " | " + job + " | \n"
string += " " + ", ".join(name_urls) + " | \n"
string += "
\n"
return string
## Read XML data
doc = xml.dom.minidom.parse(xmlfile)
root = children_named(doc, "moviesaturday")[0]
d = {}
for season in children_named(root, "season"):
sid = season.getAttribute("id")
d[sid] = {}
for movie in children_named(season, "movie"):
mid = "%02d" % int(movie.getAttribute("id"))
d[sid][mid] = {}
d[sid][mid]["xml"] = movie
d[sid][mid]["title"] = movie.getAttribute("title")
d[sid][mid]["date"] = movie.getAttribute("date")
for data in filter(isel, movie.childNodes):
if data.localName == "credits":
d[sid][mid]["credits"] = credits(data)
elif data.localName == "synopsis":
d[sid][mid]["synopsis"] = data.getAttribute("text")
elif data.localName == "video":
d[sid][mid]["video_url"] = data.getAttribute("url")
d[sid][mid]["run_time"] = data.getAttribute("time")
d[sid][mid]["video_size"] = data.getAttribute("size")
elif data.localName == "image":
d[sid][mid]["image"] = data.getAttribute("url")
elif data.localName == "forum":
d[sid][mid]["forum_url"] = data.getAttribute("url")
elif data.localName == "script":
d[sid][mid]["script_url"] = data.getAttribute("url")
elif data.localName == "photos":
d[sid][mid]["photos_url"] = data.getAttribute("url")
elif data.localName == "embed":
d[sid][mid]["embed"] = data.childNodes[0].toxml()
## Return movie list
def movie_list():
string = "\n"
for season in reverse(sort(d.keys())):
string += " \n" % season
string += "
\n"
for movie in reverse(sort(d[season].keys())):
string += "
%s: %s\n" % (cgiurl, season, movie, movie, d[season][movie]["title"])
string += "
\n"
string += "
\n"
return string
def navbar():
file = open(navbar_template, "r")
return parse(file.read(), expansion_strings, expansion_functions)
def content_overview():
template = open("overview_item.htmpl", "r").read()
string = "\n"
for season in reverse(sort(d.keys())):
for movie in reverse(sort(d[season].keys())):
tmp_hash = d[season][movie]
tmp_hash["season"] = season
tmp_hash["movie"] = movie
tmp_hash.update(expansion_strings)
string += parse(template, tmp_hash)
string += "
\n"
return string
def content_movie():
s = 1
m = 1
if CGI.has_key("s"):
s = CGI["s"].value
if CGI.has_key("m"):
m = "%02d" % int(CGI["m"].value)
template = open("movie_info.htmpl", "r").read()
tmp_hash = d[s][m]
tmp_hash["season"] = s
tmp_hash["movie"] = m
tmp_hash.update(expansion_strings)
return parse(template, tmp_hash)
def content_person():
name = CGI["n"].value
doc = xml.dom.minidom.parse(people_xmlfile)
root = children_named(doc, "moviesaturday")[0]
p = filter(lambda x: x.getAttribute("name") == name, children_named(root, "person"))
if len(p) < 1:
return "Nobody named %s. Naughty.
" % name
person = p[0]
template = open("person_info.htmpl", "r").read()
tmp_hash = {}
tmp_hash["image_url"] = person.getAttribute("image")
tmp_hash["statement"] = person.getAttribute("statement")
tmp_hash["name"] = name
info = ""
if person.hasAttribute("email"):
info += "| E-Mail | %s |
\n" % (person.getAttribute("email"), person.getAttribute("email"))
if person.hasAttribute("website"):
info += "| Website | %s |
\n" % (person.getAttribute("website"), person.getAttribute("website"))
movie_involvement = ""
# jobs = ["Cast", "Crew", "Director", "Writer", "Composer", "Wrangler"]
for s in reverse(sort(d.keys())):
for m in reverse(sort(d[s].keys())):
people = []
credits_xml = children_named(d[s][m]["xml"], "credits")[0]
jobs_xml = filter(lambda x: re.search(name, x.getAttribute("name")), children_named(credits_xml, "credit"))
if len(jobs_xml) > 0:
movie_involvement += "| %s [%s.%s] | " % (cgiurl, s, m, d[s][m]["title"], s, m)
for j in jobs_xml:
job = j.getAttribute("job")
if job == "Crew":
job = j.getAttribute("detail")
if job == "Cast":
job = "Cast: %s" % j.getAttribute("character")
if job == "Wrangler":
job = "%s Wrangler" % j.getAttribute("item").title()
if j.getAttribute("name") != name:
job = "%s (co)" % job
movie_involvement += "%s " % job
movie_involvement += " |
\n"
tmp_hash["info"] = info
tmp_hash["movie_involvement"] = movie_involvement
tmp_hash.update(expansion_strings)
return parse(template, tmp_hash)
def content_people():
string = "The People of Movie Saturday
\n"
if CGI.has_key("n"):
return content_person()
class person:
movies_in = 0
pdata = {}
doc = xml.dom.minidom.parse(people_xmlfile)
root = children_named(doc, "moviesaturday")[0]
for p_xml in children_named(root, "person"):
name = p_xml.getAttribute("name")
pdata[name] = person()
pdata[name].xml = p_xml
pdata[name].jobs = {}
jobs = ["Cast", "Crew", "Director", "Writer", "Composer", "Wrangler"]
for s in d:
for m in d[s]:
people = []
credits_xml = children_named(d[s][m]["xml"], "credits")[0]
for c in children_named(credits_xml, "credit"):
names = c.getAttribute("name")
for name in names.split(","):
name = normal_name(name)
job = c.getAttribute("job")
if not job in jobs:
jobs.append(job)
if pdata.has_key(name):
if pdata[name].jobs.has_key(job):
pdata[name].jobs[job] += 1
else:
pdata[name].jobs[job] = 1;
if not name in people:
people.append(name)
else:
#print "Name not in people.xml: \"" + name + "\"
"
pass
for p in people:
pdata[p].movies_in += 1
p_keys = pdata.keys()
p_keys.sort(lambda a, b: cmp(pdata[b].movies_in, pdata[a].movies_in))
string += "\n"
string += " \n"
for p in p_keys:
string += " | %s | %s | " % (cgiurl + "?c=people&n=" + p, p, `pdata[p].movies_in`)
for j in jobs:
jnum = ""
if pdata[p].jobs.has_key(j):
jnum = pdata[p].jobs[j]
else:
jnum = " "
string += "%s | " % jnum
string += "
\n"
string += "
"
return string
def content_file(name):
if not (name in content_files):
return "Naughty."
file = name + ".html"
try:
file = open(file, "r")
return file.read()
except IOError, (errno, strerror):
return "[Error while opening file %s: %s]" % (file, strerror);
except:
return "[Unhandlable error while opening file %s]";
def content_mail_list():
email = (CGI["email"].value).strip()
if not re.match("^[^@ ]+@\S+$", email):
return "\"%s\" looks kinda funny to me." % email
new_movie_notify = CGI.has_key("new_movie_notify")
next_movie_notify = CGI.has_key("next_movie_notify")
doc = xml.dom.minidom.parse(mailing_xmlfile)
root = children_named(doc, "mailing_list")[0]
contacts = filter(lambda a: a.getAttribute("email") == email, children_named(root, "contact"))
if len(contacts) > 0:
c_xml = contacts[0]
else:
c_xml = root.appendChild(doc.createElement("contact"))
c_xml.setAttribute("email", email)
if new_movie_notify:
c_xml.setAttribute("new_notify", "true")
if next_movie_notify:
c_xml.setAttribute("next_notify", "true")
fh = file(mailing_xmlfile, "w")
for line in doc.toprettyxml(" ").split("\n"):
if re.match("^\s*\S", line):
fh.write(line + "\n")
fh.close()
return "The mailing list has been updated. To be removed from the list, send a request to moviesaturday@luke.no-ip.org"
def content():
## CGI stuffs
cont = ""
if CGI.has_key("c"):
cont = CGI["c"].value
else:
cont = default_content
if cont == "overview":
return content_overview()
elif cont == "movie":
return content_movie()
elif cont == "people":
return content_people()
elif cont == "mail_list":
return content_mail_list()
else:
return content_file(cont)
expansion_functions = {"navbar": navbar, "content": content, "movie_list": movie_list}
def full_page():
file = open(main_template, "r")
return parse(file.read(), expansion_strings, expansion_functions)
print full_page()