Attachment 'PackagePages.py'

Download

   1 # -*- coding: iso-8859-1 -*-
   2 """
   3     MoinMoin - PackagePages action
   4 
   5     This action allows you to package pages.
   6 
   7     @copyright: 2005 MoinMoin:AlexanderSchremmer
   8     @license: GNU GPL, see COPYING for details.
   9 """
  10 
  11 import os
  12 import zipfile
  13 from datetime import datetime
  14 
  15 from MoinMoin import wikiutil, config, user
  16 from MoinMoin.PageEditor import PageEditor
  17 from MoinMoin.Page import Page
  18 from MoinMoin.util import MoinMoinNoFooter
  19 from MoinMoin.action.AttachFile import _addLogEntry
  20 
  21 MOIN_PACKAGE_FILE = 'MOIN_PACKAGE'
  22 
  23 # Parsing and (un)quoting for script files
  24 def packLine(list, separator="|"):
  25     return separator.join([x.replace('\\', '\\\\').replace(separator, '\\' + separator) for x in list])
  26 
  27 def unpackLine(string, separator="|"):
  28     result = []
  29     token = ""
  30     escaped = False
  31     for x in string:
  32         if escaped and x in ('\\', separator):
  33             token += x
  34             escaped = False
  35             continue
  36         escaped = (x == '\\')
  37         if escaped:
  38             continue
  39         if x == separator:
  40             result.append(token)
  41             token = ""
  42         else:
  43             token += x
  44     result.append(token)
  45     return result
  46 
  47 class ActionError(Exception): pass
  48 
  49 class PackagePages:
  50     def __init__(self, pagename, request):
  51         self.request = request
  52         self.pagename = pagename
  53         self.page = Page(request, pagename)
  54 
  55     def allowed(self):
  56         """ Check if user is allowed to do this. """
  57         may = self.request.user.may
  58         return (self.__class__.__name__ in self.request.cfg.allowed_actions and
  59                 may.write(self.pagename))
  60     
  61     def render(self):
  62         """ Render action
  63 
  64         This action returns a wiki page with optional message, or
  65         redirects to new page.
  66         """
  67         _ = self.request.getText
  68         form = self.request.form
  69         
  70         if form.has_key('cancel'):
  71             # User canceled
  72             return self.page.send_page(self.request)
  73 
  74         try:
  75             if not self.allowed():
  76                 raise ActionError(_('You are not allowed to edit this page.'))
  77             elif not self.page.exists():
  78                 raise ActionError(_('This page is already deleted or was never created!'))
  79     
  80             self.package()
  81         except ActionError, e:
  82             return self.page.send_page(self.request, msg=e.args[0])
  83 
  84     def package(self):
  85         """ Packages pages. """
  86         _ = self.request.getText
  87         form = self.request.form
  88         COMPRESSION_LEVEL = zipfile.ZIP_DEFLATED
  89         
  90         # Get new name from form and normalize.
  91         pagelist = form.get('pagelist', [u''])[0]
  92         packagename = form.get('packagename', [u''])[0]
  93         
  94         if not form.get('submit', [None])[0]:
  95             raise ActionError(self.makeform())
  96 
  97         pages = []
  98         for pagename in unpackLine(pagelist, ","):
  99             pagename = self.request.normalizePagename(pagename)
 100             if pagename:
 101                 page = Page(self.request, pagename)
 102                 if page.exists() and self.request.user.may.read(pagename):
 103                     pages.append(page)
 104         if not pages:
 105             raise ActionError(self.makeform(_('No pages like "%s"!') % wikiutil.escape(pagelist)))
 106 
 107         pagelist = ', '.join([getattr(page, "page_name") for page in  pages])
 108         target = wikiutil.taintfilename(packagename)
 109     
 110         if not target:
 111             raise ActionError(self.makeform(_('Invalid filename "%s"!') % wikiutil.escape(packagename)))
 112         
 113         # get directory, and possibly create it
 114         attach_dir = Page(self.request, self.page.page_name).getPagePath("attachments", check_create=1)
 115         fpath = os.path.join(attach_dir, target).encode(config.charset)
 116         print fpath
 117         if os.path.exists(fpath):
 118             raise ActionError(_("Attachment '%(target)s' (remote name '%(filename)s') already exists.") % {
 119                 'target': wikiutil.escape(target), 'filename': wikiutil.escape(target)})
 120 
 121         zf = zipfile.ZipFile(fpath, "w", COMPRESSION_LEVEL)
 122 
 123         cnt = 0
 124         script = [packLine(['MoinMoinPackage', '1']),
 125                   ]
 126 
 127         for page in pages:
 128             cnt += 1
 129             script.append(packLine(["AddRevision", str(cnt), page.page_name, user.getUserIdentification(self.request), "Created by the PackagePages action."]))
 130             timestamp = wikiutil.version2timestamp(page.mtime_usecs())
 131             zi = zipfile.ZipInfo(filename=str(cnt), date_time=datetime.fromtimestamp(timestamp).timetuple()[:6])
 132             zi.compress_type = COMPRESSION_LEVEL
 133             zf.writestr(zi, page.get_raw_body().encode("utf-8"))
 134     
 135         script += [packLine(['Print', 'Thank you for using PackagePages!'])]
 136     
 137         zf.writestr(MOIN_PACKAGE_FILE, u"\n".join(script).encode("utf-8"))
 138         zf.close()
 139 
 140         os.chmod(fpath, 0666 & config.umask)
 141 
 142         _addLogEntry(self.request, 'ATTNEW', pagename, target)
 143         
 144         raise ActionError(_("Created the package %s containing the pages %s.") % (wikiutil.escape(target), wikiutil.escape(pagelist)))
 145 
 146     def makeform(self, error=""):
 147         """ Display a rename page form
 148 
 149         The form might contain an error that happened when trying to rename.
 150         """
 151         from MoinMoin.widget.dialog import Dialog
 152         _ = self.request.getText
 153 
 154         error = u'<p class="error">%s</p>\n' % error
 155 
 156         d = {
 157             'error': error,
 158             'action': self.__class__.__name__,
 159             'pagename': wikiutil.escape(self.pagename),
 160             'package': _('Package pages'),
 161             'cancel': _('Cancel'),
 162             'newname_label': _("Package name"),
 163             'list_label': _("List of page names - separated by <tt>,</tt>"),
 164         }
 165         form = '''
 166 %(error)s
 167 <form method="post" action="">
 168 <input type="hidden" name="action" value="%(action)s">
 169 <table>
 170     <tr>
 171         <td class="label"><label>%(newname_label)s</label></td>
 172         <td class="content">
 173             <input type="text" name="packagename" value="package.zip">
 174         </td>
 175     </tr>
 176     <tr>
 177         <td class="label"><label>%(list_label)s</label></td>
 178         <td class="content">
 179             <input type="text" name="pagelist" maxlength="80">
 180         </td>
 181     </tr>
 182     <tr>
 183         <td></td>
 184         <td class="buttons">
 185             <input type="submit" name="submit" value="%(package)s">
 186             <input type="submit" name="cancel" value="%(cancel)s">
 187         </td>
 188     </tr>
 189 </table>
 190 </form>''' % d
 191         
 192         return Dialog(self.request, content=form)        
 193     
 194 def execute(pagename, request):
 195     """ Glue code for actions """
 196     PackagePages(pagename, request).render()

Attached Files

To refer to attachments on a page, use attachment:filename, as shown below in the list of files. Do NOT use the URL of the [get] link, since this is subject to change and can break easily.
  • [get | view] (2005-06-26 18:12:59, 6.5 KB) [[attachment:PackagePages.py]]
  • [get | view] (2006-06-03 01:52:20, 1.0 KB) [[attachment:package.zip]]
 All files | Selected Files: delete move to page copy to page

You are not allowed to attach a file to this page.