#!/usr/local/bin/python
"""
RDF Wiki 1.1 - A Wiki for the Semantic Web
http://infomesh.net/2001/rdfwiki/
Copyright (C) 2001 Sean B. Palmer.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of
the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public
License along with this program; if not, write to the Free
Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
MA 02111-1307, USA.
--
Is it a Wiki? Is it a Semantic Web project? No! It's both.
New to this version:-
* Now lets you use URIs as subjects and objects
* Uses RDFS label for predicates, if present
* Minor formatting edits
You'll need Python 2.0 or higher. Many thanks to Seth Russell
for the inspiration, the augmenting, and the idea, and to TimBL
for thinking up ENQUIRE which is also similar to this deeley.
"""
import sys
import os
import cgi
import string
import re
import cPickle; pickle = cPickle
# Configurable Constants
Root = 'C:\\cgi-bin\\'
WikiBase = 'http://example.org/rdfwiki'
# Other Constants
StoreFile = Root+'rdfwiki.pkl'
WikiPrefix = WikiBase + '?'
S, P, O, C = 0, 1, 2, 3
V, T = 0, 1
URI = 'tag:infomesh.net,2001-08-07:URI'
LIT = 'tag:infomesh.net,2001-08-07:Literal'
ANON = 'tag:infomesh.net,2001-08-07:Anon'
WN = 'tag:infomesh.net,2001-08-07:WikiName'
RDFSNS = 'http://www.w3.org/2000/01/rdf-schema#'
DCNS = 'http://purl.org/dc/elements/1.1/'
# Some pickle functions
def pdump(data):
pickle.dump(data,open(StoreFile,'wb'),1)
def pload():
return pickle.load(open(StoreFile,'rb'))
# XHTML formatting/output functions
def printhtml(title, content):
"""Prints an XHTML page."""
print 'Content-type: text/html\n'
print '\n'
print '
\n'+title+''
print '\n\n\n'+content+'\n'
print '
About: '
print 'RDFWiki\n\n'
def printrawhtml(title, content):
"""Prints a raw XHTML page."""
print 'Content-type: text/html\n'
print '\n\n'+title+''
print '\n\n\n'+content+'\n\n'
# Get the thing going...
# def initialize(form):
# """Get your RDF Wiki going!"""
# if form['password'].value == Password:
# data = [[['RdfWiki',WN],['WrittenBy',WN],['Sean B. Palmer',LIT]]]
# init = Store(data=data)
# pdump(init)
# printhtml('Wiki Initialized','Your Wiki has been initialized!
')
# else: raise 'Incorrect password'
def go():
"""Get your RDF Wiki going! Securer version"""
data = [[['RdfWiki',WN],['WrittenBy',WN],['Sean B. Palmer',LIT]]]
data.append([['RdfWiki',WN],[DCNS+'date',URI],['2001-09-05',LIT]])
data.append([[DCNS+'date',URI],[RDFSNS+'label',URI],['date',LIT]])
data.append([['WrittenBy',WN],[RDFSNS+'comment',URI],['the author of a resource',LIT]])
data.append([[RDFSNS+'label',URI],[RDFSNS+'label',URI],['label',LIT]])
data.append([[RDFSNS+'comment',URI],[RDFSNS+'label',URI],['comment',LIT]])
try:
pload()
printrawhtml('RDF Wiki Error','This Wiki has already been initialized.
')
except:
init = Store(data=data)
pdump(init)
printrawhtml('Wiki Initialized','Your Wiki has been initialized!
')
# WikiFunctions: Wikifi some code, validate a WikiName, etc.
wnreg = r'(^|[^A-Za-z0-9\?=]+)(([A-Z][a-z]+){2,})[^A-Z0-9]*?'
wnregsearch = re.compile(wnreg).search
def wnlink(wn):
return '%s' % (wn, wn)
def wikifi(a):
r = ''
while 1:
m = wnregsearch(a)
if not m: break
s, e = m.start(2), m.end(2)
wn = a[s:e]
wn = wnlink(wn)
r, a = r + a[:s] + wn, a[e:]
return r + a
def testwn(w):
wntest = r'([A-Z][a-z]+){2,}'
iswikiname = re.compile(wntest).match
if iswikiname(w):
return [w,WN]
else:
raise '"'+w+'" is not a valid WikiName'
def testuri(s):
uritest = r'([A-Z][a-z])([^\s\"]+?):([^\s\"]+?)'
isuri = re.compile(uritest).match
if isuri(s):
return 1
else:
return 0
# The Store class, derived from the SWIPT "Doc" class
class Store:
"""This is a general RDF store."""
def __init__(self, data=[]):
self.data = data
def addnode(self, s):
"""This adds a triple (s) to the Store"""
do = 1 # This makes sure people don't add duplicate triples
for t in self.data:
if s == t: do = 0
if do: self.data.append(s)
def deletenode(self, s):
"""This deletes a triple (s) from the Store"""
try: self.data.remove(s)
except: raise 'Triple is not in the data store'
def returnnode(self, s):
"""Return a node of given WikiName s"""
x = ''+str(s)+'
\n'
label = ['http://www.w3.org/2000/01/rdf-schema#label',URI]
plabel = None
for triple in self.data:
if s == triple[S][V] and triple[P][T] == URI and triple[O][T] == WN:
for t in self.data:
if triple[P][T] == URI and triple[P] == t[S] and t[P] == label:
plabel = t[O]
if plabel: x += ''+plabel[V]+': '
else: x += '
'+triple[P][V]+': '
x += ''+triple[O][V]+'
'
elif s == triple[S][V] and triple[P][T] == URI and triple[O][T] == LIT:
for t in self.data:
if triple[P][T] == URI and triple[P] == t[S] and t[P] == label:
plabel = t[O]
if plabel: x += ''+plabel[V]+': '
else: x += '
'+triple[P][V]+': '
x += '"'+wikifi(triple[O][V])+'"
'
elif s == triple[S][V] and triple[P][T] == WN and triple[O][T] == WN:
x += ''+triple[P][V]+': '
x += ''+triple[O][V]+'
'
elif s == triple[S][V] and triple[P][T] == WN and triple[O][T] == LIT:
x += ''+triple[P][V]+': '
x += '"'+wikifi(triple[O][V])+'"
'
else: pass
x += '
'
return x
def recent(self, s):
"""Return the most recent additions to the store."""
pass
def listnodes(self):
"""List all of the nodes"""
x = 'Nodes:-
\n'
temp = ['RdfWiki']
for triple in self.data:
do = 1
for w in temp:
if triple[S][V] == w:
do = 0
if do and triple[S][T] == WN:
x += '- '+triple[S][V]+'
'
temp.append(triple[S][V])
x += '- RdfWiki
'
return x
def n3(self):
"""This outputs the store as Notation3 (and N-Triples)."""
n3 = ''
for triple in self.data:
for term in triple:
if term[T] == URI:
n3 += '<' + term[V] + '>'
elif term[T] == ANON:
n3 += '_:' + term[V]
elif term[T] == LIT:
n3 += '"' + term[V] + '"'
elif term[T] == WN:
n3 += '<' + WikiPrefix + term[V] + '>'
n3 += ' '
n3 += '.\n'
return n3
# Some output functions
def showstore():
"""Show the internal Python store, for debugging, etc."""
x = pload()
printrawhtml('RDF Wiki Internal Python Store',str(x.data))
def shown3():
"""Print the store as Notation3/N-Triples."""
x = pload(); x = x.n3()
print "Content-Type: text/plain\n"; print x
def printnode(node):
"""Return one single node (all triples with a certain subject)."""
node = testwn(node)
node = node[V]
x = pload()
x = x.returnnode(node)
printrawhtml('RDF Wiki', x)
def list():
x = pload(); x = x.listnodes()
printrawhtml('RDF Wiki', 'List Of Nodes in This RDF Wiki
'+x)
# Now for the form functions...
def printmain():
HomePage = 'RdfWiki'
"""Prints the main page."""
content = """RDF Wiki HomePage
Welcome to the RDF Wiki home page. You can:-
""" % (WikiBase, HomePage, HomePage, WikiBase, WikiBase, WikiBase)
printhtml('RDF Wiki', content)
def add(wn=''):
"""Adds a new triple - a very important function."""
content = """RDF Wiki: Add A Triple
""" % (WikiBase, wn)
printrawhtml('RDF Wiki', content)
def addtriple(form):
"""This takes a triple from the form input, and adds it."""
subject = form['subject'].value
arc = form['arc'].value
value = form['value'].value
prefix = form['prefix'].value
subtype = form['subtype'].value
arctype, valuetype = form['arctype'].value, form['valuetype'].value
# Subject can be a URI or WikiName
if subtype == 'URI': subject = [subject,URI]
elif subtype == 'WikiName': subject = testwn(subject)
else: raise 'Unrecognized ArcType!'
# Predicate can be a URI or WikiName
if arctype == 'URI':
if prefix == 'none': arc = [arc,URI]
else: arc = [prefix+arc,URI]
elif arctype == 'WikiName': arc = testwn(arc)
else: raise 'Unrecognized ArcType!'
# Object can be a URI, WikiName, or Literal
if valuetype == 'URI': value = [value,URI]
elif valuetype == 'WikiName': value = testwn(value)
elif valuetype == 'Literal':
value = string.replace(value,'"','"')
value = [value,LIT]
else: raise 'Unrecognized ArcType!'
x = pload(); x.addnode([subject,arc,value]); pdump(x)
content = '' % (WikiBase)
node = 'Node: '+subject[V]+''
printrawhtml('RDF Wiki Addition Success!', node+' added/updated'+content)
def delete(wn=''):
"""Deletes a triple."""
content = """RDF Wiki: Delete A Triple
""" % (WikiBase, wn)
printrawhtml('RDF Wiki', content)
def deletetriple(form):
subject, arc = form['subject'].value, form['arc'].value
value = form['value'].value
subtype = form['subtype'].value
arctype, valuetype = form['arctype'].value, form['valuetype'].value
if subtype == 'URI': subject = [subject,URI]
elif subtype == 'WikiName': subject = testwn(subject)
else: raise 'error'
if arctype == 'URI': arc = [arc,URI]
elif arctype == 'WikiName': arc = testwn(arc)
else: raise 'error'
if valuetype == 'URI': value = [value,URI]
elif valuetype == 'WikiName': value = testwn(value)
elif valuetype == 'Literal': value = [value,LIT]
else: raise 'error'
x = pload()
x.deletenode([subject,arc,value]); pdump(x)
content = '' % (WikiBase)
node = 'Node: '+subject[V]+''
printrawhtml('RDF Wiki Delete Success', node+' updated:deleted'+content)
def run():
if os.environ['REQUEST_METHOD'] == 'GET':
form, qs = cgi.FieldStorage(), str(os.environ['QUERY_STRING'])
if form.has_key('showstore'): showstore()
elif form.has_key('n3'): shown3()
elif form.has_key('add') and form.has_key('name'): add(form['name'].value)
elif form.has_key('add'): add()
elif form.has_key('delete'): delete()
elif form.has_key('list'): list()
elif form.has_key('go'): go()
elif qs: printnode(qs)
else: printmain()
elif os.environ['REQUEST_METHOD'] == 'POST':
form = cgi.FieldStorage()
if form.has_key('addtriple'): addtriple(form)
elif form.has_key('deletetriple'): deletetriple(form)
else: raise 'Can only add/delete triples using POST'
else: raise 'Unknown request method:'+os.environ['REQUEST_METHOD']
if __name__=='__main__':
try: run()
except: cgi.print_exception()