#!/usr/bin/python # # TBPY by Mark Paschal # Trackback server CGI for the rest of your web site. # # See http://markpasc.org/code/tbpy/ for installing and configuring # instructions. # # # Copyright 2002 Mark Paschal # # Permission is hereby granted, free of charge, to any person obtaining a # copy of this software and associated documentation files (the "Software"), # to deal in the Software without restriction, including without limitation # the rights to use, copy, modify, merge, publish, distribute, sublicense, # and/or sell copies of the Software, and to permit persons to whom the # Software is furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER # DEALINGS IN THE SOFTWARE. # import cgi import sys import os from os.path import dirname, join from xml.dom.minidom import parse, Document from time import strftime def tbError(err): """Print the appropriate Trackback error response and exit.""" print """Content-type: text/xml 1 %s """ % err sys.exit(0) def getInnerText(node): """Get the text from inside a node.""" return ''.join([x.toxml() for x in node.childNodes]) try: resource = None # so what is it? if os.environ["REQUEST_URI"].startswith(os.environ["SCRIPT_NAME"]): if os.environ.has_key("PATH_INFO"): resource = os.environ["PATH_INFO"] else: tbError("You didn't say what resource you wanted to ping.") else: resource = os.environ["REQUEST_URI"] if resource.endswith("index.html"): resource = resource[:-10] # Load existing TrackBack content. resourceUri = "http://%s%s" % (os.environ["SERVER_NAME"], resource) tbUri = "http://%s%s%s" % (os.environ["SERVER_NAME"], os.environ["SCRIPT_NAME"], resource) dataFilename = "%s.xml" % resource[1:].replace(os.sep, "_").replace(".", "_") dataFile = join(dirname(os.environ["SCRIPT_FILENAME"]), "data", dataFilename) tb_data = None # so what is it? try: tb_data = parse(dataFile) except IOError: # Make a new document. tb_data = Document() rss = tb_data.createElement("rss") tb_data.appendChild(rss) rss.setAttribute("version", "0.91") channel = tb_data.createElement("channel") rss.appendChild(channel) chTitle = tb_data.createElement("title") chTitle.appendChild(tb_data.createTextNode("TrackBack for %s" % (resourceUri))) channel.appendChild(chTitle) chLink = tb_data.createElement("link") chLink.appendChild(tb_data.createTextNode(resourceUri)) channel.appendChild(chLink) chDesc = tb_data.createElement("description") chDesc.appendChild(tb_data.createTextNode("What some people have pung me with.")) channel.appendChild(chDesc) chLang = tb_data.createElement("language") chLang.appendChild(tb_data.createTextNode("en-us")) channel.appendChild(chLang) tb_channel = tb_data.documentElement.firstChild # Pinging or fetching? if "POST" == os.environ["REQUEST_METHOD"]: # Pinging. ping = cgi.FieldStorage() # Add this ping. pingItem = tb_data.createElement("item") if ping.has_key("title"): itemTitle = pingItem.appendChild(tb_data.createElement("title")) itemTitle.appendChild(tb_data.createTextNode(ping.getvalue("title"))) if ping.has_key("url"): itemLink = pingItem.appendChild(tb_data.createElement("link")) itemLink.appendChild(tb_data.createTextNode(ping.getvalue("url"))) if ping.has_key("excerpt"): excerpt = ping.getvalue("excerpt") if 255 < len(excerpt): excerpt = "%s..." % excerpt[:252] itemDesc = pingItem.appendChild(tb_data.createElement("description")) itemDesc.appendChild(tb_data.createTextNode(excerpt)) if ping.has_key("blog_name"): itemBN = pingItem.appendChild(tb_data.createElement("blogName")) itemBN.appendChild(tb_data.createTextNode(ping.getvalue("blog_name"))) itemDate = tb_data.createElementNS("http://purl.org/dc/elements/1.1/", "date") itemDate.appendChild(tb_data.createTextNode(strftime("%Y-%m-%dT%H:%MZ"))) pingItem.appendChild(itemDate) tb_channel.appendChild(pingItem) # Write it back out. xmlout = open(dataFile, "w") xmlout.write(tb_data.toxml()) xmlout.close() print """Content-type: text/xml 0 """ else: # Fetching. # RSS? req = cgi.FieldStorage() if req.has_key("__mode") and "rss" == req.getvalue("__mode"): # Yes, RSS. Good thing it's already built. respDoc = Document() respTag = respDoc.appendChild(respDoc.createElement("response")) respTag.appendChild(respDoc.createElement("error")).appendChild(respDoc.createTextNode("0")) respTag.appendChild(tb_data.documentElement) print "Content-type: text/xml" print print response.toxml() sys.exit(0) # No, includable HTML. template = None # so what is it? try: templateFile = open(join(dirname(os.environ["SCRIPT_FILENAME"]), "template.html"), "r") template = templateFile.readlines() templateFile.close() # Turn ("first", "middle", "middle", "middle", "last") into ("first", "middle\nmiddle\nmiddle", "last"). if 3 > len(template): raise IOError, "Not enough lines in template file" template[1:-1] = ["\n".join(template[1:-1])] except IOError: template = ["

Trackbacks (RSS)

", "
%(title)s
\n

%(description)s

\n

by %(blogName)s at %(date)s

", "
"] metadata = { 'dataUri':"http://%s%s/%s" % (os.environ["SERVER_NAME"], '/'.join(os.environ["SCRIPT_NAME"].split("/")[:-1] + ["data"]), dataFilename), 'title':getInnerText(tb_channel.getElementsByTagName("title")[0]), 'description':getInnerText(tb_channel.getElementsByTagName("description")[0]), 'resourceUri':resourceUri, 'tbUri':tbUri } print """Content-type: text/html """ % metadata # Here's a " for TextPad's broken syntax coloring. print template[0] % metadata tb_data.normalize() items = tb_data.getElementsByTagName("item") items.reverse() for item in items: data = {} for datum in ("title", "description", "link", "date", "blogName"): try: data[datum] = getInnerText(item.getElementsByTagName(datum)[0]) except IndexError, x: # No 0th element by that name. data[datum] = "" % (datum,) print template[1] % data print print template[2] % metadata except Exception, x: tbError("%s: %s" % (x.__class__.__name__, x))