Wiki History ScriptsAt the bottom of this page are two Python scripts, history.cgi and diff.cgi. These are CGI scripts that pull data from the C2 wiki and generate a somewhat friendly history listing and version diff, respectively. To use them,
You can see a sample snapshot of history.cgi at http://andstuff.org/wiki/history.html?WardCunningham. The "Compare" button for the snapshot is hard-wired to a comparison of revisions 688 and 689, which shows some of the capabilities of the color-coded diff (borrowed from JotEngine and MoinMoin).
history.cgi
#!/usr/bin/python
# This script is public domain
import urllib
import os
import re
try :
page = os.environ['QUERY_STRING']
except :
page = ""
if page == "" :
print "Content-type: text/plain"
print
print "Please indicate a page name"
exit()
stream = urllib.urlopen('http://c2.com/wiki/history/' + page)
history = stream.read()
stream.close()
stream = urllib.urlopen('http://c2.com/cgi/quickDiff?' + page)
diff = stream.read()
stream.close()
versions = []
re.sub(r'(HREF="(\d+)">\d+</A> +([-0-9A-Za-z]+ [0-9:]+))', lambda match: versions.insert(0, [int(match.group(2)), match.group(3), "http://c2.com/wiki/history/" + page + '/' + match.group(2)]), history)
re.sub(r'(Revision (\d+) made ([0-9]+ [a-z]+ ago))', lambda match: versions.insert(0, [int(match.group(2)), match.group(3), "http://c2.com/cgi/wiki?" + page]), diff)
versions.sort()
versions.reverse()
print "Content-type: text/html"
print
print "<html><head><title>History of " + page + "</title></head>"
print "<body><h1>History of <a href=\"http://c2.com/cgi/wiki?" + page + "\">" + page + "</a></h1>"
print "<form action=\"http:diff.cgi\" method=\"get\">"
print "<input type='hidden' name='page' value='" + page + "' />"
print "<table>"
count = 0
for version in versions :
count = count + 1
if count == 1 : latestsel = "checked='checked' "
else : latestsel = ""
if count == 2 : lastsel = "checked='checked' "
else : lastsel = ""
print "<tr><td><input type='radio' name='v1' value='" + str(version[0]) + "' " + lastsel + "/></td>"
print " <td><input type='radio' name='v2' value='" + str(version[0]) + "' " + latestsel + "/></td>"
print " <td><a href=\"" + version[2] + "\">Revision " + str(version[0]) + "</a></td>"
print " <td>" + version[1] + "</td></tr>"
print "</table>"
print "<input type='submit' name='submit' value='Compare' />"
print "</form>"
print "</body></html>"
diff.cgi
#!/usr/bin/python
# This script is public domain.
import re
import cgi, cgitb; cgitb.enable()
import urllib
def getcur(page) :
stream = urllib.urlopen('http://c2.com/cgi/wiki?edit=' + page)
text = stream.read()
stream.close()
match = re.search(r'<TEXTAREA[^>]+>(.*)</TEXTAREA>', text, re.DOTALL)
if match is None : result = ""
else : result = match.group(1)
result = result.replace('<', '<')
result = result.replace('>', '>')
result = result.replace('"', '"')
result = result.replace('&', '&')
return result
def diff(s1, s2) :
from difflib import SequenceMatcher
s1 = s1.replace('&', '&')
s1 = s1.replace('<', '<')
s2 = s2.replace('&', '&')
s2 = s2.replace('<', '<')
seq1 = s1.splitlines()
seq2 = s2.splitlines()
seqobj = SequenceMatcher(None, seq1, seq2)
linematch = seqobj.get_matching_blocks()
if len(seq1) == len(seq2) and linematch[0] == (0, 0, len(seq1)) : # No differences.
return '<strong>No differences.</strong>'
lastmatch = (0, 0)
end = (len(seq1), len(seq2))
result = "<table class='diff'>\n"
for match in linematch : # Print all differences.
if lastmatch == match[0:2] : # Starts of pages identical.
lastmatch = (match[0] + match[2], match[1] + match[2])
continue
result = result + "<tr><td colspan='2' style='background-color: #c0c0c0; color: #000000;'><strong>" + "Line " + str(lastmatch[0] + 1) + ", removed:" + "</strong></td><td colspan='2' style='background-color: #c0c0c0; color: #000000;'><strong>" + "Line " + str(lastmatch[1] + 1) + ", added:" + "</strong></td></tr>\n"
leftpane = ""
rightpane = ""
linecount = max(match[0] - lastmatch[0], match[1] - lastmatch[1])
for line in range(linecount) :
if line < match[0] - lastmatch[0] :
if line > 0 :
leftpane += '\n'
leftpane += seq1[lastmatch[0] + line]
if line < match[1] - lastmatch[1] :
if line > 0 :
rightpane += '\n'
rightpane += seq2[lastmatch[1] + line]
charobj = SequenceMatcher(None, leftpane, rightpane)
charmatch = charobj.get_matching_blocks()
if leftpane == "" and rightpane == "" :
ratio = 1.0
else :
ratio = charobj.ratio()
if ratio < 0.5 : # Insufficient similarity.
if len(leftpane) != 0 :
leftresult = "<span style='color: #ff0000;'>" + leftpane + "</span>"
else :
leftresult = ""
if len(rightpane) != 0 :
rightresult = "<span style='color: #ff0000;'>" + rightpane + "</span>"
else :
rightresult = ""
else : # Some similarities; markup changes.
charlast = (0, 0)
charend = (len(leftpane), len(rightpane))
leftresult = ""
rightresult = ""
for thismatch in charmatch :
if thismatch[0] - charlast[0] != 0 :
leftresult = leftresult + "<span style='color: #ff0000;'>" + leftpane[charlast[0]:thismatch[0]] + "</span>"
if thismatch[1] - charlast[1] != 0 :
rightresult = rightresult + "<span style='color: #ff0000;'>" + rightpane[charlast[1]:thismatch[1]] + "</span>"
leftresult = leftresult + leftpane[thismatch[0]:thismatch[0] + thismatch[2]]
rightresult = rightresult + rightpane[thismatch[1]:thismatch[1] + thismatch[2]]
charlast = (thismatch[0] + thismatch[2], thismatch[1] + thismatch[2])
leftpane = leftresult.replace('\n', '<br />\n')
rightpane = rightresult.replace('\n', '<br />\n')
result = result + "<tr><td colspan='2' style='background-color: #cfffcf; color: #000000; width: 50%;'>" + leftpane + "</td><td colspan='2' style='background-color: #ffffaf; color: #000000; width: 50%;'>" + rightpane + "</td></tr>\n"
lastmatch = (match[0] + match[2], match[1] + match[2])
result = result + '</table>\n'
return result
form = cgi.FieldStorage()
page = form.getfirst('page', "")
v1 = form.getfirst('v1', "")
v2 = form.getfirst('v2', "")
stream = urllib.urlopen('http://c2.com/wiki/history/' + page + '/' + v1)
v1 = stream.read()
stream.close()
stream = urllib.urlopen('http://c2.com/wiki/history/' + page + '/' + v2)
v2 = stream.read()
stream.close()
if not re.search(r'<TITLE>404 Not Found</TITLE>', v1) is None : v1 = getcur(page)
if not re.search(r'<TITLE>404 Not Found</TITLE>', v2) is None : v2 = getcur(page)
print "Content-type: text/html"
print
print "<html><head><title>Differences for " + page + "</title></head>"
print "<body><h1>Differences for <a href=\"http://c2.com/cgi/wiki?" + page + "\">" + page + "</a></h1>"
print diff(v1, v2)
print "</body></html>"
EditText of this page
(last edited November 9, 2014)
or FindPage with title or text search