#!/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 += '
[' x += 'Add triple to this node] [RDFWiki]
' 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' 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

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

Delete A Triple - use with caution!




""" % (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()