You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
222 lines
6.9 KiB
222 lines
6.9 KiB
#!/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' : ( 'Secretary', 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)
|
|
|