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

« back to all changes in this revision

Viewing changes to ivle/fileservice_lib/action.py

  • Committer: William Grant
  • Date: 2009-07-31 04:26:02 UTC
  • mfrom: (1281.1.9 aufsless)
  • Revision ID: me@williamgrant.id.au-20090731042602-51tp90sv3icl7iqv
Jails no longer use aufs, but bind mounts. Both parts of the jails must be rebuilt.

Show diffs side-by-side

added added

removed removed

Lines of Context:
131
131
import os
132
132
import cStringIO
133
133
import shutil
 
134
import urllib
134
135
 
135
136
import pysvn
136
137
 
137
138
from ivle import (util, studpath, zip)
 
139
from ivle.fileservice_lib.exceptions import WillNotOverwrite
138
140
import ivle.conf
139
141
 
 
142
 
140
143
def get_login(_realm, existing_login, _may_save):
141
144
    """Callback function used by pysvn for authentication.
142
145
    realm, existing_login, _may_save: The 3 arguments passed by pysvn to
149
152
    # If we're being asked again, then it means the credentials failed for
150
153
    # some reason and we should just fail. (This is not desirable, but it's
151
154
    # better than being asked an infinite number of times).
152
 
    return (existing_login != "", ivle.conf.login, ivle.conf.svn_pass, True)
 
155
    return (existing_login != "", str(ivle.conf.login),
 
156
                                  str(ivle.conf.svn_pass), True)
153
157
 
154
158
# Make a Subversion client object
155
159
svnclient = pysvn.Client()
194
198
    except KeyError:
195
199
        # Default, just send an error but then continue
196
200
        raise ActionError("Unknown action")
197
 
    action(req, fields)
 
201
    return action(req, fields)
198
202
 
199
203
def actionpath_to_urlpath(req, path):
200
204
    """Determines the URL path (relative to the student home) upon which the
225
229
 
226
230
    Does not mutate req.
227
231
    """
228
 
    (_, _, r) = studpath.url_to_jailpaths(actionpath_to_urlpath(req, path))
 
232
    r = studpath.to_home_path(actionpath_to_urlpath(req, path))
229
233
    if r is None:
230
234
        raise ActionError("Invalid path")
231
235
    return r
263
267
    except shutil.Error:
264
268
        raise ActionError("Could not move the file specified")
265
269
 
 
270
def svn_movefile(req, frompath, topath, copy=False):
 
271
    """Performs an svn move, resolving filenames, checking for any errors,
 
272
    and throwing ActionErrors if necessary. Can also be used to do a copy
 
273
    operation instead.
 
274
 
 
275
    frompath and topath are straight paths from the client. Will be checked.
 
276
    """
 
277
    if frompath is None or topath is None:
 
278
        raise ActionError("Required field missing")
 
279
    frompath = actionpath_to_local(req, frompath)
 
280
    topath = actionpath_to_local(req, topath)
 
281
    if not os.path.exists(frompath):
 
282
        raise ActionError("The source file does not exist")
 
283
    if os.path.exists(topath):
 
284
        if frompath == topath:
 
285
            raise ActionError("Source and destination are the same")
 
286
        raise ActionError("A file already exists with that name")
 
287
 
 
288
    try:
 
289
        if copy:
 
290
            svnclient.copy(frompath, topath)
 
291
        else:
 
292
            svnclient.move(frompath, topath)
 
293
    except OSError:
 
294
        raise ActionError("Could not move the file specified")
 
295
    except pysvn.ClientError:
 
296
        raise ActionError("Could not move the file specified")  
 
297
 
 
298
 
266
299
### ACTIONS ###
267
300
 
268
301
def action_delete(req, fields):
370
403
 
371
404
    Reads fields: 'path', 'data' (file upload, multiple), 'unpack'
372
405
    """
373
 
 
374
406
    # Important: Data is "None" if the file submitted is empty.
375
407
    path = fields.getfirst('path')
376
408
    data = fields['data']
389
421
    for datum in data:
390
422
        # Each of the uploaded files
391
423
        filepath = os.path.join(path, datum.filename)
 
424
        filepath_local = studpath.to_home_path(filepath)
 
425
        if os.path.isdir(filepath_local):
 
426
            raise ActionError("A directory already exists "
 
427
                    + "with that name")
 
428
        else:
 
429
            if os.path.exists(filepath_local):
 
430
                raise ActionError("A file already exists with that name")
392
431
        filedata = datum.file
393
432
 
394
433
        if unpack and datum.filename.lower().endswith(".zip"):
398
437
            # filename)
399
438
            try:
400
439
                # First get the entire path (within jail)
401
 
                _, _, abspath = studpath.url_to_jailpaths(path)
 
440
                abspath = studpath.to_home_path(path)
402
441
                abspath = os.path.join(os.sep, abspath)
403
442
                zip.unzip(abspath, filedata)
404
443
            except (OSError, IOError):
405
444
                goterror = True
 
445
            except WillNotOverwrite, e:
 
446
                raise ActionError("File '" + e.filename + "' already exists.")
406
447
        else:
407
448
            # Not a zip file
408
 
            (_, _, filepath_local) = studpath.url_to_jailpaths(filepath)
 
449
            filepath_local = studpath.to_home_path(filepath)
409
450
            if filepath_local is None:
410
451
                raise ActionError("Invalid path")
411
452
 
444
485
    files = fields.getlist('file')
445
486
    if dst is None or src is None or mode is None:
446
487
        raise ActionError("Required field missing")
447
 
    if mode == "copy":
448
 
        copy = True
449
 
    elif mode == "move":
450
 
        copy = False
451
 
    else:
452
 
        raise ActionError("Invalid mode (must be 'copy' or 'move')")
 
488
 
453
489
    dst_local = actionpath_to_local(req, dst)
454
490
    if not os.path.isdir(dst_local):
455
491
        raise ActionError("dst is not a directory")
464
500
        # The destination is found by taking just the basename of the file
465
501
        topath = os.path.join(dst, os.path.basename(file))
466
502
        try:
467
 
            movefile(req, frompath, topath, copy)
 
503
            if mode == "copy":
 
504
                movefile(req, frompath, topath, True)
 
505
            elif mode == "move":
 
506
                movefile(req, frompath, topath, False)
 
507
            elif mode == "svncopy":
 
508
                svn_movefile(req, frompath, topath, True)
 
509
            elif mode == "svnmove":
 
510
                svn_movefile(req, frompath, topath, False)
 
511
            else:
 
512
                raise ActionError("Invalid mode (must be '(svn)copy' or '(svn)move')")
468
513
        except ActionError, message:
469
514
            # Store the error for later; we want to copy as many as possible
470
515
            if errormsg is None:
488
533
    Reads fields: 'path'
489
534
    """
490
535
    paths = fields.getlist('path')
491
 
    user = studpath.url_to_local(req.path)[0]
 
536
    user = util.split_path(req.path)[0]
492
537
    homedir = "/home/%s" % user
493
538
    if len(paths):
494
539
        paths = map(lambda path: actionpath_to_local(req, path), paths)
495
540
    else:
496
 
        paths = [studpath.url_to_jailpaths(req.path)[2]]
 
541
        paths = [studpath.to_home_path(req.path)]
497
542
 
498
543
    # Set all the dirs in home dir world browsable (o+r,o+x)
499
544
    #FIXME: Should really only do those in the direct path not all of the 
523
568
    if len(paths):
524
569
        paths = map(lambda path: actionpath_to_local(req, path), paths)
525
570
    else:
526
 
        paths = [studpath.url_to_jailpaths(req.path)[2]]
 
571
        paths = [studpath.to_home_path(req.path)]
527
572
 
528
573
    try:
529
574
        for path in paths:
620
665
    if len(paths):
621
666
        paths = map(lambda path: actionpath_to_local(req, path), paths)
622
667
    else:
623
 
        paths = [studpath.url_to_jailpaths(req.path)[2]]
 
668
        paths = [studpath.to_home_path(req.path)]
624
669
 
625
670
    try:
626
671
        for path in paths:
669
714
    paths = fields.getlist('path')
670
715
    if len(paths) != 2:
671
716
        raise ActionError("usage: svncheckout url local-path")
672
 
    url = ivle.conf.svn_addr + "/" + paths[0]
 
717
    url = ivle.conf.svn_addr + "/" + urllib.quote(paths[0])
673
718
    local_path = actionpath_to_local(req, str(paths[1]))
674
719
    try:
675
720
        svnclient.callback_get_login = get_login
694
739
def action_svnrepostat(req, fields):
695
740
    """Discovers whether a path exists in a repo under the IVLE SVN root.
696
741
 
 
742
    If it does exist, returns a dict containing its metadata.
 
743
 
697
744
    Reads fields: 'path'
698
745
    """
699
746
    path = fields.getfirst('path')
700
747
    url = ivle.conf.svn_addr + "/" + path
701
 
    svnclient.exception_style = 1 
 
748
    svnclient.exception_style = 1
702
749
 
703
750
    try:
704
751
        svnclient.callback_get_login = get_login
705
 
        svnclient.info2(url)
 
752
        info = svnclient.info2(url,
 
753
            revision=pysvn.Revision(pysvn.opt_revision_kind.head))[0][1]
 
754
        return {'svnrevision': info['rev'].number
 
755
                  if info['rev'] and
 
756
                     info['rev'].kind == pysvn.opt_revision_kind.number
 
757
                  else None}
706
758
    except pysvn.ClientError, e:
707
759
        # Error code 170000 means ENOENT in this revision.
708
760
        if e[1][0][1] == 170000:
709
761
            raise util.IVLEError(404, 'The specified repository path does not exist')
710
762
        else:
711
763
            raise ActionError(str(e[0]))
 
764
            
712
765
 
713
766
# Table of all action functions #
714
767
# Each function has the interface f(req, fields).