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

« back to all changes in this revision

Viewing changes to src/apps/server/__init__.py

  • Committer: mattgiuca
  • Date: 2007-12-19 06:01:34 UTC
  • Revision ID: svn-v3-trunk0:2b9c9e99-6f39-0410-b283-7f802c844ae2:trunk:85
common/studpath.py: Added url_to_jailpaths.
apps/server: Rewrote parts to now get the UserID and paths relative to jail,
    and pass those off to the interpreter. The interpreter is no longer
    python, but one relative to IVLE (our trampoline). (Currently a test one).
Added bin/tramptest trampoline, called by server temporarily. Just prints out
    its arguments.

Show diffs side-by-side

added added

removed removed

Lines of Context:
31
31
import functools
32
32
import mimetypes
33
33
import os
 
34
import pwd
34
35
import subprocess
35
36
 
36
37
def handle(req):
91
92
        else:
92
93
            serve_file_direct(req, filename, type)
93
94
 
 
95
def serve_file_direct(req, filename, type):
 
96
    """Serves a file by directly writing it out to the response.
 
97
 
 
98
    req: An IVLE request object.
 
99
    filename: Filename in the local file system.
 
100
    type: String. Mime type to serve the file with.
 
101
    """
 
102
    if not os.access(filename, os.R_OK):
 
103
        req.throw_error(req.HTTP_NOT_FOUND)
 
104
    req.content_type = type
 
105
    req.sendfile(filename)
 
106
 
94
107
def interpret_file(req, owner, filename, interpreter):
95
108
    """Serves a file by interpreting it using one of IVLE's builtin
96
 
    interpreters.
 
109
    interpreters. All interpreters are intended to run in the user's jail. The
 
110
    jail location is provided as an argument to the interpreter but it is up
 
111
    to the individual interpreters to create the jail.
97
112
 
98
113
    req: An IVLE request object.
99
114
    owner: Username of the user who owns the file being served.
106
121
    # certain interpreters.
107
122
    if not os.access(filename, os.R_OK):
108
123
        req.throw_error(req.HTTP_NOT_FOUND)
109
 
    return interpreter(filename, req)
110
 
 
111
 
def serve_file_direct(req, filename, type):
112
 
    """Serves a file by directly writing it out to the response.
113
 
 
114
 
    req: An IVLE request object.
115
 
    filename: Filename in the local file system.
116
 
    type: String. Mime type to serve the file with.
117
 
    """
118
 
    if not os.access(filename, os.R_OK):
119
 
        req.throw_error(req.HTTP_NOT_FOUND)
120
 
    req.content_type = type
121
 
    req.sendfile(filename)
 
124
 
 
125
    # Get the UID of the owner of the file
 
126
    # (Note: files are executed by their owners, not the logged in user.
 
127
    # This ensures users are responsible for their own programs and also
 
128
    # allows them to be executed by the public).
 
129
    try:
 
130
        (_,_,uid,_,_,_,_) = pwd.getpwnam(owner)
 
131
    except KeyError:
 
132
        # The user does not exist. This should have already failed the
 
133
        # previous test.
 
134
        req.throw_error(req.HTTP_INTERNAL_SERVER_ERROR)
 
135
 
 
136
    # Split up req.path again, this time with respect to the jail
 
137
    (_, jail_dir, path) = studpath.url_to_jailpaths(req.path)
 
138
    (working_dir, _) = os.path.split(path)
 
139
    # Now jail_dir is the jail directory relative to the jails root.
 
140
    # Note that the trampoline has jails root hard-coded for security.
 
141
    # path is the filename relative to the user's jail.
 
142
    # working_dir is the directory containing the file relative to the user's
 
143
    # jail.
 
144
 
 
145
    return interpreter(uid, jail_dir, working_dir, path, req)
122
146
 
123
147
# Used to store mutable data
124
148
class Dummy:
125
149
    pass
126
150
 
127
 
def execute_cgi(filename, studentprog, req):
 
151
def execute_cgi(trampoline, uid, jail_dir, working_dir, script_path, req):
128
152
    """
129
 
    filename: Full path on the local system to the CGI wrapper program
 
153
    trampoline: Full path on the local system to the CGI wrapper program
130
154
        being executed.
131
 
    studentprog: Full path on the local system to the CGI student program
132
 
        which will eventually be executed.
 
155
    uid: User ID of the owner of the file.
 
156
    jail_dir: Owner's jail directory relative to the jails root.
 
157
    working_dir: Directory containing the script file relative to owner's
 
158
        jail.
 
159
    script_path: CGI script relative to the owner's jail.
133
160
    req: IVLE request object.
134
161
 
135
162
    The called CGI wrapper application shall be called using popen and receive
138
165
    """
139
166
 
140
167
    # Get the student program's directory and execute it from that context.
141
 
    slashloc = studentprog.rfind(os.sep)
142
 
    if slashloc >= 0:
143
 
        progdir = studentprog[0:slashloc]
144
 
    else:
145
 
        progdir = "/"
 
168
    (tramp_dir, _) = os.path.split(trampoline)
146
169
 
147
170
    # TODO: Don't create a file if the body length is known to be 0
148
171
    # Write the HTTP body to a temporary file so it can be passed as a *real*
154
177
        f.flush()
155
178
        f.seek(0)       # Rewind, for reading
156
179
 
157
 
    pid = subprocess.Popen([filename, studentprog],
158
 
        stdin=f, stdout=subprocess.PIPE, cwd=progdir)
 
180
    # usage: tramp uid jail_dir working_dir script_path
 
181
    pid = subprocess.Popen(
 
182
        [trampoline, str(uid), jail_dir, working_dir, script_path],
 
183
        stdin=f, stdout=subprocess.PIPE, cwd=tramp_dir)
159
184
 
160
185
    # process_cgi_line: Reads a single line of CGI output and processes it.
161
186
    # Prints to req, and also does fancy HTML warnings if Content-Type
226
251
</body>
227
252
</html>""")
228
253
 
 
254
# TODO: Replace mytest with cgi trampoline handler script
 
255
location_cgi_python = os.path.join(conf.ivlepath, "bin/mytest")
 
256
 
229
257
# Mapping of interpreter names (as given in conf/app/server.py) to
230
258
# interpreter functions.
231
259
 
232
260
interpreter_objects = {
233
261
    'cgi-python'
234
 
        : functools.partial(execute_cgi, '/usr/bin/python'),
 
262
        : functools.partial(execute_cgi, location_cgi_python),
235
263
    # Should also have:
236
264
    # cgi-generic
237
265
    # python-server-page