Attachment 'AttachTable.py'
Download 1 """
2 MoinMoin - AttachTable Macro
3
4 A macro to produce a table of files attached to a page.
5
6 Usage:
7 [[AttachTable]]
8 [[AttachTable(page=FrontPage, preview=1)]]
9 [[AttachTable(readonly=1, closed=1, syntax=1]]
10
11 args:
12 @page=string display the attachemnt table for a different page
13 @preview=1 if the attachment is a jpg/gif/png file, show a thumbnail image
14 @syntax=1 display the wiki syntax how to reference to an attachment
15 @closed=0 display the table in a closed/open state overriding the default cfg value 'attach_table_compact'
16 @readonly=0 force the display the table in a readonly mode, i.e. remove the 'delete attachment' option
17
18 @copyright: 2007 Oliver Siemoneit
19 @copyright: 2006 Erick Martin, Oliver Siemoneit
20 @copyright: 2004 Jacob Cohen, Nigel Metheringham
21 @license: GNU GPL, see COPYING for details.
22
23 """
24
25 import os, urllib, time, random
26 from MoinMoin import config, wikiutil
27 from MoinMoin.action.AttachFile import getAttachDir, getAttachUrl
28 from MoinMoin.Page import Page
29
30 def _get_files(base_dir):
31 if os.path.isdir(base_dir):
32 files = map(lambda a: a.decode(config.charset), os.listdir(base_dir))
33 files.sort()
34 return files
35 return []
36
37 def _table_row(d):
38 row = (' <tr style="display:">\n'
39 ' <td>\n'
40 ' %(data_1)s\n'
41 ' <p>\n'
42 ' %(data_2)s\n'
43 ' </td>\n'
44 ' <td> %(data_3)s </td>\n'
45 ' <td> %(data_4)s </td>\n'
46 ' <td> %(data_5)s </td>\n'
47 ' </tr>\n') % d
48 return row
49
50 def make_thumbnail(request, formatter, attachment_url, ext):
51 _ = request.getText
52 kw = {}
53 alt, icon, w, h = request.theme.icons[ext]
54 kw['src'] = attachment_url
55 kw['alt'] = _(alt)
56 kw['height'] = h
57 # display problems: Opera would also need width
58 #kw['width'] = (h / orig_h) * orig_w
59 return "%s" % formatter.image(**kw)
60
61 def file_table(formatter, request, base_dir, pagename, preview_images=0, display_table_closed=0, display_attach_syntax=1, readonly=0):
62 _ = request.getText
63 attachments = _get_files(base_dir)
64 action = 'AttachFile'
65 page_url = wikiutil.quoteWikinameURL(pagename)
66
67 # wikiutil.link_tag does not support title so we do it long hand
68 manage_url = '<a href="%(baseurl)s/%(page_url)s?action=%(action)s" title="%(title)s" alt="%(title)s">%(text)s</a>' % {
69 'baseurl': request.getScriptname(),
70 'page_url': page_url,
71 'action': action,
72 'text': _('Add/Manage'),
73 'title': _('Add/Manage uploaded files'), }
74
75 if not attachments and Page(request, pagename).exists() == False:
76 return _(u"\n%(icon)s %(manage_url)s files for the '''%(pagename)s''' page ''[No such page]''\n") % {
77 'icon': request.theme.make_icon('table-null'),
78 'pagename': pagename,
79 'manage_url': manage_url, }
80
81 if not attachments:
82 return _(u"\n%(icon)s %(manage_url)s files for the '''%(pagename)s''' page\n") % {
83 'icon': request.theme.make_icon('table-null'),
84 'pagename': pagename,
85 'manage_url': manage_url, }
86
87 label_del = _("delete")
88 label_get = _("download")
89 label_edit = _("edit")
90 label_view = _("view")
91
92 table_closed_file_name = 'table-open.png'
93 table_open_file_name = 'table-close.png'
94
95 open_image = request.theme.img_url(table_open_file_name)
96 closed_image = request.theme.img_url(table_closed_file_name)
97
98 javascript_function = """
99 // Toggle display of a folder's contents.
100 function showHideContents ( idnum ) {
101 the_table = document.getElementById( 't' + idnum );
102
103 arrowObj = document.getElementById( 'a' + idnum );
104 // we use the image to determine if the table is open or closed
105 if (arrowObj.src.indexOf('%(table_open_file_name)s') > -1) {
106 arrowObj.src = '%(closed_image)s';
107 display = 'none';
108 } else {
109 arrowObj.src = '%(open_image)s';
110 display = '';
111 }
112
113 // change the open/closed state of the rows for the table
114 for (var i = 0; i < the_table.rows.length; i++) {
115 the_table.rows[i].style.display = display;
116 }
117 }
118 """ % {'closed_image': closed_image,
119 'open_image': open_image,
120 'table_open_file_name': table_open_file_name, }
121
122 html = ("\n"
123 '<script type="text/javascript">' "\n"
124 "<!--\n"
125 "%(javascript_function)s\n"
126 "--> </script>\n"
127 "\n" ) % {'javascript_function': javascript_function, }
128
129
130 file_id = random.randint(1, 99999999999)
131
132 html = html + '\n<div class="attachmentTable" >\n'
133
134 table_caption1 = ('<a onClick="showHideContents(%(file_id)s);" title="%(alt_title)s">'
135 '<img id="a%(file_id)s" align="middle" border=0 src="%(open_image)s"'
136 'alt="%(alt_title)s"></a>\n') % {
137 'file_id': file_id,
138 'alt_title': _("Click to open/close table"),
139 'open_image': open_image, }
140
141 table_caption2 = _(u"%(manage_url)s files for the '''%(pagename)s''' page ''[%(num_files)s file(s)]''") % {
142 'num_files': len(attachments),
143 'pagename': pagename,
144 'manage_url': manage_url, }
145
146 table_caption = table_caption1 + table_caption2
147
148 if display_attach_syntax:
149 html = html + ('<br>\n'
150 '%(table_caption)s\n'
151 '<table id="t%(file_id)s" >\n'
152 ' <tr style="display:">\n'
153 ' <th>%(name)s<p>%(syntax)s</th>\n'
154 ' <th>%(size)s</th>\n'
155 ' <th>%(date)s</th>\n'
156 ' <th>%(action)s</th>\n'
157 ' </tr>\n') % {
158 'file_id': file_id,
159 'table_caption': table_caption,
160 'name': _('Name'),
161 'syntax': _('Wiki Include Syntax'),
162 'size': _('Size'),
163 'date': _('Date'),
164 'action': _('Action'),}
165 else:
166 html = html + ('<br>\n'
167 '%(table_caption)s\n'
168 '<table id="t%(file_id)s" >\n'
169 ' <tr style="display:">\n'
170 ' <th>%(name)s</th>\n'
171 ' <th>%(size)s</th>\n'
172 ' <th>%(date)s</th>\n'
173 ' <th>%(action)s</th>\n'
174 ' </tr>\n') % {
175 'file_id': file_id,
176 'table_caption': table_caption,
177 'name': _('Name'),
178 'size': _('Size'),
179 'date': _('Date'),
180 'action': _('Action'),}
181
182 # if user can't delete, force readonly mode
183 if not request.user.may.delete(pagename):
184 readonly = 1
185
186 for attachment in attachments:
187 fsize = float(os.stat(os.path.join(base_dir, attachment).encode(config.charset))[6]) # in byte
188 mtime = os.stat(os.path.join(base_dir, attachment).encode(config.charset))[8]
189 fsize = "%.1f" % (fsize/1024)
190 fdate = time.ctime(mtime)
191 urlfile = urllib.quote_plus(attachment.encode(config.charset))
192
193 # build translation for datetime object
194 _fdate = fdate.split(' ')
195 _fdate[0] = _(_fdate[0])
196 _fdate[1] = _(_fdate[1])
197 fdate = _("%(day)s %(month)s %(date)s %(time)s %(year)s") % { 'day': _fdate[0],
198 'month': _fdate[1],
199 'date': _fdate[2],
200 'time': _fdate[3],
201 'year': _fdate[4], }
202
203 base, ext = os.path.splitext(attachment)
204 get_url = getAttachUrl(pagename, attachment, request, escaped=1)
205 parmdict = {'page_url': page_url, 'action': action,
206 'urlfile': urlfile, 'label_del': label_del,
207 'base': base, 'label_edit': label_edit,
208 'label_view': label_view,
209 'get_url': get_url, 'label_get': label_get,
210 'file': attachment, 'fsize': fsize,
211 'pagename': pagename, }
212
213 del_link = ''
214 if not readonly:
215 action_args = 'do=del&target=%(urlfile)s' % {'urlfile' : urlfile, }
216 url = '%(page_url)s?action=%(action)s&%(action_args)s' % {
217 'page_url': page_url,
218 'action': action,
219 'action_args': action_args, }
220 del_link = wikiutil.link_tag(request, url, text=label_del,
221 formatter=request.formatter)
222
223
224 if ext == '.draw':
225 action_args = 'drawing=%(base)s' % {'base': base, }
226 url = '%(page_url)s?action=%(action)s&%(action_args)s' % {
227 'page_url': page_url,
228 'action': action,
229 'action_args': action_args, }
230
231 viewlink = wikiutil.link_tag(request, url, text=label_edit,
232 formatter=request.formatter)
233 else:
234 action_args = 'do=view&target=%(urlfile)s' % {'urlfile': urlfile, }
235 url = '%(page_url)s?action=%(action)s&%(action_args)s' % {
236 'page_url': page_url,
237 'action': action,
238 'action_args': action_args, }
239 viewlink = wikiutil.link_tag(request, url, text=label_view,
240 formatter=request.formatter)
241
242 #build file or preview icon
243 ext = ext.lower()
244 do_preview = False
245 #check if we have an icon for the extension
246 if ext in request.theme.icons:
247 if not preview_images:
248 ext = ext
249 else:
250 if ext in ['.jpg', '.jpeg', '.jpe', '.gif', '.png']:
251 do_preview = True
252 # if not: check whether ext belongs to a generic mimetype class
253 elif ext in ['.py', '.js', '.jar', '.diff', '.patch']:
254 ext = 'generic-text-x-source'
255 elif ext in ['.tar', '.zip', '.bz2', '.rar', '.gz', '.cab', '.lha', '.arj']:
256 ext = 'generic-x-archive'
257 elif ext in ['.wav', '.aif', '.aifc', '.aiff', '.midi', '.mid', '.au']:
258 ext = 'generic-x-audio'
259 elif ext in ['.jpg', '.jpeg', '.jpe', '.gif', '.png']:
260 ext = 'generic-x-image'
261 if preview_images:
262 do_preview = True
263 elif ext in ['.bmp', '.ps', '.eps', '.cdr', '.pct', '.mac', '.drw', '.svg']:
264 ext = 'generic-x-image'
265 elif ext in ['.mpeg', '.mpg', '.wmv', '.avi', '.mov', '.movie', '.qt']:
266 ext = 'generic-x-video'
267 elif ext in ['.htm', '.html']:
268 ext = '.html'
269 # if not: take icon 'unknown filetype'
270 else:
271 ext = 'unknown'
272
273 # check if we have to do an image preview or not
274 if preview_images and do_preview:
275 image = make_thumbnail(request, formatter, get_url, ext)
276 else:
277 image = request.theme.make_icon(ext)
278
279 parmdict['image'] = image
280 parmdict['viewlink'] = viewlink
281 parmdict['del_link'] = del_link
282
283 parmdict['open_image'] = open_image
284
285 action_args = 'do=get&target=%(urlfile)s' % {'urlfile': urlfile, }
286 url = '%(page_url)s?action=%(action)s&%(action_args)s' % {
287 'page_url': page_url,
288 'action': action,
289 'action_args': action_args, }
290 text = ' %(image)s %(file)s ' % {'image': image, 'file': attachment, }
291 getlink = wikiutil.link_tag(request, url, text=text,
292 formatter=request.formatter)
293
294 parmdict['getlink'] = getlink
295
296 depth = len(attachment.split(os.path.sep)) - 1
297 indent_txt = "<div class=indent%d>\n " % depth
298
299 if not os.path.isdir(os.path.join(base_dir, attachment).encode(config.charset)):
300 data_5 = ('\n'
301 ' %(viewlink)s\n'
302 ' <a href="%(get_url)s"> %(label_get)s </a>\n'
303 ' %(del_link)s\n ') % parmdict
304 data_2 = ' '
305 if display_attach_syntax:
306 if pagename == request.formatter.page.page_name:
307 data_2 = 'attachment:%(file)s' % {'file' : wikiutil.url_quote(attachment), }
308 else:
309 data_2 = 'attachment:%(pagename)s/%(file)s' % {
310 'file': wikiutil.url_quote(attachment),
311 'pagename': pagename, }
312
313 html = html + _table_row( {
314 'data_1' : indent_txt + '<strong>%(getlink)s</strong>' % parmdict,
315 'data_2' : data_2,
316 'data_3' : '%(fsize)s KB' % parmdict,
317 'data_4' : '%(fdate)s' % { 'fdate' : fdate },
318 'data_5' : data_5,
319 } )
320
321 html = html + '\n</table>\n</div>\n'
322
323 if display_table_closed:
324 close_str = ('\n<script type="text/javascript">\n'
325 '<!--\nshowHideContents(%(file_id)s);\n-->\n'
326 '</script>\n' ) % { 'file_id' : file_id, }
327 html = html + close_str
328
329
330 return html
331
332 def getArgs(given_arguments, allowed_arguments):
333 if not given_arguments:
334 return {}
335 args = {}
336 for s in given_arguments.split(','):
337 if s and s.find('=') > 0:
338 key, value = s.split('=', 1)
339 if key and value:
340 key = key.strip()
341 if key in allowed_arguments:
342 args[key] = value.strip()
343 return args
344
345 def execute(macro, options):
346 arguments = ['page', 'preview', 'syntax', 'closed', 'readonly']
347 args = getArgs(options, arguments)
348 pagename = args.get('page', macro.formatter.page.page_name)
349
350 # access directory
351 attach_dir = getAttachDir(macro.request, pagename)
352
353 default_table_closed = 0
354 if hasattr(macro.request.cfg, 'attach_table_compact'):
355 default_table_closed = macro.request.cfg.attach_table_compact
356 table_closed = int(args.get('closed', default_table_closed))
357
358 default_attach_syntax = 0
359 display_attach_syntax = int(args.get('syntax', default_attach_syntax))
360
361 table_readonly = int(args.get('readonly', 0))
362 preview_images = int(args.get('preview', 0))
363
364 return file_table(macro.formatter, macro.request, attach_dir, pagename,
365 preview_images, table_closed, display_attach_syntax, table_readonly)
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.