Attachment 'PDF-1.2.py'
Download 1 # -*- coding: iso-8859-1 -*-
2 """
3 MoinMoin - PageAsPDF action Version 1.2, 12.02.2013
4
5 @copyright: 2013 Ian Riley <ian.riley@internode.on.net>
6
7 History:
8
9 Version 1.2 - 12.02.2013; enabled pragma settings for options,
10
11 Version 1.1 - 12.02.2013; added option to show the subrocess call
12
13 Version 1.0 - 6.02.2013: initial version.
14
15 incorporting code from:
16
17 @copyright: 2001 by Ken Sugino (sugino@mediaone.net),
18 2001-2004 by Juergen Hermann <jh@web.de>,
19 2005 MoinMoin:AlexanderSchremmer,
20 2005 DiegoOngaro at ETSZONE (diego@etszone.com),
21 2005-2007 MoinMoin:ReimarBauer,
22 2007-2008 MoinMoin:ThomasWaldmann
23
24 @license: GNU GPL, see COPYING for details.
25 """
26 import os, time, codecs, datetime
27 from subprocess import call
28 from werkzeug import http_date
29 from MoinMoin import config, wikiutil
30 from MoinMoin.Page import Page
31
32 action_name = __name__.split('.')[-1]
33 actname = {'actname': action_name}
34
35 class Options():
36 def __init__(self):
37 # Option Defaults: wiki and wkhtmltopdf Order
38 self.values = {'margin-top': ['20mm', '10mm', 1],
39 'margin-bottom': ['20mm', '10mm', 2],
40 'margin-left': ['10mm', '10mm', 3],
41 'margin-right': ['10mm', '10mm', 4],
42 'page-height': ['297mm', '297mm', 5],
43 'page-size': ['A4', 'A4', 6],
44 'page-width': ['210mm', '210mm', 7],
45 'title': ['[pagename]', '', 8],
46 'header-font-name': ['Arial', 'Arial', 9],
47 'header-font-size': ['9', '12', 10],
48 'header-spacing': ['10', '0', 11],
49 'header-line': [False, False, 12],
50 'header-left': ['[pagename]', '', 13],
51 'header-center': ['', '', 14],
52 'header-right': ['[date] [time]', '', 15],
53 'footer-font-name': ['Arial', 'Arial', 16],
54 'footer-font-size': ['9', '12', 17],
55 'footer-spacing': ['10', '', 18],
56 'footer-line': [False, False, 19],
57 'footer-left': ['[url]', '', 20],
58 'footer-center': ['', '', 21],
59 'footer-right': ['[page] of [topage]', '', 22],
60 }
61 def __repr__(self):
62 return str(self.formatted())
63
64 def update(self, new_opts = {}):
65 for k, v in new_opts.iteritems():
66 if k in self.values.keys():
67 if type(v) <> type(self.values[k][1]):
68 v = False
69 self.values[k][0] = v
70 return self.values
71
72 def replace(self, code, value):
73 code = '[%s]' % code
74 for k, v in self.values.iteritems():
75 if code in str(v[0]):
76 self.values[k][0] = v[0].replace(code, str(value))
77
78 def formatted(self):
79 values = sorted(self.values.iteritems(), key=lambda i: i[1][2])
80 couplets = [('--%s%s' % (k, [' %s' % v[0],''][type(v[0])==bool])).
81 split(' ', 1)
82 for k, v in values
83 if v[0] and (v[0] <> v[1])] #only if not app default
84 return [item for sublist in couplets for item in sublist] #flatten
85
86 def cookies(request):
87 triplets = [['--cookie', k, str(v)] for k, v in request.cookies.iteritems()]
88 return [item for sublist in triplets for item in sublist] #flatten
89
90 def page_options(request):
91 args = [str(args[4:]).split(' ',1)
92 for verb, args in request.page.meta
93 if verb == 'pragma' and args.startswith('pdf ')]
94 options = {}
95 for i, option in enumerate(args):
96 option[0] = option[0].replace('centre', 'center')
97 if len(option) == 1:
98 args[i].append(True)
99 options[option[0]] = option[1]
100 return options
101
102 def execute(pagename, request):
103
104 _ = request.getText
105
106
107 if not request.user.may.read(pagename):
108 Page(request, pagename).send_page()
109
110 show = request.values.get('show', 'pdf')
111
112 filename = '%s.pdf' % pagename.replace('/','-')
113 pdf_datetime = request.user.getFormattedDateTime(time.time())
114 pdf_date = request.user.getFormattedDate(time.time())
115 pdf_time = pdf_datetime.replace(pdf_date, '').strip()
116
117 options = Options()
118 options.update(page_options(request))
119
120 #prepare for subprocess call
121 #set app to local path for wkhtmltopdf
122 #TODO do this from wikiconfig
123 app = '/Applications/wkhtmltopdf.app/Contents/MacOS/wkhtmltopdf'
124 url = (request.url_root + request.page.url(request,
125 querystr={'action': 'print'},relative=True))
126 fpath = request.rootpage.getPagePath('wiki-page.pdf', isfile=1)
127
128 options.replace('pagename', pagename)
129 options.replace('url', url.replace('%20',' '))
130 # overide to give user not server date/time
131 options.replace('date', pdf_date)
132 options.replace('time', pdf_time)
133
134 params = ([app, '-q'] +
135 options.formatted() +
136 [url] +
137 cookies(request) +
138 [fpath])
139
140 #make and respond to subprocess call
141 if show == 'call' and request.user.may.admin(pagename):
142 for i, p in enumerate(params):
143 if ' ' in p:
144 params[i] = '"%s"' % p
145 request.theme.add_msg(' '.join(params), 'info')
146 elif show == 'pdf':
147 call_error = call(params)
148 if call_error:
149 msg = '%(actname)s failed.' % actname
150 request.theme.add_msg(msg, 'error')
151 else:
152 filename_enc = filename.encode(config.charset)
153 timestamp = datetime.datetime.fromtimestamp(os.path.getmtime(fpath))
154 mt = wikiutil.MimeType(filename=filename)
155 content_type = mt.content_type()
156 mime_type = mt.mime_type()
157 now = time.time()
158 request.headers['Date'] = http_date(now)
159 request.headers['Content-Type'] = content_type
160 request.headers['Last-Modified'] = http_date(timestamp)
161 request.headers['Expires'] = http_date(now - 365 * 24 * 3600)
162 request.headers['Content-Length'] = os.path.getsize(fpath)
163 content_dispo_string = '%s; filename="%s"' % ('inline', filename_enc)
164 request.headers['Content-Disposition'] = content_dispo_string
165 # send data
166 request.send_file(open(fpath, 'rb'))
167 else:
168 msg = '%(actname)s show request invalid.' % actname
169 request.theme.add_msg(msg, 'error')
170 Page(request, pagename).send_page()
You are not allowed to attach a file to this page.