old-website/scripts/xsltproc.py

223 lines
6.9 KiB
Python
Executable File

#!/usr/bin/python
import os, sys, urllib, libxml2, libxslt, ldap, time, datetime, re, pytz
#
# globals
#
cscUri = "http://csclub.uwaterloo.ca/xsltproc"
cscTerms = ["Winter", "Spring", "Fall"]
cscShortTerms = ['w', 's', 'f']
cscLdapUri = "ldap://ldap1.csclub.uwaterloo.ca ldap://ldap2.csclub.uwaterloo.ca"
cscLdap = None
cscPeopleBase = 'ou=People,dc=csclub,dc=uwaterloo,dc=ca'
cscPositions = {
# position name exec elected order
'president' : ( 'President', True, True, 1, ),
'vice-president' : ( 'Vice-president', True, True, 2, ),
'treasurer' : ( 'Treasurer', True, True, 3, ),
'secretary' : ( 'Assistant Vice-President',True, True, 4, ),
'sysadmin' : ( 'System Administrator', True, False, 5, ),
'cro' : ( 'Chief Returning Officer', False, False, 6, ),
'offsck' : ( 'Office Manager', False, False, 7, ),
'librarian' : ( 'Librarian', False, False, 8, ),
'imapd' : ( 'Imapd', False, False, 9, ),
'webmaster' : ( 'Web Master', False, False, 10, ),
}
cscYesNo = { True : 'yes', False : 'no' }
def xslArgToString(arg):
if type(arg) == type([]):
return libxml2.xmlNode(arg[0]).getContent()
else:
return arg
#
# cscLdapConnect
#
def cscLdapConnect():
global cscLdap
cscLdap = ldap.initialize(cscLdapUri)
cscLdap.simple_bind_s("", "")
#
# csc:encode-for-uri
#
def cscEncodeForUri(ctx, uri):
uri = xslArgToString(uri)
return urllib.quote(uri)
#
# csc:term
#
def cscTerm(ctx, date):
date = xslArgToString(date)
try:
[year, month, day] = date.split("-")
term = (int(month) - 1) / 4
return cscTerms[term] + " " + year
except:
print "Invalid date '%s'" % date
raise
#
# csc:member-list
#
def cscMemberList(ctx, _):
try:
if cscLdap == None:
cscLdapConnect()
curDate = time.strftime('%d-%m-%Y')
year = time.localtime().tm_year
term = cscShortTerms[int(time.localtime().tm_mon - 1) / 4]
members = cscLdap.search_s(cscPeopleBase, ldap.SCOPE_SUBTREE,
'(&(objectClass=member)(term=%s%d))' % (term, year))
doc = libxml2.newDoc("1.0")
root = doc.newChild(None, "root", None)
for (_, member) in members:
node = root.newChild(None, "member", None)
node.setProp("userid", member['uid'][0])
node.setProp("name", member['cn'][0])
if not 'program' in member:
member['program'] = ['']
node.setProp("program", member['program'][0])
return [root]
except Exception, e:
print e
raise
#
# csc:position-list
#
def cscPositionList(ctx, _):
try:
if cscLdap == None:
cscLdapConnect()
members = cscLdap.search_s(cscPeopleBase, ldap.SCOPE_SUBTREE,
'(&(objectClass=member)(position=*))')
doc = libxml2.newDoc("1.0")
root = doc.newChild(None, "root", None)
positions = {}
for (_, member) in members:
for position in member['position']:
if not position in positions:
positions[position] = []
positions[position].append(member)
for position in cscPositions.keys():
if not position in positions:
positions[position] = []
for (position, members) in positions.iteritems():
node = root.newChild(None, "position", None)
node.setProp("position", position)
if not position in cscPositions:
raise Exception("Position '%s' not known" % position)
position = cscPositions[position]
node.setProp("name", position[0])
node.setProp("exec", cscYesNo[position[1]])
node.setProp("elected", cscYesNo[position[2]])
node.setProp("order", str(position[3]))
for member in members:
child = node.newChild(None, "holder", None)
child.setProp("userid", member['uid'][0])
child.setProp("name", member['cn'][0])
return [root]
except Exception, e:
print e
raise
#
# csc:ical-datetime
#
def cscIcalDatetime(ctx, date, time, addmin = "0"):
date = xslArgToString(date)
time = xslArgToString(time)
addmin = int(xslArgToString(addmin))
r = re.search("(\d*)-(\d*)-(\d*)", date)
year, month, day = 0, 0, 0
if r != None:
year, month, day = (int(i) for i in r.groups())
r = re.search("(\d*):(\d*)\s*([apAP])", time)
hour, minute = (0, 0)
if r != None:
hour, minute = (int(i) for i in r.groups()[:2])
# 12-hour times
if r.group(3) in 'aA':
hour %= 12 #hour % 12
elif r.group(3) in 'pP':
hour %= 12
hour += 12
# 24-hour time
else:
hour %= 24
dt = datetime.datetime(year, month, day, hour, minute)
dt = pytz.timezone('Canada/Eastern').localize(dt)
dt += datetime.timedelta(0, 0, 0, 0, addmin)
return dt.astimezone(pytz.utc).strftime("%Y%m%dT%H%M%SZ")
#
# csc:ical-escape
#
def cscIcalEscape(ctx, str):
str = xslArgToString(str)
str = str.replace("\n", " ")
#str = str.replace(":", "")
#str = str.replace(";", "")
#str = str.replace(",", "")
str = re.sub("\s+", " ", str)
str = re.sub("^\s+", "", str)
str = re.sub("\s+$", "", str)
return str
#
# csc:email
#
def cscEmail(ctx, email):
email = xslArgToString(email)
return "_EMAIL_TODO_"
#
# main
#
# check argv
if len(sys.argv) < 4:
print "Usage: xsltproc.py input-file style-sheet output-file [params...]"
sys.exit(1)
inFile = sys.argv[1]
xsltFile = sys.argv[2]
outFile = sys.argv[3]
rawParams = sys.argv[4:]
# check params
params = {}
for p in rawParams:
try:
[key, val] = p.split("=")
params[key] = "'" + val + "'"
except:
print "Missing value for parameter '%s'" % p
sys.exit(1)
try:
# register extensions
libxslt.registerExtModuleFunction("encode-for-uri", cscUri, cscEncodeForUri)
libxslt.registerExtModuleFunction("term", cscUri, cscTerm)
libxslt.registerExtModuleFunction("member-list", cscUri, cscMemberList)
libxslt.registerExtModuleFunction("position-list", cscUri, cscPositionList)
libxslt.registerExtModuleFunction("ical-datetime", cscUri, cscIcalDatetime)
libxslt.registerExtModuleFunction("ical-escape", cscUri, cscIcalEscape)
libxslt.registerExtModuleFunction("email", cscUri, cscEmail)
# parse xml/xslt and apply style-sheet
style = libxslt.parseStylesheetFile(xsltFile)
if style == None: sys.exit(1)
doc = libxml2.parseFile(inFile)
res = style.applyStylesheet(doc, params)
ret = style.saveResultToFilename(outFile, res, 0)
except Exception, e:
print e
sys.exit(1)