/sw/foafcite.cgi
#!/usr/bin/env python
"""
FOAFCite CGI - Get summary information on people
Author: Sean B. Palmer, inamidst.com
License: GPL 2; share and enjoy!
"""
import sys, re, cgi, urllib
import cgitb; cgitb.enable()
form = cgi.FieldStorage()
def call(s):
try: return form[s].value
except KeyError: return None
form.__call__ = call
mkquery = 'select %s where %s%s%s'
r_word = re.compile(r'[A-Za-z0-9]+')
r_line = re.compile(r'^[a-z]+: ')
class Grab(urllib.URLopener):
def __init__(self, *args):
self.version = 'Mozilla/5.0 (foafcite)'
urllib.URLopener.__init__(self, *args)
def http_error_default(self, url, fp, errcode, errmsg, headers):
return urllib.addinfourl(fp, [headers, errcode], "http:" + url)
urllib._urlopener = Grab()
using = ('using foaf for <http://xmlns.com/foaf/0.1/>, ' +
'rdfs for <http://www.w3.org/2000/01/rdf-schema#>')
using = ''
julie = 'http://crschmidt.net/rdfpython/redlandbot.py?machine=1&cmd=%5Eq+'
def mknamebel(name):
name = ''.join(r_word.findall(name))
if not name: return 'Person'
if name[0] in '0123456789':
name = 'n' + name
return name
def term(t):
if t.startswith('_'):
return t[2:]
elif t.startswith('<'):
return t[1:-1].decode('utf-8')
else: return t[1:-1].decode('unicode-escape')
def parse(s):
# Depends on crschmidt's format being regular
results = []
for bindings in s.split('\n\n'):
results.append({})
for line in bindings.splitlines():
if r_line.match(line):
var, t = line.split(': ', 1)
results[-1][var] = term(t)
return filter(lambda b: len(b), results)
def query(q):
u = urllib.urlopen(julie + urllib.quote(q))
s = u.read()
u.close()
return parse(s)
def serve(status, body):
sys.stdout.write("Status: %s\r\n" % status)
sys.stdout.write("Content-Type: text/html; charset=utf-8\r\n\r\n")
sys.stdout.write(body)
if not body.endswith('\n'):
sys.stdout.write('\n')
sys.exit()
def barf(msg):
serve(200, "Error: " + msg)
def homepage():
serve(200, """
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>FOAFCite: Lookup People's Details Fast!</title>
<link rel="stylesheet" type="text/css" href="/trove/misc.css" />
<style type="text/css">
h1 { font-family: Tahoma, sans-serif; }
form {
margin: 1em 1.5em;
padding: 0.75em;
border: 1px dashed #bba;
}
input[type="submit"] { background-color: #f8f7f0; }
</style>
</head>
<body>
<div class="body">
<h1>FOAFCite Query</h1>
<form action="./foafcite" method="GET">
<div>
Name: <input type="text" name="name" size="20" />
Nick: <input type="text" name="nick" size="20" />
</div>
<div><span style="font-variant:small-caps;">Details:</span>
{ mbox_sha1sum: <input type="checkbox" name="sha1sum" value="1"
checked="checked" /> }
{ homepage: <input type="checkbox" name="homepage"
value="1" checked="checked" /> }
{ foaffile: <input type="checkbox"
name="foaffile" value="1" checked="checked" /> }
</div>
<div>
RDF/XML: <input type="radio" name="format" value="rdfxml" checked="checked" />
Notation3: <input type="radio" name="format" value="n3" />
</div>
<div><br /><input type="submit" /></div>
</form>
<p>Ever wanted to add a person to your FOAF file but didn't want to have to go
through the rigmorale of looking up their foaf:mbox_sha1sum, foaf:homepage, and
the location of their possibly numerous FOAF files? Rigmorale no more! This
service queries <a href="http://crschmidt.net/">Christopher Schmidt</a>'s
excellent <a href="http://crschmidt.net/semweb/redlandbot/">redlandbot</a>
service. Want to know how this works? Check out the foafcite <a
href="/inside/foafcite">source code</a>.</p>
<p>Tip: if the results returned are inaccurate, try using <em>both</em> a name
and a nickname for greater accuracy. Both name and nickname are case
sensitive.</p>
</div>
<address>
<a href="http://inamidst.com/sbp/">Sean B. Palmer</a>
</address>
</body>
</html>
""")
def main():
name, nick = form('name'), form('nick')
if not (name or nick):
homepage()
# barf("You must include either a name or a nickname!")
ident = ''
if name: ident += '(?p foaf:name "%s") ' % name
if nick: ident += '(?p foaf:nick "%s") ' % nick
namebel = mknamebel(name or nick)
format = form('format')
if format not in ('rdfxml', 'n3'):
barf("Format must be one of: rdfxml, n3.")
print 'Content-Type: text/plain; charset=utf-8'
print
if format == 'rdfxml':
print '<rdf:RDF xmlns:foaf="http://xmlns.com/foaf/0.1/" '
print ' xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" '
print ' xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#">'
print '<foaf:Person rdf:nodeID="%s">' % namebel
else:
print '@prefix foaf: <http://xmlns.com/foaf/0.1/> .'
print '@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .'
print
print ('_:%s' % namebel),
if name:
if format == 'rdfxml':
print ' <foaf:name>%s</foaf:name>' % name
else: print 'foaf:name "%s"; ' % name
if nick: # @@ elif nick?
if format == 'rdfxml':
print ' <foaf:nick>%s</foaf:nick>' % nick
else: print ' foaf:nick "%s"; ' % nick
if form('sha1sum'):
q = mkquery % ('?sha', ident, '(?p foaf:mbox_sha1sum ?sha) ', using)
for result in query(q):
sha = result['sha']
if format == 'rdfxml':
print ' <foaf:mbox_sha1sum>%s</foaf:mbox_sha1sum>' % sha
else: print ' foaf:mbox_sha1sum "%s"; ' % sha
if form('homepage'):
q = mkquery % ('?home', ident, '(?p foaf:homepage ?home) ', using)
for result in query(q):
home = result['home']
if format == 'rdfxml':
print ' <foaf:homepage rdf:resource="%s"/>' % home
else: print ' foaf:homepage <%s>; ' % home
if form('foaffile'):
foafy = 'and ?foaf =~ /foaf/ '
q1 = mkquery % ('?foaf', ident, '(?p foaf:made ?foaf) '+foafy, using)
q2 = mkquery % ('?foaf', ident, '(?foaf foaf:maker ?p) '+foafy, using)
q3 = mkquery % ('?foaf', ident, '(?p rdfs:seeAlso ?foaf) '+foafy, using)
q1r = query(q1)
if q1r:
for result in q1r:
foaf = result['foaf']
if format == 'rdfxml':
print ' <rdfs:seeAlso rdf:resource="%s"/>' % foaf
else: print ' rdfs:seeAlso <%s>; ' % foaf
else:
q2r = query(q2)
if q2r:
for result in q2r:
foaf = result['foaf']
if format == 'rdfxml':
print ' <rdfs:seeAlso rdf:resource="%s"/>' % foaf
else: print ' rdfs:seeAlso <%s>; ' % foaf
else:
q3r = query(q3)
for result in q3r:
foaf = result['foaf']
if format == 'rdfxml':
print ' <rdfs:seeAlso rdf:resource="%s"/>' % foaf
else: print ' rdfs:seeAlso <%s>; ' % foaf
if format == 'rdfxml':
print '</foaf:Person>'
print '</rdf:RDF>'
else: print '.'
if __name__=="__main__":
main()