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

« back to all changes in this revision

Viewing changes to www/apps/fileservice/__init__.py

  • Committer: mattgiuca
  • Date: 2008-01-10 01:11:54 UTC
  • Revision ID: svn-v3-trunk0:2b9c9e99-6f39-0410-b283-7f802c844ae2:trunk:152
fileservice: Improved the action handler:
    * Added ActionError exception.
    * Handler catches such exceptions and relays them to response.
    * Added actionpath_to_local for resolving paths specified in actions
        to local paths.
    Added action "remove". (works)

Show diffs side-by-side

added added

removed removed

Lines of Context:
75
75
# directory seen when fileservice has no arguments or path). Paths without a
76
76
# slash are taken relative to the specified path.
77
77
 
78
 
# action=rm: Delete a file or directory (recursively).
79
 
#       path:   The path to the file or directory to delete.
 
78
# action=remove: Delete a file(s) or directory(s) (recursively).
 
79
#       path:   The path to the file or directory to delete. Can be specified
 
80
#               multiple times.
80
81
# TODO: More actions.
81
82
 
82
83
import os
98
99
# Mime types
99
100
# application/json is the "best" content type but is not good for
100
101
# debugging because Firefox just tries to download it
101
 
mime_dirlisting = "text/plain"
 
102
mime_dirlisting = "text/html"
102
103
#mime_dirlisting = "application/json"
103
104
 
 
105
class ActionError(Exception):
 
106
    """Represents an error processing an action. This can be
 
107
    raised by any of the action functions, and will be caught
 
108
    by the top-level handler, put into the HTTP response field,
 
109
    and continue.
 
110
 
 
111
    Important Security Consideration: The message passed to this
 
112
    exception will be relayed to the client.
 
113
    """
 
114
    pass
 
115
 
104
116
def handle(req):
105
117
    """Handler for the File Services application."""
106
118
 
112
124
    # side-effects on the server.
113
125
    action = None
114
126
    fields = None
115
 
    if req.method == 'POST':
 
127
    if True or req.method == 'POST':
116
128
        fields = req.get_fieldstorage()
117
129
        action = fields.getfirst('action')
118
130
 
119
131
    if action is not None:
120
 
        handle_action(req, action, fields)
 
132
        try:
 
133
            handle_action(req, action, fields)
 
134
        except ActionError, message:
 
135
            req.headers_out['X-IVLE-Action-Error'] = str(message)
121
136
 
122
137
    handle_return(req)
123
138
 
128
143
    writes the X-IVLE-Action-Error header to the request object. Otherwise,
129
144
    does not touch the request object. Does NOT write any bytes in response.
130
145
 
 
146
    May throw an ActionError. The caller should put this string into the
 
147
    X-IVLE-Action-Error header, and then continue normally.
 
148
 
131
149
    action: String, the action requested. Not sanitised.
132
150
    fields: FieldStorage object containing all arguments passed.
133
151
    """
134
 
    if action == "rm":
135
 
        path = fields.getfirst('path')
136
 
        # TODO: Delete the file
137
 
        # Do an SVN rm if possible
138
 
        pass
 
152
    if action == "remove":
 
153
        path = fields.getlist('path')
 
154
        action_remove(req, path)
 
155
    else:
 
156
        # Default, just send an error but then continue
 
157
        raise ActionError("Unknown action")
139
158
 
140
159
def handle_return(req):
141
160
    """Perform the "return" part of the response.
249
268
        # Can't get any more information so just return d
250
269
        pass
251
270
    return filename, d
 
271
 
 
272
### ACTIONS ###
 
273
 
 
274
def actionpath_to_local(req, path):
 
275
    """Determines the local path upon which an action is intended to act.
 
276
    Note that fileservice actions accept two paths: the request path,
 
277
    and the "path" argument given to the action.
 
278
    According to the rules, if the "path" argument begins with a '/' it is
 
279
    relative to the user's home; if it does not, it is relative to the
 
280
    supplied path.
 
281
 
 
282
    This resolves the path, given the request and path argument.
 
283
 
 
284
    May raise an ActionError("Invalid path"). The caller is expected to
 
285
    let this fall through to the top-level handler, where it will be
 
286
    put into the HTTP response field. Never returns None.
 
287
    """
 
288
    if path is None:
 
289
        path = req.path
 
290
    elif len(path) > 0 and path[0] == os.sep:
 
291
        # Relative to student home
 
292
        path = path[1:]
 
293
    else:
 
294
        # Relative to req.path
 
295
        path = os.path.join(req.path, path)
 
296
 
 
297
    _, r = studpath.url_to_local(path)
 
298
    if r is None:
 
299
        raise ActionError("Invalid path")
 
300
    return r
 
301
 
 
302
def action_remove(req, paths):
 
303
    # TODO: Do an SVN rm if the file is versioned.
 
304
    """Removes a list of files or directories."""
 
305
    goterror = False
 
306
    for path in paths:
 
307
        path = actionpath_to_local(req, path)
 
308
        try:
 
309
            os.remove(path)
 
310
        except OSError:
 
311
            goterror = True
 
312
    if goterror:
 
313
        if len(paths) == 1:
 
314
            raise ActionError("Could not delete the file specified")
 
315
        else:
 
316
            raise ActionError(
 
317
                "Could not delete one or more of the files specified")