Attachment 'PDF-1.4.py'

Download

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

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