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

« back to all changes in this revision

Viewing changes to lib/fileservice_lib/action.py

  • Committer: apeel
  • Date: 2008-06-17 06:12:45 UTC
  • Revision ID: svn-v3-trunk0:2b9c9e99-6f39-0410-b283-7f802c844ae2:trunk:781
install now creates a file ivle_install_dir/version/ivle-revision.txt
which contains a listing from 'svn status -v'. 
This is so that we can tell which version of the code is actually deployed.

Show diffs side-by-side

added added

removed removed

Lines of Context:
62
62
#               will create a directory instead and unpack the ZIP file
63
63
#               into it.
64
64
#
 
65
# action=mkdir: Create a directory. The parent dir must exist.
 
66
#       path:   The path to a file which does not exist, but whose parent
 
67
#               does. The dir will be made with this name.
 
68
#
65
69
# The differences between putfile and putfiles are:
66
70
# * putfile can only accept a single file.
67
71
# * putfile can accept string data, doesn't have to be a file upload.
68
72
# * putfile ignores the upload filename, the entire filename is specified on
69
73
#       path. putfiles calls files after the name on the user's machine.
70
74
#
71
 
# Clipboard-based actions. Cut/copy/paste work in the same way as modern
72
 
# file browsers, by keeping a server-side clipboard of files that have been
73
 
# cut and copied. The clipboard is stored in the session data, so it persists
74
 
# across navigation, tabs and browser windows, but not across browser
75
 
# sessions.
76
 
77
 
# action=copy: Write file(s) to the session-based clipboard. Overrides any
78
 
#               existing clipboard data. Does not actually copy the file.
79
 
#               The files are physically copied when the clipboard is pasted.
80
 
#       path:   The path to the file or directory to copy. Can be specified
81
 
#               multiple times.
82
 
83
 
# action=cut: Write file(s) to the session-based clipboard. Overrides any
84
 
#               existing clipboard data. Does not actually move the file.
85
 
#               The files are physically moved when the clipboard is pasted.
86
 
#       path:   The path to the file or directory to cut. Can be specified
87
 
#               multiple times.
88
 
89
 
# action=paste: Copy or move the files stored in the clipboard. Clears the
90
 
#               clipboard. The files are copied or moved to a specified dir.
91
 
#       path:   The path to the DIRECTORY to paste the files to. Must not
 
75
# action=paste: Copy or move the files to a specified dir.
 
76
#       src:    The path to the DIRECTORY to get the files from (relative).
 
77
#       dst:    The path to the DIRECTORY to paste the files to. Must not
92
78
#               be a file.
 
79
#       mode:   'copy' or 'move'
 
80
#       file:   File to be copied or moved, relative to src, to a destination
 
81
#               relative to dst. Can be specified multiple times.
93
82
#
94
83
# Subversion actions.
95
84
# action=svnadd: Add an existing file(s) to version control.
143
132
 
144
133
def get_login(_realm, _username, _may_save):
145
134
    """Return the subversion credentials for the user."""
146
 
    return (True, conf.login, conf.passwd, True)
 
135
    return (True, conf.login, conf.svn_pass, True)
147
136
 
148
137
# Make a Subversion client object
149
138
svnclient = pysvn.Client()
296
285
    topath = fields.getfirst('to')
297
286
    movefile(req, frompath, topath)
298
287
 
 
288
def action_mkdir(req, fields):
 
289
    """Creates a directory with the given path.
 
290
    Reads fields: 'path'
 
291
    """
 
292
    path = fields.getfirst('path')
 
293
    if path is None:
 
294
        raise ActionError("Required field missing")
 
295
    path = actionpath_to_local(req, path)
 
296
 
 
297
    # Create the directory
 
298
    try:
 
299
        os.mkdir(path)
 
300
    except OSError:
 
301
        raise ActionError("Could not create directory")
 
302
 
299
303
def action_putfile(req, fields):
300
304
    """Writes data to a file, overwriting it if it exists and creating it if
301
305
    it doesn't.
306
310
    # Important: Data is "None" if the file submitted is empty.
307
311
    path = fields.getfirst('path')
308
312
    data = fields.getfirst('data')
309
 
    if path is None or data is None:
 
313
    if path is None:
310
314
        raise ActionError("Required field missing")
 
315
    if data is None:
 
316
        # Workaround - field reader treats "" as None, so this is the only
 
317
        # way to allow blank file uploads
 
318
        data = ""
311
319
    path = actionpath_to_local(req, path)
312
320
 
313
321
    if data is not None:
347
355
    for datum in data:
348
356
        # Each of the uploaded files
349
357
        filepath = os.path.join(path, datum.filename)
350
 
        filedata = datum.value
 
358
        filedata = datum.file
351
359
 
352
360
        if unpack and datum.filename.lower().endswith(".zip"):
353
361
            # A zip file - unpack it instead of just copying
355
363
            # Note: Just unzip into the current directory (ignore the
356
364
            # filename)
357
365
            try:
358
 
                zip.unzip(path, filedata)
 
366
                # First get the entire path (within jail)
 
367
                _, _, abspath = studpath.url_to_jailpaths(path)
 
368
                abspath = os.path.join(os.sep, abspath)
 
369
                zip.unzip(abspath, filedata)
359
370
            except (OSError, IOError):
360
371
                goterror = True
361
372
        else:
379
390
            raise ActionError(
380
391
                "Could not write to one or more of the target files")
381
392
 
382
 
def action_copy_or_cut(req, fields, mode):
383
 
    """Marks specified files on the clipboard, stored in the
384
 
    browser session. Sets clipboard for either a cut or copy operation
385
 
    as specified.
386
 
 
387
 
    Reads fields: 'path'
388
 
    """
389
 
    # The clipboard object created conforms to the JSON clipboard
390
 
    # specification given at the top of listing.py.
391
 
    # Note that we do not check for the existence of files here. That is done
392
 
    # in the paste operation.
393
 
    files = fields.getlist('path')
394
 
    clipboard = { "mode" : mode, "base" : req.path, "files" : files }
395
 
    session = req.get_session()
396
 
    session['clipboard'] = clipboard
397
 
    session.save()
398
 
 
399
 
def action_copy(req, fields):
400
 
    """Marks specified files on the clipboard, stored in the
401
 
    browser session. Sets clipboard for a "copy" action.
402
 
 
403
 
    Reads fields: 'path'
404
 
    """
405
 
    action_copy_or_cut(req, fields, "copy")
406
 
 
407
 
def action_cut(req, fields):
408
 
    """Marks specified files on the clipboard, stored in the
409
 
    browser session. Sets clipboard for a "cut" action.
410
 
 
411
 
    Reads fields: 'path'
412
 
    """
413
 
    action_copy_or_cut(req, fields, "cut")
414
 
 
415
393
def action_paste(req, fields):
416
 
    """Performs the copy or move action with the files stored on
417
 
    the clipboard in the browser session. Copies/moves the files
418
 
    to the specified directory. Clears the clipboard.
 
394
    """Performs the copy or move action with the files specified.
 
395
    Copies/moves the files to the specified directory.
419
396
 
420
 
    Reads fields: 'path'
 
397
    Reads fields: 'src', 'dst', 'mode', 'file' (multiple).
 
398
    src: Base path that all the files are relative to (source).
 
399
    dst: Destination path to paste into.
 
400
    mode: 'copy' or 'move'.
 
401
    file: (Multiple) Files relative to base, which will be copied
 
402
        or moved to new locations relative to path.
421
403
    """
422
404
    errormsg = None
423
405
 
424
 
    todir = fields.getfirst('path')
425
 
    if todir is None:
 
406
    dst = fields.getfirst('dst')
 
407
    src = fields.getfirst('src')
 
408
    mode = fields.getfirst('mode')
 
409
    files = fields.getlist('file')
 
410
    if dst is None or src is None or mode is None:
426
411
        raise ActionError("Required field missing")
427
 
    todir_local = actionpath_to_local(req, todir)
428
 
    if not os.path.isdir(todir_local):
429
 
        raise ActionError("Target is not a directory")
430
 
 
431
 
    session = req.get_session()
432
 
    try:
433
 
        clipboard = session['clipboard']
434
 
        files = clipboard['files']
435
 
        base = clipboard['base']
436
 
        if clipboard['mode'] == "copy":
437
 
            copy = True
438
 
        else:
439
 
            copy = False
440
 
    except KeyError:
441
 
        raise ActionError("Clipboard was empty")
 
412
    if mode == "copy":
 
413
        copy = True
 
414
    elif mode == "move":
 
415
        copy = False
 
416
    else:
 
417
        raise ActionError("Invalid mode (must be 'copy' or 'move')")
 
418
    dst_local = actionpath_to_local(req, dst)
 
419
    if not os.path.isdir(dst_local):
 
420
        raise ActionError("dst is not a directory")
442
421
 
443
422
    errorfiles = []
444
423
    for file in files:
445
424
        # The source must not be interpreted as relative to req.path
446
425
        # Add a slash (relative to top-level)
447
 
        frompath = os.sep + os.path.join(base, file)
 
426
        if src[:1] != '/':
 
427
            src = '/' + src
 
428
        frompath = os.path.join(src, file)
448
429
        # The destination is found by taking just the basename of the file
449
 
        topath = os.path.join(todir, os.path.basename(file))
 
430
        topath = os.path.join(dst, os.path.basename(file))
450
431
        try:
451
432
            movefile(req, frompath, topath, copy)
452
433
        except ActionError, message:
459
440
            # Add this file to errorfiles; it will be put back on the
460
441
            # clipboard for possible future pasting.
461
442
            errorfiles.append(file)
462
 
    # If errors occured, augment the clipboard and raise ActionError
463
 
    if len(errorfiles) > 0:
464
 
        clipboard['files'] = errorfiles
465
 
        session['clipboard'] = clipboard
466
 
        session.save()
 
443
    if errormsg is not None:
467
444
        raise ActionError(errormsg)
468
445
 
469
 
    # Success: Clear the clipboard
470
 
    del session['clipboard']
471
 
    session.save()
 
446
    # XXX errorfiles contains a list of files that couldn't be pasted.
 
447
    # we currently do nothing with this.
 
448
 
 
449
def action_publish(req,fields):
 
450
    """Marks the folder as published by adding a '.published' file to the 
 
451
    directory and ensuring that the parent directory permissions are correct
 
452
 
 
453
    Reads fields: 'path'
 
454
    """
 
455
    paths = fields.getlist('path')
 
456
    user = studpath.url_to_local(req.path)[0]
 
457
    homedir = "/home/%s" % user
 
458
    if len(paths):
 
459
        paths = map(lambda path: actionpath_to_local(req, path), paths)
 
460
    else:
 
461
        paths = [studpath.url_to_jailpaths(req.path)[2]]
 
462
 
 
463
    # Set all the dirs in home dir world browsable (o+r,o+x)
 
464
    #FIXME: Should really only do those in the direct path not all of the 
 
465
    # folders in a students home directory
 
466
    for root,dirs,files in os.walk(homedir):
 
467
        os.chmod(root, os.stat(root).st_mode|0005)
 
468
 
 
469
    try:
 
470
        for path in paths:
 
471
            if os.path.isdir(path):
 
472
                pubfile = open(os.path.join(path,'.published'),'w')
 
473
                pubfile.write("This directory is published\n")
 
474
                pubfile.close()
 
475
            else:
 
476
                raise ActionError("Can only publish directories")
 
477
    except OSError, e:
 
478
        raise ActionError("Directory could not be published")
 
479
 
 
480
def action_unpublish(req,fields):
 
481
    """Marks the folder as unpublished by removing a '.published' file in the 
 
482
    directory (if it exits). It does not change the permissions of the parent 
 
483
    directories.
 
484
 
 
485
    Reads fields: 'path'
 
486
    """
 
487
    paths = fields.getlist('path')
 
488
    if len(paths):
 
489
        paths = map(lambda path: actionpath_to_local(req, path), paths)
 
490
    else:
 
491
        paths = [studpath.url_to_jailpaths(req.path)[2]]
 
492
 
 
493
    try:
 
494
        for path in paths:
 
495
            if os.path.isdir(path):
 
496
                pubfile = os.path.join(path,'.published')
 
497
                if os.path.isfile(pubfile):
 
498
                    os.remove(pubfile)
 
499
            else:
 
500
                raise ActionError("Can only unpublish directories")
 
501
    except OSError, e:
 
502
        raise ActionError("Directory could not be unpublished")
 
503
 
472
504
 
473
505
def action_svnadd(req, fields):
474
506
    """Performs a "svn add" to each file specified.
519
551
    Reads fields: 'path'
520
552
    """
521
553
    paths = fields.getlist('path')
522
 
    paths = map(lambda path: actionpath_to_local(req, path), paths)
 
554
    if len(paths):
 
555
        paths = map(lambda path: actionpath_to_local(req, path), paths)
 
556
    else:
 
557
        paths = [studpath.url_to_jailpaths(req.path)[2]]
523
558
 
524
559
    try:
525
560
        for path in paths:
579
614
actions_table = {
580
615
    "remove" : action_remove,
581
616
    "move" : action_move,
 
617
    "mkdir" : action_mkdir,
582
618
    "putfile" : action_putfile,
583
619
    "putfiles" : action_putfiles,
584
 
 
585
 
    "copy" : action_copy,
586
 
    "cut" : action_cut,
587
620
    "paste" : action_paste,
 
621
    "publish" : action_publish,
 
622
    "unpublish" : action_unpublish,
588
623
 
589
624
    "svnadd" : action_svnadd,
590
625
    "svnupdate" : action_svnupdate,