Example #1
0
def dumpExtensions():
    '''Writes the list of registered extensions to stderr.'''
    Utils.Error('List of registered extensions:', prefix='Info: ')
    for extensionName in _registered_extensions_.keys():
        (category, shortDesc, longDesc, author, copyright, date,
         isSimpleExtension,
         extensionClass) = _registered_extensions_[extensionName]
        p = extensionClass()
        Utils.Error(p.name(), prefix='- ')
Example #2
0
def NoValidFunction(req, res, e):
    # We save the result in a temporary directory as well as the exception
    # message. Then we remove the ValidatorIcon.
    tmp = tempfile.mktemp()
    os.mkdir(tmp)
    fn = 'novalid_' + os.path.basename(req.path)
    Utils.FileString(os.path.join(tmp, fn), res[1])
    Utils.Error('Saved in dir ' + tmp, prefix='See: ')
    Utils.FileString(os.path.join(tmp, 'message'), str(e))
    # Remove ValidatorIcon:
    res[1] = string.replace(res[1], WebWorkers.ValidatorIconText, '')
    # Adjust Content-length:
    res[0]['Content-length'] = str(len(res[1]))
Example #3
0
    def createSuccessMessage(self):
        examnr = self.examnr
        # evaluate the changes
        registrations = {}
        l = Utils.SortNumerAlpha(Data.people.keys())
        for k in l:
            p = Data.people[k]
            wasRegistered = (examnr < len(p.exams) and p.exams[examnr] != None
                             and p.exams[examnr].registration == 1)
            shouldBeRegistered = self.options.has_key('T' + k)
            if wasRegistered != shouldBeRegistered:
                registrations[k] = int(shouldBeRegistered)

        # put the changes into the database
        registered = []
        unregistered = []
        Data.Lock.acquire()
        timestamp = int(time.time())
        for k in Utils.SortNumerAlpha(registrations.keys()):
            v = registrations[k]
            line = AsciiData.LineTuple(
                (k, str(examnr), str(v), str(timestamp)))
            try:
                Data.examregdesc.AppendLine(line)
            except:
                Data.Lock.release()
                Utils.Error('[' + Utils.LocalTimeString() +
                            '] Failed to register person for exam:\n' + line)
                return '<emph>Error: The changes could not be saved.</emph>'
            p = Data.people[k]
            while len(p.exams) < examnr + 1:
                p.exams.append(None)
            if p.exams[examnr] == None:
                p.exams[examnr] = Data.Exam()
            p.exams[examnr].timestamp = timestamp
            p.exams[examnr].registration = v
            if Data.Exam.maxexamnumber < examnr + 1:
                Data.Exam.maxexamnumber = examnr + 1
            line = (Utils.CleanWeb(p.lname) + ', ' + Utils.CleanWeb(p.fname) +
                    ' (' + k + ')')
            if v == 1:
                registered.append(line)
            else:
                unregistered.append(line)
        Data.Lock.release()

        Utils.Error('[' + Utils.LocalTimeString() + '] Changed registrations '
                    'for exam ' + str(examnr),
                    prefix='BulkExamRegistration: ')
        s = '<h3>An-/Abmeldung von Klausur ' + str(examnr) + '</h3>\n'
        if len(registered) > 0:
            s += ('<div>Die folgenden Personen wurden zur Klausur angemeldet:'
                  '</div>\n'
                  '<ul>\n<li>' + str('</li>\n<li>').join(registered) +
                  '</li>\n</ul>\n')
        if len(unregistered) > 0:
            s += ('<div>Die folgenden Personen wurden von der Klausur '
                  ' abgemeldet:</div>\n'
                  '<ul>\n<li>' + str('</li>\n<li>').join(unregistered) +
                  '</li>\n</ul>\n')
        return s
Example #4
0
def PostProcessing():
    '''This routine is called by the server to bring configuration options
into a usable form. Some values are changed into other data types.'''
    try:
        l = map(string.strip, conf['Resolutions'].split(','))
        conf['Resolutions'] = map(int, l)
    except:
        Utils.Error('Value of "Resolutions" option must be a comma-separated' +
                    ' list of positive integers.')
        FailMiserably()
    try:
        conf['IdCheckRegExp'] = re.compile(conf['IdCheckRegExp'])
    except:
        Utils.Error('Regular expression in "IdCheckRegExp" cannot be '
                    'compiled.')
        etype, value, tb = sys.exc_info()
        lines = traceback.format_exception(etype, value, tb)
        Utils.Error(string.join(lines), prefix="")
        FailMiserably()
    if not (conf.has_key('GuestIdRegExp')):
        conf['GuestIdRegExp'] = '^$'  # matches only the empty string
    try:
        conf['GuestIdRegExp'] = re.compile(conf['GuestIdRegExp'])
    except:
        Utils.Error('Regular expression in "GuestIdRegExp" cannot be '
                    'compiled.')
        etype, value, tb = sys.exc_info()
        lines = traceback.format_exception(etype, value, tb)
        Utils.Error(string.join(lines), prefix="")
        FailMiserably()
    try:
        conf['GeneralMessages'] = Utils.StringFile(conf['GeneralMessageFile'])
    except:
        Utils.Error(
            'Cannot read general messages for results pages, assuming'
            ' no messages.',
            prefix="Warning:")
        conf['GeneralMessages'] = ''
        traceback.print_exc()
    for i in range(len(conf['AccessList'])):
        s = conf['AccessList'][i]
        try:
            pos = s.find('/')
            if pos < 0:
                Utils.Error('Range in AccessList must contain a slash:\n' + s)
                FailMiserably()
            # Handle a bug in Python 2.2:
            if s[pos + 1:] == '255.255.255.255':
                conf['AccessList'][i] = (socket.inet_aton(s[:pos]),
                                         '\xff\xff\xff\xff')
            else:
                conf['AccessList'][i] = (socket.inet_aton(s[:pos]),
                                         socket.inet_aton(s[pos + 1:]))
        except:
            traceback.print_exc()
            Utils.Error('Cannot parse IP range for AccessList: ' + s)
            FailMiserably()
    for i in range(len(conf['AdministrationAccessList'])):
        s = conf['AdministrationAccessList'][i]
        try:
            pos = s.find('/')
            if pos < 0:
                Utils.Error('Range in AdministrationAccessList must contain '
                            'a slash:\n' + s)
                FailMiserably()
            # Handle a bug in Python 2.2:
            if s[pos + 1:] == '255.255.255.255':
                conf['AdministrationAccessList'][i] = \
                      (socket.inet_aton(s[:pos]),'\xff\xff\xff\xff')
            else:
                conf['AdministrationAccessList'][i] = \
                      (socket.inet_aton(s[:pos]),socket.inet_aton(s[pos+1:]))
        except:
            traceback.print_exc()
            Utils.Error(
                'Cannot parse IP range for AdministrationAccessList: ' + s)
            FailMiserably()
    # Give a default for Header:
    if not (conf.has_key('Header')):
        conf['Header'] = ''
    # Give a default for Footer:
    if not (conf.has_key('Footer')):
        conf['Footer'] = ''
    # Give a default for MaxStringInputLength:
    if not (conf.has_key('MaxStringInputLength')):
        conf['MaxStringInputLength'] = 20
    # Give a default for InteractiveMode:
    if not (conf.has_key('InteractiveMode')):
        conf['InteractiveMode'] = 0
    # Give a default for RestrictToOwnGroup:
    if not (conf.has_key('RestrictToOwnGroup')):
        conf['RestrictToOwnGroup'] = 1
    # Give a default for MCScoreCorrectDefault:
    if not (conf.has_key('MCScoreCorrectDefault')):
        conf['MCScoreCorrectDefault'] = 1
    # Give a default for MCScoreWrongDefault:
    if not (conf.has_key('MCScoreWrongDefault')):
        conf['MCScoreWrongDefault'] = -1
    # Give a default for MCScoreExerciseLowerLimitDefault:
    if not (conf.has_key('MCScoreExerciseLowerLimitDefault')):
        conf['MCScoreExerciseLowerLimitDefault'] = 0
    # Give a default for the DocumentRoot:
    if not (conf.has_key('DocumentRoot')):
        conf['DocumentRoot'] = os.path.join(home, 'html')
    # Give a default for GroupInfoFile:
    if not (conf.has_key('GroupInfoFile')):
        conf['GroupInfoFile'] = os.path.join(home, 'data/groupinfo.txt')
    # Give a default for ExtraLaTeXHeader:
    if not (conf.has_key('ExtraLaTeXHeader')):
        conf['ExtraLaTeXHeader'] = ''
    # Preparse the PDFTemplate:
    conf['PDFTemplate'] = SimpleTemplate.ParseString(conf['PDFTemplate'])
    # Same for NoTable variant:
    if not conf.has_key('PDFTemplateNoTable'):
        conf['PDFTemplateNoTable'] = ''
    conf['PDFTemplateNoTable'] = SimpleTemplate.ParseString(
        conf['PDFTemplateNoTable'])
    # Now parse the GradingFunction if applicable:
    if conf.has_key('GradingFunction'):
        d = {}
        try:
            exec conf['GradingFunction'] + '\n' in d
            conf['GradingFunction'] = d['Grade']
        except:
            etype, value, tb = sys.exc_info()
            lines = traceback.format_exception(etype, value, tb)
            Utils.Error('Cannot parse GradingFunction.\n' + string.join(lines))
            conf['GradingFunction'] = None
    else:
        conf['GradingFunction'] = None
    if not (conf.has_key('GradingActive')):
        conf['GradingActive'] = 0
    # Now parse the ExamGradingFunction if applicable:
    if conf.has_key('ExamGradingFunction'):
        d = {}
        try:
            exec conf['ExamGradingFunction'] + '\n' in d
            conf['ExamGradingFunction'] = d['Grade']
        except:
            etype, value, tb = sys.exc_info()
            lines = traceback.format_exception(etype, value, tb)
            Utils.Error('Cannot parse ExamGradingFunction.\n' +
                        string.join(lines))
            conf['ExamGradingFunction'] = None
    else:
        conf['ExamGradingFunction'] = None
    if not (conf.has_key('ExamGradingActive')):
        conf['ExamGradingActive'] = 0
    if not (conf.has_key('DateTimeFormat')):
        conf['DateTimeFormat'] = '%c'
    # Also parse the EMailHeaderFunction:
    d = {}
    try:
        exec conf['EMailHeaderFunction'] + '\n' in d
        conf['EMailHeaderFunction'] = d['EMailHeaderFunction']
    except:
        etype, value, tb = sys.exc_info()
        lines = traceback.format_exception(etype, value, tb)
        Utils.Error('Cannot parse EMailHeaderFunction.\n' + string.join(lines))
        FailMiserably()
    # Compile regular expression for valid email addresses
    try:
        conf['reValidEmail'] = re.compile(conf['ValidEmailAddresses'], re.I)
    except:
        Utils.Error('Regular expression in "ValidEmailAddresses" cannot be '
                    'compiled.')
        etype, value, tb = sys.exc_info()
        lines = traceback.format_exception(etype, value, tb)
        Utils.Error(string.join(lines), prefix="")
        FailMiserably()
Example #5
0
def ReadConfig():
    global conf
    configfile = os.path.join(home, "Config.xml")
    parseconf = {
        'fourth': pyRXPU.recordLocation,
        'ReturnDefaultedAttributes': 0,
        'MergePCData': 1,
        'Validate': 1,
        'eoCB': OurDtdOpener
    }
    tree = XMLRewrite.Parse(config=parseconf, file=configfile)
    if not tree:
        Utils.Error("Cannot parse the Config.xml file!")
        FailMiserably()

    # Now run through the tree:
    # We know by the DTD that there is exactly one "Config" element.
    if tree[2] != None:  # there might be no subelements
        for node in tree[2]:
            if type(node) == types.TupleType:
                # We know by the DTD that there is only element content, but
                # strings in between are still reported by pyRXP.
                key = node[0].encode('ISO-8859-1', 'replace')
                if Parameters.has_key(key):
                    info = Parameters[key]
                    # special case 'ConfigData', create dictionary if not there
                    if key == 'ConfigData':
                        if not conf.has_key(key):
                            conf[key] = {}
                        cnf = conf[key]
                        key = node[1]['key'].encode('ISO-8859-1', 'replace')
                    else:
                        cnf = conf
                    if info[0] == 'STRING' or info[0] == 'INT' or \
                       info[0] == 'FLOAT' or info[0] == 'PATH':
                        # We know by the DTD that there is only #PCDATA content
                        # Usually this will come as one chunk because of
                        # "MergePCData=1" above. We strip whitespace at
                        # beginning and end:
                        cnf[key] = string.strip(string.join(node[2]))
                        if info[0] == 'STRING' or info[0] == 'PATH':
                            try:
                                cnf[key] = cnf[key].encode('ISO8859-1')
                            except:
                                Utils.Error(
                                    'Value "' + cnf[key] + '" of ' +
                                    'configuration field "' + key + '" at ' +
                                    Utils.StrPos(node[3]) +
                                    ' has no ISO8859-1' +
                                    ' encoding. We assume the empty string.',
                                    prefix='Warning: ')
                                cnf[key] = ""
                            if info[0] == 'PATH':
                                cnf[key] = os.path.join(home, cnf[key])
                        elif info[0] == 'INT':
                            try:
                                cnf[key] = int(cnf[key])
                            except:
                                Utils.Error('Value "' + cnf[key] + '" of ' +
                                            'configuration field "' + key +
                                            '" at ' + Utils.StrPos(node[3]) +
                                            ' is not an integer. We' +
                                            ' assume 0.',
                                            prefix='Warning: ')
                                cnf[key] = 0
                        elif info[0] == 'FLOAT':
                            try:
                                cnf[key] = float(cnf[key])
                            except:
                                Utils.Error('Value "' + cnf[key] + '" of ' +
                                            'configuration field "' + key +
                                            '" at ' + Utils.StrPos(node[3]) +
                                            ' is not a float. We' +
                                            ' assume 0.0 .',
                                            prefix='Warning: ')
                                cnf[key] = 0.0
                    elif info[0] == 'LIST' or info[0] == 'PATHLIST':
                        # We know by the DTD, that the children are just a list
                        # of elements with #PCDATA content:
                        cnf[key] = []
                        for subnode in node[2]:
                            if type(subnode) == types.TupleType:
                                s = string.strip(string.join(subnode[2]))
                                try:
                                    s = s.encode('ISO8859-1')
                                except:
                                    Utils.Error('Value "' + s + '" of ' +
                                                'configuration field "' + key +
                                                '" at ' +
                                                Utils.StrPos(node[3]) +
                                                ' has no ISO8859-1' +
                                                ' encoding. We ignore it.',
                                                prefix='Warning: ')
                                if info[0] == 'PATHLIST':
                                    s = os.path.join(home, s)
                                cnf[key].append(s)

                else:  # A configuration field that we do not know!
                    Utils.Error('Unknown configuration field "' + key +
                                '" at ' + Utils.StrPos(node[3]) +
                                ', ignoring.',
                                prefix='Warning: ')
    abort = 0
    for k in Parameters.keys():
        if Parameters[k][1] and not (conf.has_key(k)):
            Utils.Error('Essential configuration option not found: "' + k +
                        '".')
            abort = 1
    if abort:
        FailMiserably()
    # See whether we can find the VERSION file:
    try:
        f = file(os.path.join(home, "VERSION"))
        version = f.readline()
        f.close()
        conf["Version"] = string.strip(version)
    except:
        conf["Version"] = 'UNKNOWN'
        pass  # we silently ignore, if the VERSION file is not found
Example #6
0
def FailMiserably():
    Utils.Error("Aborting.", prefix="")
    sys.exit(1)
Example #7
0
#   (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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.

import os, sys

from fmTools import Utils

Utils.Error('Loading extensions...', prefix='Info: ')

import plugins

pluginsPath = os.path.join(plugins.__path__[0])
for pluginDir in os.listdir(pluginsPath):
    if pluginDir in ['CVS', '.svn', '.git']:
        continue  # skip the CVS and similae  directory
    if not os.path.isdir(os.path.join(pluginsPath, pluginDir)):
        continue  # skip non-directories
    # load modules in this directory
    module = None
    try:
        module = __import__(plugins.__name__ + '.' + pluginDir)
    except ImportError:
        Utils.Error('Importing plugin ' + pluginDir + '.' + name + ' failed')
Example #8
0
import os, sys, string, time, tempfile, traceback, locale, signal

import Config  # this automatically determines our home dir
# but does not read the configuration file

# try to get correct locale from environment
try:
    locale.setlocale(locale.LC_ALL, '')
except:
    pass

# Fetch the "Utils" and switch error reporting to log file:
from fmTools import Utils
Utils.ErrorLogFileName = os.path.join(Config.home, 'log/server.log')
Utils.currentError = Utils.ErrorToLogfile
Utils.Error(time.asctime(time.localtime()) + ' Starting server...', prefix='')

# Now we can read our configuration file with proper error reporting
# (note that this might fail miserably):

Config.ReadConfig()
Config.PostProcessing()  # some postprocessing of configuration data

# We perform a few sanity checks and give appropriate messages:
if not (os.path.isdir(Config.conf['DocumentRoot'])):
    Utils.Error('Cannot find DocumentRoot directory: ' +
                Config.conf['DocumentRoot'])
    Utils.Error('Aborting.', prefix='')
    sys.exit(0)
if not (os.path.isdir(os.path.join(Config.conf['DocumentRoot'], 'images'))):
    Utils.Error('DocumentRoot directory does not contain an "images" '
Example #9
0
Config.ReadConfig()
Config.PostProcessing()  # some postprocessing of configuration data

f = file("log/server.log", "r")
f.seek(0, 2)  # seek to end of file
p = f.tell()

# Now send the request:
try:
    u = urllib.urlopen('http://localhost:' + str(Config.conf['Port']) +
                       '/AdminWork?Action=PID')
    spid = u.read()
    u.close()
except:
    Utils.Error('Cannot contact server. No server running?')
    sys.exit(1)

pid = os.fork()
if pid == 0:
    time.sleep(0.5)  # Let the parent get hold of the log file
    os.kill(int(spid), signal.SIGUSR1)
    try:
        # generate a request such that server notices the signal
        u = urllib.urlopen('http://localhost:' + str(Config.conf['Port']) +
                           '/')
        u.close()
    except:
        pass
    print 'Sent server with PID ' + spid + ' a USR1 signal.'
    sys.exit(0)  # Terminate this child process
Example #10
0
import sys, os, time

# get paths right
homedir = os.path.abspath(sys.path[0])
okudir = os.path.join(homedir, '..')
os.environ["OKUSONHOME"] = okudir
sys.path = [os.path.join(okudir, 'server')] + sys.path

# read config
import Config
Config.ReadConfig()
Config.PostProcessing()

# read exercises and sheets
from fmTools import Utils, AsciiData
Utils.Error('Reading exercises and sheets...', prefix='Info: ')
import Exercises
for d in Config.conf['ExerciseDirectories']:
    Exercises.ReadExercisesDirectory(d)
for d in Config.conf['SheetDirectories']:
    Exercises.ReadSheetsDirectory(d)

# list of triples (number, name, sheet)
sheets = Exercises.SheetList()

# read data
import Data
Utils.Error('Reading personal data...', prefix='Info: ')
Data.peopledesc.LoadFile()
Utils.Error('Reading multiple choice data...', prefix='Info: ')
Data.mcresultsdesc.LoadFile()
Example #11
0
    def createSummary(self):
        examnr = self.examnr
        maxscore = self.maxscore
        scores = self.scores
        oldscores = self.oldscores

        # put the changes into the database
        table = []
        table.append([
            '', 'Matr.-Nr.', 'Name', 'Punkte',
            'Punkte in den einzelnen Aufgaben'
        ])
        unchanged = []
        unchanged.append([
            '', 'Matr.-Nr.', 'Name', 'Punkte (alt)', 'Punkte (aktuell)',
            'Punkte (Ihre Angabe)', 'Details (alt)', 'Details (aktuell)',
            'Details (Ihre Angabe)'
        ])
        counter = 0
        unchangedcount = 0
        Data.Lock.acquire()
        for k in Utils.SortNumerAlpha(scores.keys()):
            p = Data.people[k]
            while len(p.exams) < examnr + 1:
                p.exams.append(None)
            exam = p.exams[examnr]
            newOrChanged = False
            # we only have to save non-default values for not yet existing
            # entries or changed values for existing entries
            newtotalscore = scores[k][0]
            newdetails = scores[k][1]
            oldtotalscore = oldscores[k][0]
            olddetails = oldscores[k][1]
            # if ( exam == None ):       # only needed for the following print
            #     curtotalscore = -1
            #     curdetails = '<None>'
            # else:
            #     curtotalscore = exam.totalscore
            #     curdetails = exam.scores
            # print ( k + ': totalscore (old/cur/new): ' + str(oldtotalscore) +
            #             '/' + str(curtotalscore) + '/' + str(newtotalscore) +
            #             ' -- details (old/cur/new): "' + olddetails + '"/"' +
            #             curdetails + '"/"' + newdetails + '"' )
            if (exam == None):
                # do we have non-default values?
                if (newtotalscore != -1 or newdetails != ''):
                    exam = Data.Exam()
                    newOrChanged = True
            else:
                # has the user made changes?
                valuesChanged = ((newtotalscore != oldtotalscore)
                                 or (newdetails != olddetails))
                # are there changes with respect to the currently stored values
                # (because of changes by another user while the first user editted
                # the values)
                needsSaving = ((newtotalscore != exam.totalscore)
                               or (newdetails != exam.scores))
                # have there been changes behind our back
                changedBehindBack = ((oldtotalscore != exam.totalscore)
                                     or (olddetails != exam.scores))
                if (valuesChanged and needsSaving and changedBehindBack):
                    # the user has changed a value and additionally this value has
                    # been changed by another user while the first user editted
                    # the values; in this case we don't save our values
                    unchangedcount += 1
                    if newtotalscore == -1:
                        newtotalscorestr = '-'
                    else:
                        newtotalscorestr = locale.str(newtotalscore)
                    if oldtotalscore == -1:
                        oldtotalscorestr = '-'
                    else:
                        oldtotalscorestr = locale.str(oldtotalscore)
                    if exam.totalscore == -1:
                        curtotalscorestr = '-'
                    else:
                        curtotalscorestr = locale.str(exam.totalscore)
                    unchanged.append([
                        str(unchangedcount), k,
                        Utils.CleanWeb(p.lname) + ', ' +
                        Utils.CleanWeb(p.fname), oldtotalscorestr,
                        curtotalscorestr, newtotalscorestr, olddetails,
                        exam.scores, newdetails
                    ])
                elif (valuesChanged):
                    newOrChanged = True
                elif (exam.maxscore != maxscore
                      and (oldtotalscore != -1 or olddetails != '')):
                    newOrChanged = True
            if newOrChanged:
                exam.totalscore = newtotalscore
                exam.scores = newdetails
                exam.maxscore = maxscore
                line = AsciiData.LineTuple((k, str(examnr), str(newtotalscore),
                                            str(maxscore), newdetails))
                try:
                    Data.examdesc.AppendLine(line)
                except:
                    Data.Lock.release()
                    Utils.Error('[' + Utils.LocalTimeString() +
                                '] Failed to store exam result:\n' + line)
                    return '<em>Error: The results could not be saved.</em>'
                p.exams[examnr] = exam
                counter += 1
                if newtotalscore == -1:
                    newtotalscorestr = '-'
                else:
                    newtotalscorestr = locale.str(newtotalscore)
                table.append([
                    str(counter), k,
                    Utils.CleanWeb(p.lname) + ', ' + Utils.CleanWeb(p.fname),
                    newtotalscorestr, newdetails
                ])
        Data.Lock.release()

        Utils.Error('[' + Utils.LocalTimeString() + '] Changed results '
                    'for exam ' + str(examnr),
                    prefix=self.name() + ': ')
        s = '<h3>Ergebnisse von Klausur ' + str(examnr) + '</h3>\n'
        if len(unchanged) > 1:
            s += (
                '<p>Einige Werte wurden geändert, während Sie die Werte editiert '
                'haben. Daher wurden die folgenden Änderungen <strong>nicht</strong> '
                'gespeichert.')
            s += createHTMLTable(unchanged)
        s += '<p>Die folgenden Änderungen wurden gespeichert.</p>'
        s += createHTMLTable(table)
        return s