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

« back to all changes in this revision

Viewing changes to lib/common/interpret.py

  • Committer: mattgiuca
  • Date: 2008-02-18 00:32:43 UTC
  • Revision ID: svn-v3-trunk0:2b9c9e99-6f39-0410-b283-7f802c844ae2:trunk:487
setup.py: Added code to convert usrmgt_port into an int before writing to conf
    (and checking). Same as db_port.
userservice: Now uses config'd values for usrmgt settings instead of
    hard-coded.

Show diffs side-by-side

added added

removed removed

Lines of Context:
28
28
# This can be resolved but needs careful sanitisation. See fixup_environ.
29
29
 
30
30
from common import studpath
31
 
from common import db
32
 
from common.util import IVLEError
33
31
import conf
34
32
import functools
35
33
 
44
42
 
45
43
CGI_BLOCK_SIZE = 65535
46
44
 
47
 
uids = {}
48
 
 
49
 
def get_uid(login):
50
 
    """Get the unix uid corresponding to the given login name.
51
 
       If it is not in the dictionary of uids, then consult the
52
 
       database and retrieve an update of the user table."""
53
 
    global uids
54
 
    if login in uids:
55
 
        return uids[login]
56
 
 
57
 
    conn = db.DB()
58
 
    res = conn.get_all('login', ['login', 'unixid'])
59
 
    def repack(flds):
60
 
        return (flds['login'], flds['unixid'])
61
 
    uids = dict(map(repack,res))
62
 
 
63
 
    return uids[login]
64
 
 
65
 
def interpret_file(req, owner, jail_dir, filename, interpreter, gentle=True):
 
45
def interpret_file(req, owner, jail_dir, filename, interpreter):
66
46
    """Serves a file by interpreting it using one of IVLE's builtin
67
47
    interpreters. All interpreters are intended to run in the user's jail. The
68
48
    jail location is provided as an argument to the interpreter but it is up
74
54
    filename: Absolute filename within the user's jail.
75
55
    interpreter: A function object to call.
76
56
    """
77
 
    # We can't test here whether or not the target file actually exists,
78
 
    # because the apache user may not have permission. Instead we have to
79
 
    # rely on the interpreter generating an error.
 
57
    # Make sure the file exists (otherwise some interpreters may not actually
 
58
    # complain).
 
59
    # Don't test for execute permission, that will only be required for
 
60
    # certain interpreters.
80
61
    if filename.startswith(os.sep):
81
62
        filename_abs = filename
82
63
        filename_rel = filename[1:]
84
65
        filename_abs = os.path.join(os.sep, filename)
85
66
        filename_rel = filename
86
67
 
 
68
    if not os.access(os.path.join(jail_dir, filename_rel), os.R_OK):
 
69
        req.throw_error(req.HTTP_NOT_FOUND)
 
70
 
87
71
    # Get the UID of the owner of the file
88
72
    # (Note: files are executed by their owners, not the logged in user.
89
73
    # This ensures users are responsible for their own programs and also
90
74
    # allows them to be executed by the public).
91
 
    uid = get_uid(owner)
 
75
    uid = req.get_session()['unixid']
92
76
 
93
77
    # Split up req.path again, this time with respect to the jail
94
78
    (working_dir, _) = os.path.split(filename_abs)
99
83
    # (Note that paths "relative" to the jail actually begin with a '/' as
100
84
    # they are absolute in the jailspace)
101
85
 
102
 
    return interpreter(uid, jail_dir, working_dir, filename_abs, req,
103
 
                       gentle)
 
86
    return interpreter(uid, jail_dir, working_dir, filename_abs, req)
104
87
 
105
88
class CGIFlags:
106
 
    """Stores flags regarding the state of reading CGI output.
107
 
       If this is to be gentle, detection of invalid headers will result in an
108
 
       HTML warning."""
109
 
    def __init__(self, begentle=True):
110
 
        self.gentle = begentle
 
89
    """Stores flags regarding the state of reading CGI output."""
 
90
    def __init__(self):
111
91
        self.started_cgi_body = False
112
92
        self.got_cgi_headers = False
113
93
        self.wrote_html_warning = False
115
95
        self.headers = {}       # Header names : values
116
96
 
117
97
def execute_cgi(interpreter, trampoline, uid, jail_dir, working_dir,
118
 
                script_path, req, gentle):
 
98
                script_path, req):
119
99
    """
120
100
    trampoline: Full path on the local system to the CGI wrapper program
121
101
        being executed.
170
150
    # process_cgi_line: Reads a single line of CGI output and processes it.
171
151
    # Prints to req, and also does fancy HTML warnings if Content-Type
172
152
    # omitted.
173
 
    cgiflags = CGIFlags(gentle)
 
153
    cgiflags = CGIFlags()
174
154
 
175
155
    # Read from the process's stdout into req
176
156
    data = pid.stdout.read(CGI_BLOCK_SIZE)
202
182
        # Break data into lines of CGI header data. 
203
183
        linebuf = cgiflags.linebuf + data
204
184
        # First see if we can split all header data
205
 
        # We need to get the double CRLF- or LF-terminated headers, whichever
206
 
        # is smaller, as either sequence may appear somewhere in the body.
207
 
        usplit = linebuf.split('\n\n', 1)
208
 
        wsplit = linebuf.split('\r\n\r\n', 1)
209
 
        split = len(usplit[0]) > len(wsplit[0]) and wsplit or usplit
 
185
        split = linebuf.split('\r\n\r\n', 1)
 
186
        if len(split) == 1:
 
187
            # Allow UNIX newlines instead
 
188
            split = linebuf.split('\n\n', 1)
210
189
        if len(split) == 1:
211
190
            # Haven't seen all headers yet. Buffer and come back later.
212
191
            cgiflags.linebuf = linebuf
232
211
            if len(split) == 1:
233
212
                split = headers.split('\n', 1)
234
213
 
235
 
        # Is this an internal IVLE error condition?
236
 
        if 'X-IVLE-Error-Code' in cgiflags.headers:
237
 
            raise IVLEError(int(cgiflags.headers['X-IVLE-Error-Code']),
238
 
                            cgiflags.headers['X-IVLE-Error-Message'])
239
 
 
240
214
        # Check to make sure the required headers were written
241
 
        if cgiflags.wrote_html_warning or not cgiflags.gentle:
 
215
        if cgiflags.wrote_html_warning:
242
216
            # We already reported an error, that's enough
243
217
            pass
244
218
        elif "Content-Type" in cgiflags.headers:
271
245
    try:
272
246
        name, value = line.split(':', 1)
273
247
    except ValueError:
274
 
        # If we are being gentle, we want to help the user understand what
275
 
        # went wrong. Otherwise, we bail out.
276
 
        if not cgiflags.gentle:
277
 
            raise
278
248
        # No colon. The user did not write valid headers.
279
249
        if len(cgiflags.headers) == 0:
280
250
            # First line was not a header line. We can assume this is not
306
276
        try:
307
277
            req.status = int(value.split(' ', 1)[0])
308
278
        except ValueError:
309
 
            if not cgiflags.gentle:
310
 
                # This isn't user code, so it should be good.
311
 
                # Get us out of here!
312
 
                raise
313
279
            message = """The "Status" CGI header was invalid. You need to
314
280
print a number followed by a message, such as "302 Found"."""
315
281
            write_html_warning(req, message)