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

« back to all changes in this revision

Viewing changes to ivle/fileservice_lib/action.py

  • Committer: matt.giuca
  • Date: 2009-01-14 07:24:15 UTC
  • mto: This revision was merged to the branch mainline in revision 1090.
  • Revision ID: svn-v3-trunk0:2b9c9e99-6f39-0410-b283-7f802c844ae2:branches%2Fstorm:1129
ivle.database: Added User class.
    This is distinct from (and intended to replace) ivle.db.User.
    Sorry for the intermittent confusion.

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