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.You are not allowed to attach a file to this page.