changeset 6018:b85dc05a75e1

AttachFile: move or delete multiple attachments
author Thomas Waldmann <tw AT waldmann-edv DOT de>
date Fri, 31 Jan 2014 18:33:18 +0100
parents 06af086f97f5
children 926d83725c3a
files MoinMoin/action/AttachFile.py
diffstat 1 files changed, 131 insertions(+), 30 deletions(-) [+]
line wrap: on
line diff
--- a/MoinMoin/action/AttachFile.py	Sat Jan 11 03:53:05 2014 +0100
+++ b/MoinMoin/action/AttachFile.py	Fri Jan 31 18:33:18 2014 +0100
@@ -265,6 +265,54 @@
     return target, filesize
 
 
+class SamePath(Exception):
+    """
+    raised if an attachment move is attempted to same target path
+    """
+
+class DestPathExists(Exception):
+    """
+    raised if an attachment move is attempted to an existing target path
+    """
+
+
+def move_attachment(request, pagename, dest_pagename, target, dest_target,
+                    overwrite=False):
+    """ move attachment <target> of page <pagename>
+        to attachment <dest_target> of page <dest_pagename>
+
+        note: this is lowlevel code, acl permissions need to be checked before
+              and also the target page should somehow exist (can be "deleted",
+              but the pagedir should be there)
+    """
+    # replace illegal chars
+    target = wikiutil.taintfilename(target)
+    dest_target = wikiutil.taintfilename(dest_target)
+
+    attachment_path = os.path.join(getAttachDir(request, pagename),
+                                   target).encode(config.charset)
+    dest_attachment_path = os.path.join(getAttachDir(request, dest_pagename, create=1),
+                                        dest_target).encode(config.charset)
+    if not overwrite and os.path.exists(dest_attachment_path):
+        raise DestPathExists
+    if dest_attachment_path == attachment_path:
+        raise SamePath
+    filesize = os.path.getsize(attachment_path)
+    try:
+        filesys.rename(attachment_path, dest_attachment_path)
+    except Exception:
+        raise
+    else:
+        _addLogEntry(request, 'ATTDEL', pagename, target)
+        event = FileRemovedEvent(request, pagename, target, filesize)
+        send_event(event)
+        _addLogEntry(request, 'ATTNEW', dest_pagename, dest_target)
+        event = FileAttachedEvent(request, dest_pagename, dest_target, filesize)
+        send_event(event)
+
+    return dest_target, filesize
+
+
 #############################################################################
 ### Internal helpers
 #############################################################################
@@ -346,6 +394,22 @@
         may_write = request.user.may.write(pagename)
         may_delete = request.user.may.delete(pagename)
 
+        html.append(u"""\
+<script>
+function checkAll(bx, targets_name) {
+  var cbs = document.getElementsByTagName('input');
+  for(var i=0; i < cbs.length; i++) {
+    if(cbs[i].type == 'checkbox' && cbs[i].name == targets_name) {
+      cbs[i].checked = bx.checked;
+    }
+  }
+}
+</script>
+<form method="POST">
+<input type="hidden" name="action" value="AttachFile">
+<input type="hidden" name="do" value="multifile">
+""")
+
         html.append(fmt.bullet_list(1))
         for file in files:
             mt = wikiutil.MimeType(filename=file)
@@ -410,9 +474,26 @@
 
             html.append(fmt.listitem(1))
             html.append("[%s]" % "&nbsp;| ".join(links))
+            html.append('''<input type="checkbox" name="fn" value="%s">''' % file)
             html.append(" (%(fmtime)s, %(fsize)s KB) [[attachment:%(file)s]]" % parmdict)
             html.append(fmt.listitem(0))
         html.append(fmt.bullet_list(0))
+        html.append(u"""\
+<input type="checkbox" onclick="checkAll(this, 'fn')">\
+&nbsp;%(all_files)s&nbsp;|&nbsp;%(sel_files)s
+<input type="radio" name="multifile" value="rm">%(delete)s</input>
+<input type="radio" name="multifile" value="mv">%(move)s</input>
+<input type="text" name="multi_dest_pagename" value="%(pagename)s">
+<input type="submit" value="%(submit)s">
+""" % dict(
+            all_files=_('All files'),
+            sel_files=_("Selected Files:"),
+            delete=_("delete"),
+            move=_("move to page"),
+            pagename=pagename,
+            submit=_("Do it."),
+))
+        html.append("</form>")
 
     else:
         if showheader:
@@ -424,6 +505,35 @@
     return ''.join(html)
 
 
+def _do_multifile(pagename, request):
+    _ = request.getText
+    action = request.form.get('multifile')
+    fnames = request.form.getlist('fn')
+    if action == 'rm':
+        if not request.user.may.delete(pagename):
+            return _('You are not allowed to delete attachments on this page.')
+        for fn in fnames:
+            remove_attachment(request, pagename, fn)
+        msg = _("Attachment '%(filename)s' deleted.") % dict(
+                filename=u'{%s}' % ','.join(fnames))
+        return upload_form(pagename, request, msg=msg)
+    if action == 'mv':
+        if not request.user.may.delete(pagename):
+            return _('You are not allowed to move attachments from this page.')
+        dest_pagename = request.form.get('multi_dest_pagename')
+        if not request.user.may.write(dest_pagename):
+            return _('You are not allowed to attach a file to this page.')
+        for fn in fnames:
+            move_attachment(request, pagename, dest_pagename, fn, fn)
+        msg = _("Attachment '%(pagename)s/%(filename)s' moved to '%(new_pagename)s/%(new_filename)s'.") % dict(
+                pagename=pagename,
+                filename=u'{%s}' % ','.join(fnames),
+                new_pagename=dest_pagename,
+                new_filename=u'*')
+        return upload_form(pagename, request, msg=msg)
+    return u'unsupported multifile operation'
+
+
 def _get_files(request, pagename):
     attach_dir = getAttachDir(request, pagename)
     if os.path.isdir(attach_dir):
@@ -695,39 +805,30 @@
     _ = request.getText
 
     newpage = Page(request, new_pagename)
-    if newpage.exists(includeDeleted=1) and request.user.may.write(new_pagename) and request.user.may.delete(pagename):
-        new_attachment_path = os.path.join(getAttachDir(request, new_pagename,
-                              create=1), new_attachment).encode(config.charset)
-        attachment_path = os.path.join(getAttachDir(request, pagename),
-                          attachment).encode(config.charset)
-
-        if os.path.exists(new_attachment_path):
-            upload_form(pagename, request,
-                msg=_("Attachment '%(new_pagename)s/%(new_filename)s' already exists.") % {
+    if (newpage.exists(includeDeleted=1)
+        and
+        request.user.may.write(new_pagename)
+        and
+        request.user.may.delete(pagename)):
+        try:
+            move_attachment(request, pagename, new_pagename,
+                            attachment, new_attachment)
+        except DestPathExists:
+            msg = _("Attachment '%(new_pagename)s/%(new_filename)s' already exists.") % {
                     'new_pagename': new_pagename,
-                    'new_filename': new_attachment})
-            return
-
-        if new_attachment_path != attachment_path:
-            filesize = os.path.getsize(attachment_path)
-            filesys.rename(attachment_path, new_attachment_path)
-            _addLogEntry(request, 'ATTDEL', pagename, attachment)
-            event = FileRemovedEvent(request, pagename, attachment, filesize)
-            send_event(event)
-            _addLogEntry(request, 'ATTNEW', new_pagename, new_attachment)
-            event = FileAttachedEvent(request, new_pagename, new_attachment, filesize)
-            send_event(event)
-            upload_form(pagename, request,
-                        msg=_("Attachment '%(pagename)s/%(filename)s' moved to '%(new_pagename)s/%(new_filename)s'.") % {
-                            'pagename': pagename,
-                            'filename': attachment,
-                            'new_pagename': new_pagename,
-                            'new_filename': new_attachment})
+                    'new_filename': new_attachment}
+        except SamePath:
+            msg = _("Nothing changed")
         else:
-            upload_form(pagename, request, msg=_("Nothing changed"))
+            msg = _("Attachment '%(pagename)s/%(filename)s' moved to '%(new_pagename)s/%(new_filename)s'.") % {
+                    'pagename': pagename,
+                    'filename': attachment,
+                    'new_pagename': new_pagename,
+                    'new_filename': new_attachment}
     else:
-        upload_form(pagename, request, msg=_("Page '%(new_pagename)s' does not exist or you don't have enough rights.") % {
-            'new_pagename': new_pagename})
+        msg = _("Page '%(new_pagename)s' does not exist or you don't have enough rights.") % {
+                'new_pagename': new_pagename}
+    upload_form(pagename, request, msg=msg)
 
 
 def _do_attachment_move(pagename, request):