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.