~azzar1/unity/add-show-desktop-key

« back to all changes in this revision

Viewing changes to ivle/interpret.py

  • Committer: William Grant
  • Date: 2009-12-08 03:50:24 UTC
  • mfrom: (1294.2.143 ui-the-third)
  • Revision ID: grantw@unimelb.edu.au-20091208035024-wjx8zp54gth15ph8
Merge ui-the-third. This is another UI revamp.

The header is now thin! Thin! The yellow bar is gone. The tabs are gone.
Breadcrumbs are here. Routes is replaced (with an object publishing
mechanism). Views are less repetitive. etc.

Show diffs side-by-side

added added

removed removed

Lines of Context:
21
21
 
22
22
# Runs a student script in a safe execution environment.
23
23
 
 
24
import ivle
24
25
from ivle import studpath
25
 
from ivle.util import IVLEError, IVLEJailError
26
 
import ivle.conf
 
26
from ivle.util import IVLEError, IVLEJailError, split_path
27
27
 
28
28
import functools
29
29
 
88
88
        self.linebuf = ""
89
89
        self.headers = {}       # Header names : values
90
90
 
91
 
def execute_cgi(interpreter, trampoline, uid, jail_dir, working_dir,
92
 
                script_path, req, gentle):
 
91
def execute_cgi(interpreter, uid, jail_dir, working_dir, script_path,
 
92
                req, gentle):
93
93
    """
94
94
    trampoline: Full path on the local system to the CGI wrapper program
95
95
        being executed.
105
105
    its environment.
106
106
    """
107
107
 
 
108
    trampoline = os.path.join(req.config['paths']['lib'], 'trampoline')
 
109
 
108
110
    # Support no-op trampoline runs.
109
111
    if interpreter is None:
110
112
        interpreter = '/bin/true'
134
136
        del os.environ[k]
135
137
    for (k,v) in req.get_cgi_environ().items():
136
138
        os.environ[k] = v
137
 
    fixup_environ(req)
 
139
    fixup_environ(req, script_path)
138
140
 
139
141
    # usage: tramp uid jail_dir working_dir script_path
140
142
    pid = subprocess.Popen(
141
 
        [trampoline, str(uid), jail_dir, working_dir, interpreter,
142
 
        script_path],
 
143
        [trampoline, str(uid), req.config['paths']['jails']['mounts'],
 
144
         req.config['paths']['jails']['src'],
 
145
         req.config['paths']['jails']['template'],
 
146
         jail_dir, working_dir, interpreter, script_path],
143
147
        stdin=f, stdout=subprocess.PIPE, stderr=subprocess.STDOUT,
144
148
        cwd=tramp_dir)
145
149
 
341
345
    <pre>
342
346
""" % (warning, text))
343
347
 
344
 
location_cgi_python = os.path.join(ivle.conf.lib_path, "trampoline")
345
 
 
346
348
# Mapping of interpreter names (as given in conf/app/server.py) to
347
349
# interpreter functions.
348
350
 
349
351
interpreter_objects = {
350
352
    'cgi-python'
351
 
        : functools.partial(execute_cgi, "/usr/bin/python",
352
 
            location_cgi_python),
 
353
        : functools.partial(execute_cgi, "/usr/bin/python"),
353
354
    'noop'
354
 
        : functools.partial(execute_cgi, None,
355
 
            location_cgi_python),
 
355
        : functools.partial(execute_cgi, None),
356
356
    # Should also have:
357
357
    # cgi-generic
358
358
    # python-server-page
359
359
}
360
360
 
361
 
def fixup_environ(req):
 
361
def fixup_environ(req, script_path):
362
362
    """Assuming os.environ has been written with the CGI variables from
363
363
    apache, make a few changes for security and correctness.
364
364
 
384
384
        del env['PATH']
385
385
    except: pass
386
386
 
387
 
    # Remove SCRIPT_FILENAME. Not part of CGI spec (see SCRIPT_NAME).
388
 
 
389
 
    # PATH_INFO is wrong because the script doesn't physically exist.
390
 
    # Apache makes it relative to the "serve" app. It should actually be made
391
 
    # relative to the student's script. intepretservice does that in the jail,
392
 
    # so here we just clear it.
393
 
    env['PATH_INFO'] = ''
394
 
    env['PATH_TRANSLATED'] = ''
395
 
 
396
387
    # CGI specifies that REMOTE_HOST SHOULD be set, and MAY just be set to
397
388
    # REMOTE_ADDR. Since Apache does not appear to set this, set it to
398
389
    # REMOTE_ADDR.
399
390
    if 'REMOTE_HOST' not in env and 'REMOTE_ADDR' in env:
400
391
        env['REMOTE_HOST'] = env['REMOTE_ADDR']
401
392
 
 
393
    env['PATH_INFO'] = ''
 
394
    del env['PATH_TRANSLATED']
 
395
 
 
396
    normuri = os.path.normpath(req.uri)
 
397
    env['SCRIPT_NAME'] = normuri
 
398
 
402
399
    # SCRIPT_NAME is the path to the script WITHOUT PATH_INFO.
403
 
    script_name = req.uri
404
 
    env['SCRIPT_NAME'] = script_name
 
400
    # We don't care about these if the script is null (ie. noop).
 
401
    # XXX: We check for /home because we don't want to interfere with
 
402
    # CGIRequest, which fileservice still uses.
 
403
    if script_path and script_path.startswith('/home'):
 
404
        normscript = os.path.normpath(script_path)
 
405
 
 
406
        uri_into_jail = studpath.to_home_path(os.path.normpath(req.path))
 
407
 
 
408
        # PATH_INFO is wrong because the script doesn't physically exist.
 
409
        env['PATH_INFO'] = uri_into_jail[len(normscript):]
 
410
        if len(env['PATH_INFO']) > 0:
 
411
            env['SCRIPT_NAME'] = normuri[:-len(env['PATH_INFO'])]
405
412
 
406
413
    # SERVER_SOFTWARE is actually not Apache but IVLE, since we are
407
414
    # custom-making the CGI request.
408
 
    env['SERVER_SOFTWARE'] = "IVLE/" + str(ivle.conf.ivle_version)
 
415
    env['SERVER_SOFTWARE'] = "IVLE/" + ivle.__version__
409
416
 
410
417
    # Additional environment variables
411
 
    username = studpath.url_to_jailpaths(req.path)[0]
 
418
    username = split_path(req.path)[0]
412
419
    env['HOME'] = os.path.join('/home', username)
 
420
 
 
421
class ExecutionError(Exception):
 
422
    pass
 
423
 
 
424
def execute_raw(config, user, jail_dir, working_dir, binary, args):
 
425
    '''Execute a binary in a user's jail, returning the raw output.
 
426
 
 
427
    The binary is executed in the given working directory with the given
 
428
    args. A tuple of (stdout, stderr) is returned.
 
429
    '''
 
430
 
 
431
    tramp = os.path.join(config['paths']['lib'], 'trampoline')
 
432
    tramp_dir = os.path.split(tramp)[0]
 
433
 
 
434
    # Fire up trampoline. Vroom, vroom.
 
435
    proc = subprocess.Popen(
 
436
        [tramp, str(user.unixid), config['paths']['jails']['mounts'],
 
437
         config['paths']['jails']['src'],
 
438
         config['paths']['jails']['template'],
 
439
         jail_dir, working_dir, binary] + args,
 
440
        stdin=subprocess.PIPE, stdout=subprocess.PIPE,
 
441
        stderr=subprocess.PIPE, cwd=tramp_dir, close_fds=True)
 
442
 
 
443
    (stdout, stderr) = proc.communicate()
 
444
    exitcode = proc.returncode
 
445
 
 
446
    if exitcode != 0:
 
447
        raise ExecutionError('subprocess ended with code %d, stderr %s' %
 
448
                             (exitcode, proc.stderr.read()))
 
449
    return (stdout, stderr)