#!/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 += "
Season %s
\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 += " " for j in jobs: string += "" % j.title() string += "\n" for p in p_keys: string += " " % (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 += "" % jnum string += "\n" string += "
Movies%s
%s%s%s
" 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()