Attachment 'CreatePdfDocument2_1_1.py'

Download

   1 # -*- coding: iso-8859-1 -*-
   2 __doc__ = """
   3     MoinMoin - Generate PDF document using HTMLDOC
   4 
   5     This action script generate PDF documents from a Wiki site using
   6     the HTMLDOC (http://www.htmldoc.org) software packages which has
   7     to be preinstalled first.
   8 
   9     To use this feature install this script in your's MoinMoin action
  10     script plugin directory.
  11 
  12     Thanks goes to Pascal Bauermeister who initiated the implementaion.
  13     Lot of things changes since then but the idear using HTMLDOC is the
  14     main concept of this implementation.
  15 
  16     @copyright: (C) 2006  Pascal Bauermeister
  17     @copyright: (C) 2006-2007  Raphael Bossek <raphael.bossek@solutions4linux.de>
  18     @license: GNU GPL, see COPYING for details
  19 """
  20 
  21 __version__ = u'2.1.1'
  22 
  23 release_information = """
  24     2007-08-21  RaphaelBossek
  25     * Release v2.1.1
  26     * Applied speed improvemtn patch from BrianDickman.
  27     * Fixed font size values where x.9 was missing.
  28     * Some cosmetic changes in the form.
  29 
  30     2007-08-20  RaphaelBossek
  31     * Release v2.1.0
  32     * Configuration is seperated by tabbs.
  33     * Added support for font style and colors.
  34     * Fixed save/load of configuration variables within page (may be empty).
  35     
  36     2007-08-17  RaphaelBossek
  37     * Release v2.0.11
  38     * Added support for alternative title page and title page logo.
  39     * Added support for additional fields for the title page author, docnumber
  40       and copyright.
  41     
  42     2006-12-18  RaphaelBossek
  43     * Release v2.0.10
  44     * Improved support for webpage/book styles if the HTML documents does not.
  45     
  46     2006-12-17  RaphaelBossek
  47     * Release v2.0.9
  48     * Added AUTH_TYPE for RedirectOutputRequest()
  49     
  50     2006-11-16  RaphaelBossek
  51     * Release v2.0.8
  52     * Fixed another missing configuration for RedirectOutputRequest()
  53 
  54     2006-11-15  RaphaelBossek
  55     * Release v2.0.7
  56     * Fixed support for MoinMoin 1.5.3
  57     * Fixed SSL support.
  58 
  59     2006-11-14  RaphaelBossek
  60     * Release v2.0.6
  61     * MoinMoin 1.6 support added.
  62     * Fixed Windows(TM) platform support.
  63     * Added support for alternative title text.
  64 
  65     2006-09-13  RaphaelBossek
  66     * Release v2.0.5
  67     * Fixed RedirectOutputRequest class where definition of script_name
  68       was missing.
  69 
  70     2006-09-12  RaphaelBossek
  71     * Release v2.0.4
  72     * Fixed RedirectOutputRequest class where function was redifined
  73       to boolean value.
  74 
  75     2006-09-06  RaphaelBossek
  76     * Release v2.0.3
  77     * Fixed FastCGI support by removing stdout redirect output code. The
  78       same functionality will be done by the RedirectOutputRequest class.
  79     * Renamed to CreatePdfDocument (for better translation possibilities).
  80     * Fixed encoding of title page.
  81     * Added charset set option.
  82     * Fixed waiting for HTMLDOC.
  83 
  84     2006-09-02  RaphaelBossek
  85     * Release v2.0.2
  86     * Added createpdfdocument_validoptions and createpdfdocument_defaultvalues
  87       configuration parameter support. You are not able to preset available
  88       options and which defaults are used in your configuration file.
  89 
  90     2006-08-30  RaphaelBossek
  91     * Release v2.0.1
  92     * Fixed issue with page revision number forwarding (traceback).
  93 
  94     2006-08-30  RaphaelBossek
  95     * Release v2.0.0
  96     * Feature enchanced and bug fixed version.
  97 
  98     2006-05-26  PascalBauermeister
  99     * Release v1.0.2
 100     * Relative image URLs turned absolute was bogus. It is less bogus now.
 101 
 102     2006-05-26  PascalBauermeister
 103     * Release v1.0.1
 104     * Set env var HTMLDOC_NOCGI to solve CGI issue
 105 
 106     2006-05-24  PascalBauermeister
 107     * Initial release v1.0.0
 108 """
 109 
 110 import os
 111 import sys
 112 import stat
 113 import re
 114 import copy
 115 import shutil
 116 import StringIO
 117 import array
 118 from MoinMoin import config
 119 from MoinMoin import util
 120 from MoinMoin import wikiutil
 121 from MoinMoin import packages
 122 from MoinMoin import error
 123 from MoinMoin.Page import Page
 124 from MoinMoin.request import RequestBase
 125 from MoinMoin.widget.dialog import Dialog
 126 from MoinMoin.version import release as moinmoin_release
 127 
 128 # http://www.barelyfitz.com/projects/tabber/
 129 tabber_minimized = '''
 130 // Version 1.9 stripped by Creativyst SS & JavaScript Compressor v2.2c (http://www.creativyst.com/Prod/3/)
 131 function tabberObj(argsObj)
 132 { var arg; this.div = null; this.classMain = "tabber"; this.classMainLive = "tabberlive"; this.classTab = "tabbertab"; this.classTabDefault = "tabbertabdefault"; this.classNav = "tabbernav"; this.classTabHide = "tabbertabhide"; this.classNavActive = "tabberactive"; this.titleElements = ['h2','h3','h4','h5','h6']; this.titleElementsStripHTML = true; this.removeTitle = true; this.addLinkId = false; this.linkIdFormat = '<tabberid>nav<tabnumberone>'; for (arg in argsObj) { this[arg] = argsObj[arg];}
 133 this.REclassMain = new RegExp('\\\\b' + this.classMain + '\\\\b', 'gi'); this.REclassMainLive = new RegExp('\\\\b' + this.classMainLive + '\\\\b', 'gi'); this.REclassTab = new RegExp('\\\\b' + this.classTab + '\\\\b', 'gi'); this.REclassTabDefault = new RegExp('\\\\b' + this.classTabDefault + '\\\\b', 'gi'); this.REclassTabHide = new RegExp('\\\\b' + this.classTabHide + '\\\\b', 'gi'); this.tabs = new Array(); if (this.div) { this.init(this.div); this.div = null;}
 134 }
 135 tabberObj.prototype.init = function(e)
 136 { var
 137 childNodes, i, i2, t, defaultTab=0, DOM_ul, DOM_li, DOM_a, aId, headingElement; if (!document.getElementsByTagName) { return false;}
 138 if (e.id) { this.id = e.id;}
 139 this.tabs.length = 0; childNodes = e.childNodes; for(i=0; i < childNodes.length; i++) { if(childNodes[i].className &&
 140 childNodes[i].className.match(this.REclassTab)) { t = new Object(); t.div = childNodes[i]; this.tabs[this.tabs.length] = t; if (childNodes[i].className.match(this.REclassTabDefault)) { defaultTab = this.tabs.length-1;}
 141 }
 142 }
 143 DOM_ul = document.createElement("ul"); DOM_ul.className = this.classNav; for (i=0; i < this.tabs.length; i++) { t = this.tabs[i]; t.headingText = t.div.title; if (this.removeTitle) { t.div.title = '';}
 144 if (!t.headingText) { for (i2=0; i2<this.titleElements.length; i2++) { headingElement = t.div.getElementsByTagName(this.titleElements[i2])[0]; if (headingElement) { t.headingText = headingElement.innerHTML; if (this.titleElementsStripHTML) { t.headingText.replace(/<br>/gi," "); t.headingText = t.headingText.replace(/<[^>]+>/g,"");}
 145 break;}
 146 }
 147 }
 148 if (!t.headingText) { t.headingText = i + 1;}
 149 DOM_li = document.createElement("li"); t.li = DOM_li; DOM_a = document.createElement("a"); DOM_a.appendChild(document.createTextNode(t.headingText)); DOM_a.href = "javascript:void(null);"; DOM_a.title = t.headingText; DOM_a.onclick = this.navClick; DOM_a.tabber = this; DOM_a.tabberIndex = i; if (this.addLinkId && this.linkIdFormat) { aId = this.linkIdFormat; aId = aId.replace(/<tabberid>/gi, this.id); aId = aId.replace(/<tabnumberzero>/gi, i); aId = aId.replace(/<tabnumberone>/gi, i+1); aId = aId.replace(/<tabtitle>/gi, t.headingText.replace(/[^a-zA-Z0-9\-]/gi, '')); DOM_a.id = aId;}
 150 DOM_li.appendChild(DOM_a); DOM_ul.appendChild(DOM_li);}
 151 e.insertBefore(DOM_ul, e.firstChild); e.className = e.className.replace(this.REclassMain, this.classMainLive); this.tabShow(defaultTab); if (typeof this.onLoad == 'function') { this.onLoad({tabber:this});}
 152 return this;}; tabberObj.prototype.navClick = function(event)
 153 { var
 154 rVal, a, self, tabberIndex, onClickArgs; a = this; if (!a.tabber) { return false;}
 155 self = a.tabber; tabberIndex = a.tabberIndex; a.blur(); if (typeof self.onClick == 'function') { onClickArgs = {'tabber':self, 'index':tabberIndex, 'event':event}; if (!event) { onClickArgs.event = window.event;}
 156 rVal = self.onClick(onClickArgs); if (rVal === false) { return false;}
 157 }
 158 self.tabShow(tabberIndex); return false;}; tabberObj.prototype.tabHideAll = function()
 159 { var i; for (i = 0; i < this.tabs.length; i++) { this.tabHide(i);}
 160 }; tabberObj.prototype.tabHide = function(tabberIndex)
 161 { var div; if (!this.tabs[tabberIndex]) { return false;}
 162 div = this.tabs[tabberIndex].div; if (!div.className.match(this.REclassTabHide)) { div.className += ' ' + this.classTabHide;}
 163 this.navClearActive(tabberIndex); return this;}; tabberObj.prototype.tabShow = function(tabberIndex)
 164 { var div; if (!this.tabs[tabberIndex]) { return false;}
 165 this.tabHideAll(); div = this.tabs[tabberIndex].div; div.className = div.className.replace(this.REclassTabHide, ''); this.navSetActive(tabberIndex); if (typeof this.onTabDisplay == 'function') { this.onTabDisplay({'tabber':this, 'index':tabberIndex});}
 166 return this;}; tabberObj.prototype.navSetActive = function(tabberIndex)
 167 { this.tabs[tabberIndex].li.className = this.classNavActive; return this;}; tabberObj.prototype.navClearActive = function(tabberIndex)
 168 { this.tabs[tabberIndex].li.className = ''; return this;}; function tabberAutomatic(tabberArgs)
 169 { var
 170 tempObj, divs, i; if (!tabberArgs) { tabberArgs = {};}
 171 tempObj = new tabberObj(tabberArgs); divs = document.getElementsByTagName("div"); for (i=0; i < divs.length; i++) { if (divs[i].className &&
 172 divs[i].className.match(tempObj.REclassMain)) { tabberArgs.div = divs[i]; divs[i].tabber = new tabberObj(tabberArgs);}
 173 }
 174 return this;}
 175 function tabberAutomaticOnLoad(tabberArgs)
 176 { var oldOnLoad; if (!tabberArgs) { tabberArgs = {};}
 177 oldOnLoad = window.onload; if (typeof window.onload != 'function') { window.onload = function() { tabberAutomatic(tabberArgs);};} else { window.onload = function() { oldOnLoad(); tabberAutomatic(tabberArgs);};}
 178 }
 179 if (typeof tabberOptions == 'undefined') { tabberAutomaticOnLoad();} else { if (!tabberOptions['manualStartup']) { tabberAutomaticOnLoad(tabberOptions);}
 180 }
 181 '''
 182 
 183 tabber_minimized_css = '''
 184 <style type="text/css">
 185 /*--------------------------------------------------
 186   REQUIRED to hide the non-active tab content.
 187   But do not hide them in the print stylesheet!
 188   --------------------------------------------------*/
 189 .tabberlive .tabbertabhide {
 190  display:none;
 191 }
 192 
 193 /*--------------------------------------------------
 194   .tabber = before the tabber interface is set up
 195   .tabberlive = after the tabber interface is set up
 196   --------------------------------------------------*/
 197 .tabber {
 198 }
 199 .tabberlive {
 200  margin-top:1em;
 201 }
 202 
 203 /*--------------------------------------------------
 204   ul.tabbernav = the tab navigation list
 205   li.tabberactive = the active tab
 206   --------------------------------------------------*/
 207 ul.tabbernav
 208 {
 209  margin:0;
 210  padding: 3px 0;
 211  border-bottom: 1px solid #778;
 212  font: bold 12px Verdana, sans-serif;
 213 }
 214 
 215 ul.tabbernav li
 216 {
 217  list-style: none;
 218  margin: 0;
 219  display: inline;
 220 }
 221 
 222 ul.tabbernav li a
 223 {
 224  padding: 3px 0.5em;
 225  margin-left: 3px;
 226  border: 1px solid #778;
 227  border-bottom: none;
 228  background: #DDE;
 229  text-decoration: none;
 230 }
 231 
 232 ul.tabbernav li a:link { color: #448; }
 233 ul.tabbernav li a:visited { color: #667; }
 234 
 235 ul.tabbernav li a:hover
 236 {
 237  color: #000;
 238  background: #AAE;
 239  border-color: #227;
 240 }
 241 
 242 ul.tabbernav li.tabberactive a
 243 {
 244  background-color: #fff;
 245  border-bottom: 1px solid #fff;
 246 }
 247 
 248 ul.tabbernav li.tabberactive a:hover
 249 {
 250  color: #000;
 251  background: white;
 252  border-bottom: 1px solid white;
 253 }
 254 
 255 /*--------------------------------------------------
 256   .tabbertab = the tab content
 257   Add style only after the tabber interface is set up (.tabberlive)
 258   --------------------------------------------------*/
 259 .tabberlive .tabbertab {
 260  padding:5px;
 261  border:1px solid #aaa;
 262  border-top:0;
 263 
 264  /* If you don't want the tab size changing whenever a tab is changed
 265     you can set a fixed height */
 266 
 267  /* height:200px; */
 268 
 269  /* If you set a fix height set overflow to auto and you will get a
 270     scrollbar when necessary */
 271 
 272  /* overflow:auto; */
 273 }
 274 
 275 /* If desired, hide the heading since a heading is provided by the tab */
 276 .tabberlive .tabbertab h2 {
 277  display:none;
 278 }
 279 .tabberlive .tabbertab h3 {
 280  display:none;
 281 }
 282 
 283 /* Example of using an ID to set different styles for the tabs on the page */
 284 .tabberlive#tab1 {
 285 }
 286 .tabberlive#tab2 {
 287 }
 288 .tabberlive#tab2 .tabbertab {
 289  height:200px;
 290  overflow:auto;
 291 }
 292 </style>
 293 '''
 294 
 295 class RedirectOutputRequest(RequestBase):
 296     """Redirect output to string without HTTP headers."""
 297     def __init__ (self, req, action=u'print'):
 298         """Prepare a compatible request."""
 299         # 1.5,1.6:req.path_info = u'/RaphaelBossek/\xd6nologe' | u'/FrontPage'
 300         # after enconde() self.path_info = '/RaphaelBossek/\xd6nologe'
 301         self.path_info = req.path_info.encode(config.charset)
 302         # 1.5,1.6:query_string = req.query_string = u'action=CreatePdfDocument'
 303         self.query_string = u'action=' + action
 304         # 1.5,1.6:request_uri = req.request_uri = u'/FrontPage?action=CreatePdfDocument'
 305         self.request_uri = req.path_info.replace(req.query_string, self.query_string)
 306         # 1.5,1.6:url = req.url = u'localhost:8080/FrontPage?action=CreatePdfDocument'
 307         self.url = req.url.replace(req.query_string, self.query_string)
 308         # 1.5,1.6: Not all kinds of request support SSL.
 309         if 'is_ssl' in req.__dict__:
 310             self.is_ssl = req.is_ssl
 311         else:
 312             self.is_ssl = 0
 313         # 1.5,1.6: Not all kinds of request set env.
 314         self.env = {}
 315         if 'env' in req.__dict__:
 316             # 1.5,1.6: Do not copy env otherwise UNICODE encoding does not work right.
 317             #self._setup_vars_from_std_env(req.env)
 318             self.env['AUTH_TYPE'] = req.env.get('AUTH_TYPE', '')
 319         self.http_host = req.http_host
 320         self.http_user_agent = req.http_user_agent
 321         self.request_method = None
 322         self.saved_cookie = req.saved_cookie
 323         self.remote_addr = req.remote_addr
 324         self.script_name = getattr (req, u'script_name', u'')
 325 
 326         self.req = req
 327         RequestBase.__init__(self)
 328 
 329     def run(self, rev = None):
 330         """Start processing the document."""
 331         # 1.6:MoinMoin/request/__init__.py: Initialise action from environment variables not from form.
 332         self.action = u'print'
 333         if rev:
 334             self.form[u'rev'] = [rev]
 335         self.output_string = u''
 336         self.error_string = u''
 337         self.sent_headers = False
 338         self.failed = 0
 339         RequestBase.run(self)
 340         return (self.output_string, self.error_string)
 341 
 342     def http_headers (self, *args, **kw):
 343         """Used by MoinMoin 1.5.x instead of emit_http_headers()."""
 344         self.sent_headers = True
 345     
 346     def emit_http_headers(self, *args, **kw):
 347         """Used by MoinMoin 1.6.x instaed of http_headers()."""
 348         self.sent_headers = 1
 349 
 350     def fail (self, err):
 351         """Catch if a error occurs and save the message in our string."""
 352         RequestBase.fail (self, err)
 353         if not self.error_string:
 354             self.error_string = str(err)
 355 
 356     def write (self, *data):
 357         """Catch the document in our output_string."""
 358         if self.sent_headers:
 359             if self.failed:
 360                 self.error_string += data[0]
 361             else:
 362                 self.output_string += data[0]
 363 
 364     def flush(self):
 365         pass
 366 
 367 
 368 def attachment_fsname(attachment, page, request):
 369     """Return location of attament on the file system. current_page is the relative location
 370     where attachment is used.
 371     """
 372     from MoinMoin.action import AttachFile
 373     pagename, filename = AttachFile.absoluteName(attachment, page.page_name)
 374     #self.request.log("attachment_link: url %s pagename %s filename %s" % (url, pagename, filename))
 375     fname = wikiutil.taintfilename(filename)
 376     return AttachFile.getFilename(request, pagename, fname)
 377 
 378 
 379 def shell_quote(parameter):
 380     o = parameter
 381     for c in [u' ', u'(', u')']:
 382         o = o.replace(c, u'\\' + c)
 383     return o
 384 
 385 
 386 def getEditorName(request):
 387     """Return name of the last editor."""
 388     editorname = u''
 389     log = request.page._last_edited(request)
 390     if log:
 391         if request.cfg.show_hosts:
 392             title = " @ %s[%s]" % (log.hostname, log.addr)
 393         else:
 394             title = ""
 395         kind, info = log.getInterwikiEditorData(request)
 396         if kind in ['interwiki', 'email']:
 397             if log._usercache[log.userid].__dict__.get('aliasname', u''):
 398                 editorname = log._usercache[log.userid].aliasname
 399             else:
 400                 editorname = log._usercache[log.userid].name
 401         elif kind == 'ip':
 402             try:
 403                 idx = info.index('.')
 404             except ValueError:
 405                 idx = len(info)
 406             editorname = wikiutil.escape(info[:idx])
 407     return editorname
 408 
 409 
 410 def pipeCommand(cmdstr, input=None):
 411     inp, out, err = os.popen3 (cmdstr, u'b')
 412     try:
 413         if input:
 414             inp.write(input)
 415         inp.close()
 416     except:
 417         pass
 418 
 419     output = out.read()
 420     out.close()
 421 
 422     erroutput = err.read()
 423     err.close()
 424 
 425     if os.name in ['posix', 'mac']:
 426         try:
 427             # REMARK: Otherwise we get <defunct> processes.
 428             os.wait()
 429         except OSError, e:
 430             # 10: No child processes.
 431             if e.errno != 10:
 432                 raise
 433     return (output, erroutput)
 434 
 435 
 436 class CreatePdfDocument:
 437     """Implementation of the PDF document generator."""
 438 
 439     def __init__(self):
 440         self.action_name = self.__class__.__name__
 441         self.pagename = None
 442         self.request = None
 443         self._ = None
 444         self.debug = False
 445         self.msg = None
 446         self.errormsgsent = False
 447         self.default_values = {
 448             'style': u'webpage',
 449             'format': u'pdf13',
 450             'titlefileimage': u'',
 451             'linkstyle': u'underline',
 452             'headerleft': u't',
 453             'headermiddle': u'.',
 454             'headerright': u'D',
 455             'footerleft': u'.',
 456             'footermiddle': u'/',
 457             'footerright': u'.',
 458             'tocheaderleft': u'.',
 459             'tocheadermiddle': u't',
 460             'tocheaderright': u'.',
 461             'tocfooterleft': u'.',
 462             'tocfootermiddle': u'.',
 463             'tocfooterright': u'i',
 464             'bodycolor': u'FFFFFF',
 465             'bodyimage': u'',
 466             'textcolor': u'000000',
 467             'linkcolor': u'0000E0',
 468             'size': u'legal',
 469             'user-password': u'',
 470             'owner-password': u'',
 471             'toclevels': u'3',
 472             'grayscale': u'unchecked',
 473             'title': u'checked',
 474             'duplex': u'unchecked',
 475             'landscape': u'unchecked',
 476             'usersize': u'',
 477             'margintop': u'0.50in',
 478             'marginbottom': u'0.50in',
 479             'marginleft': u'1.00in',
 480             'marginright': u'0.50in',
 481             'no-toc': u'checked',
 482             'no-links': u'checked',
 483             'firstpage': u'p1',
 484             'jpeg': u'0',
 485             'compression': u'0',
 486             'pagemode': u'outline',
 487             'pagelayout': u'single',
 488             'firstpage': u'c1',
 489             'numbered': u'checked',
 490             'encryption': u'unchecked',
 491             'permissioncopy': u'checked',
 492             'permissionprint': u'checked',
 493             'permissionannotate': u'checked',
 494             'permissionmodify': u'checked',
 495             'charset': u'iso-8859-1',
 496             'debug': u'',
 497             'rev': 0,
 498             'extra-titledocnumber': u'',
 499             'extra-titleauthor': u'',
 500             'extra-titlecopyright': u'',
 501             'pageinfo': u'unchecked',
 502             'bodyfont': u'times',
 503             'headingfont': u'helvetica',
 504             'headfootfont': u'helvetica',
 505             'fontsize': u'11.0',
 506             'headfootsize': u'11.0',
 507             'fontspacing': u'1.2',
 508             'embedfonts': u'checked',
 509         }
 510         # We have to know which values are checkboxes within the form. If a key does
 511         # not exists wihtin the form the corresponding checkbox is not checked.
 512         self.form_checkbox = []
 513         for key, value in self.default_values.items():
 514             if value in [u'checked', u'unchecked']:
 515                 self.form_checkbox += [key]
 516         self.contenttype = u'application/pdf'
 517 
 518     def error_msg (self, msg):
 519         """Display error message."""
 520         if not self.errormsgsent:
 521             # Backward compatiblity with MoinMoin 1.5.
 522             if Page.send_page.func_code.co_varnames[1] == "request":
 523                 Page(self.request, self.pagename).send_page(self.request, msg=msg)
 524                 
 525             else:
 526                 Page(self.request, self.pagename).send_page(msg=msg)
 527             self.errormsgsent = True
 528 
 529     def fixhtmlstr(self, str):
 530         """Convert utf-8 encoded multi-byte sequences into &#XXXX; format."""
 531         htmlstr = array.array('c')
 532         for c in str:
 533             if ord(c) >= 128:
 534                 htmlstr.fromstring('&#%d;' % ord(c))
 535             else:
 536                 htmlstr.fromstring(c)
 537         return htmlstr.tostring()
 538 
 539     def set_page_values(self):
 540         """Scan raw page for additional information relating PDF generation."""
 541         #pdflines = False
 542         for line in self.request.page.get_raw_body().split(u'\n'):
 543             if line[:6] == u'##pdf ' and len(line[6:]):
 544                 line = line[6:]
 545                 key = line.split()[0]
 546                 value = line[len(key) + 1:]
 547                 # Only accept known values/settings.
 548                 if key in self.default_values:
 549                     # Check if there are any restrictions for key.
 550                     if key in self.valid_options:
 551                         # Set only the value if the restrictions are confirmed.
 552                         valid_values = self.valid_options[key].keys()
 553                         if value in valid_values:
 554                             self.values[key] = value
 555                     else:
 556                         # There are no restrictions for value.
 557                         self.values[key] = value
 558             elif not line:
 559                 break
 560 
 561     def set_page_default_values(self):
 562         # We are not able to recognise if this string is part of a verbatim area.
 563         matchtoclvl = re.compile(r'^\[\[TableOfContents\(\s*(\d+)\s*\)\]\]')
 564         matchtoc = re.compile(r'^\[\[TableOfContents\(*\)*\]\]')
 565         toc = False
 566         for line in self.request.page.get_raw_body().split(u'\n'):
 567             if line[:10] == u'#language ' and not u'language' in self.values:
 568                 lang = self.make_isolang(line[10:])
 569                 if lang:
 570                     self.default_values[u'language'] = lang
 571             elif not u'toclevels' in self.values and not toc:
 572                 result = matchtoclvl.match(line)
 573                 if result:
 574                     toclevels = int(result.group(1).strip())
 575                     if toclevels > 4:
 576                         toclevels = 4
 577                     self.default_values[u'toclevels'] = str(toclevels)
 578                     toc = True
 579                 elif matchtoc.match(line):
 580                     toc = True
 581         # We assume if table-of-contents is used we intent to generate a book.
 582         if toc:
 583             # Do not change style if set manually or by configuration.
 584             self.default_values[u'style'] = self.default_values.get(u'style', u'book')
 585         # Do not generate a table of contents page.
 586         if self.default_values[u'style'] != u'book':
 587             # Do not change style if set manually or by configuration.
 588             self.default_values[u'no-toc'] = self.default_values.get(u'no-toc', u'unchecked')
 589  
 590     def _select(self, name, description=None):
 591         """Helper function to create a selection control."""
 592         str = u'<select name="%s" size="1">' % (name,)
 593         if not description:
 594             description = self.valid_options[name]
 595         keys = description.keys()
 596         keys.sort()
 597         for value in keys:
 598             if value == self.values[name]:
 599                 selected = u'selected'
 600             else:
 601                 selected = u''
 602             str += u'<option value="%s" %s>%s</option>' % (value, selected, description[value],)
 603         str += u'</select>'
 604         return str
 605 
 606     def _chooseformat(self, name):
 607         """Helper function to create left/middle/right selection controls."""
 608         str = u"""    <tr>
 609         <td class="label"><label>%s</label></td>
 610         <td><table>
 611                 <tr>
 612                     <td>%s</td>
 613                     <td>%s</td>
 614                 </tr>
 615                 <tr>
 616                     <td>%s</td>
 617                     <td>%s</td>
 618                 </tr>
 619                 <tr>
 620                     <td>%s</td>
 621                     <td>%s</td>
 622                 </tr>
 623             </table>
 624         </td>
 625         <td>%s</td>
 626     </tr>""" % (self.fields[u'label_' + name],
 627               self.fields[u'label_left'], self._select(name + u'left', self.valid_options[u'tocformats']),
 628               self.fields[u'label_middle'], self._select(name + u'middle', self.valid_options[u'tocformats']),
 629               self.fields[u'label_right'], self._select(name + u'right', self.valid_options[u'tocformats']),
 630               self.fields[u'help_' + name],)
 631         return str
 632 
 633     def makeform(self, errormsg=u''):
 634         self.fields = {
 635             'error': errormsg,
 636             'pagename': wikiutil.escape(self.pagename),
 637             'action': self.action_name,
 638             'version': __version__,
 639             'moinmoin_release': moinmoin_release,
 640 
 641             'label_input': self._(u'Input'),
 642             'label_output': self._(u'Output'),
 643             'label_page': self._(u'Page'),
 644             'label_tableofcontents': self._(u'Contents'),
 645             'label_pdf': self._(u'PDF'),
 646             'label_security': self._(u'Security'),
 647 
 648             'label_choose_style': self._(u'Choose style'),
 649             'help_choose_style': self._(u'book: Create a structured PDF document with headings, chapters, etc.') + u'<br/>' + \
 650                                  self._(u'webpage: Specifies that the HTML sources are unstructured (plain web pages.) A page break is inserted between each file or URL in the output.') + u'<br/>' + \
 651                                  self._(u'continuous: Specifies that the HTML sources are unstructured (plain web pages.) No page breaks are inserted between each file or URL in the output.'),
 652 
 653             'help_titletext': self._(u'Title of the document for the front page.'),
 654             
 655             'label_titlefileimage': self._(u'Title file/image'),
 656             'help_titlefileimage': self._(u'The title image or HTML page. These file has to be an attachments!'),
 657             
 658             'label_extra-titledocnumber': self._(u'Version'),
 659             'help_extra-titledocnumber': self._(u'Specify document version to be displayed on the title page.'),
 660             
 661             'label_extra-titleauthor': self._(u'Author'),
 662             'help_extra-titleauthor': self._(u'Intellectual property owner of this document.'),
 663             
 664             'label_extra-titlecopyright': self._(u'Copyright'),
 665             'help_extra-titlecopyright': self._(u'Copyright notice for this document.'),
 666             
 667             'label_pageinfo': self._(u'Apply page information'),
 668             'help_pageinfo': self._(u'Information about who and when modified the document are applied at the end.'),
 669             
 670             'label_format': self._(u'Output format'),
 671             'help_format': self._(u'Specifies the output format.'),
 672 
 673             'label_outputoptions': self._(u'Output options'),
 674             'label_grayscale': self._(u'Grayscale document'),
 675             'label_titlepage': self._(u'Title page'),
 676             'label_titletext': self._(u'Title'),
 677             'label_jpeg': self._(u'JPEG big images'),
 678             'label_compression': self._(u'Compression'),
 679 
 680             'label_no-toc': self._(u'Generate a table of contents'),
 681             'help_no-toc': self._(u''),
 682 
 683             'label_toclevels': self._(u'Limit the number of levels in the table-of-contents'),
 684             'help_toclevels': self._(u'Sets the number of levels in the table-of-contents.') + u' ' + self._(u'Empty for unlimited levels.'),
 685 
 686             'label_numbered': self._(u'Numbered headings'),
 687             'help_numbered': self._(u'Check to number all of the headings in the document.'),
 688 
 689             'label_toctitle': self._(u'Table-of-contents title'),
 690             'help_toctitle': self._(u'Sets the title for the table-of-contents.') + u' ' + self._(u'Empty for default title.'),
 691 
 692             'label_left': self._(u'Left'),
 693             'label_middle': self._(u'Middle'),
 694             'label_right': self._(u'Right'),
 695 
 696             'label_tocheader': self._(u'Header of table-of-contantes page'),
 697             'help_tocheader': self._(u'Sets the page header to use on table-of-contents pages.'),
 698 
 699             'label_tocfooter': self._(u'Footer of table-of-contantes page'),
 700             'help_tocfooter': self._(u'Sets the page footer to use on table-of-contents pages.'),
 701 
 702             'label_header': self._(u'Page header'),
 703             'help_header': self._(u'Sets the page header to use on body pages.'),
 704 
 705             'label_footer': self._(u'Page footer'),
 706             'help_footer': self._(u'Sets the page footer to use on body pages.'),
 707 
 708             'label_colors': self._(u'Colors'),
 709             'label_no-links': self._(u'Create HTTP links'),
 710             'help_no-links': self._(u'Enables generation of links in PDF files.'),
 711             
 712             'label_linkstyle': self._(u'Style of HTTP links'),
 713             'help_linkstyle': self._(u''),
 714 
 715             'label_linkcolor': self._(u'HTTP links color'),
 716             'help_linkcolor': self._(u'Sets the color of links.'),
 717             
 718             'label_bodycolor': self._(u'Body color'),
 719             'help_bodycolor': self._(u'Enter the HTML color for the body (background).'),
 720             
 721             'label_bodyimage': self._(u'Body image'),
 722             'help_bodyimage': self._(u'Enter the image file for the body (background). These file has to be an attachments!'),
 723             
 724             'label_textcolor': self._(u'Text color'),
 725             'help_textcolor': self._(u'Enter the HTML color for the text.'),
 726             
 727             'label_duplex': self._(u'2-Sided'),
 728             'help_duplex': self._(u'Specifies that the output should be formatted for double-sided printing.'),
 729 
 730             'label_landscape': self._(u'Landscape'),
 731 
 732             'label_choose_size': self._(u'Choose page size'),
 733             'help_choose_size': self._(u'Choose one of the predefined standard sizes or select user defined.'),
 734 
 735             'label_usersize': self._(u'User defined page size'),
 736             'help_usersize': self._(u'Specifies the page size using a standard name or in points (no suffix or ##x##pt), inches (##x##in), centimeters (##x##cm), or millimeters (##x##mm).'),
 737 
 738             'label_margin': self._(u'User defined margin'),
 739             'label_margintop': self._(u'Top'),
 740             'label_marginbottom': self._(u'Bottom'),
 741             'label_marginleft': self._(u'Left'),
 742             'label_marginright': self._(u'Right'),
 743             'help_margin': self._(u'Specifies the margin size using points (no suffix or ##x##pt), inches (##x##in), centimeters (##x##cm), or millimeters (##x##mm).') + u' ' + self._(u'Keep empty for default value.'),
 744 
 745             'label_pagemode': self._(u'Page mode'),
 746             'help_pagemode': self._(u'Controls the initial viewing mode for the document.') + u'<br/>' + self._(u'Document: Displays only the docuemnt pages.') + u'<br/>' + self._(u'Outline: Display the table-of-contents outline as well as the document pages.') + u'<br/>' + self._(u'Full-screen: Displays pages on the whole screen; this mode is used primarily for presentations.'),
 747 
 748             'label_pagelayout': self._(u'Page layout'),
 749             'help_pagelayout': self._(u'Controls the initial layout of document pages on the screen.') + u'<br/>' + self._(u'Single: Displays a single page at a time.') + u'<br/>' + self._(u'One column: Displays a single column of pages at a time.') + u'<br/>' + self._(u'Two column left/right: Display two columns of pages at a time; the first page is displayed in the left or right column as selected.'),
 750 
 751             'label_firstpage': self._(u'First page'),
 752             'help_firstpage': self._(u'Choose the initial page that will be shown.'),
 753 
 754             'label_encryption': self._(u'Encryption'),
 755             'help_encryptin': self._(u'Enables encryption and security features for PDF output.'),
 756             'label_permissions': self._(u'Permissions'),
 757             'help_permissions': self._(u'Specifies the document permissions.'),
 758 
 759             'label_permissionannotate': self._(u'Annotate'),
 760             'label_permissionprint': self._(u'Print'),
 761             'label_permissionmodify': self._(u'Modify'),
 762             'label_permissioncopy': self._(u'Copy'),
 763 
 764             'label_owner-password': self._(u'Owner password'),
 765             'help_owner-password': self._(u'Specifies the owner password to control who can change document permissions etc.') + u' ' + self._(u'If this field is left blank, a random 32-character password is generated so that no one can change the document.'),
 766 
 767             'label_user-password': self._(u'User password'),
 768             'help_user-password': self._(u'Specifies the user password to restrict viewing permissions on this PDF document.') + u' ' + self._(u'Empty for no encryption.'),
 769 
 770             'label_expert': self._(u'Expert'),
 771             'label_language': self._(u'Language translation'),
 772             'help_language': self._(u'Specify language to use for date and time format.'),
 773 
 774             'label_fonts': self._(u'Fonts'),
 775             'label_fontsize': self._(u'Base font size'),
 776             'help_fontsize': self._(u'Set the default size of text.'),
 777             'label_fontspacing': self._(u'Line spacing'),
 778             'help_fontspacing': self._(u'Set the spacing between lines of text.'),
 779             'label_bodyfont': self._(u'Body typeface'),
 780             'help_bodyfont': self._(u'Choose the default typeface (font) of text.'),
 781             'label_headingfont': self._(u'Heading typeface'),
 782             'help_headingfont': self._(u'Choose the default typeface (font) of headings.'),
 783             'label_headfootsize': self._(u'Header/Footer size'),
 784             'help_headfootsize': self._(u'Set the size of header and footer text.'),
 785             'label_headfootfont': self._(u'Header/Footer font'),
 786             'help_headfootfont': self._(u'Choose the font for header and footer text.'),
 787             'label_charset': self._(u'Charset set'),
 788             'help_charset': self._(u'Change the encoding of the text in document.'),
 789             'label_embedfonts': self._(u'Embed fonts'),
 790             'help_embedfonts': self._(u'Check to embed font in the output file.'),
 791             
 792             'label_about': self._(u'About'),
 793             'copyright': u'',
 794             'version': self._(u'Version') + u' ' + __version__,
 795 
 796             'button_generate': self._(u'Generate PDF'),
 797             'button_remember': self._(u'Remember form'),
 798             'button_cancel': self._(u'Cancel'),
 799             'button_reset': self._(u'Reset'),
 800             }
 801         
 802         self.fields['copyright'] = u"<br/>\n".join(wikiutil.escape(__doc__).split(u"\n"))
 803         self.fields.update(self.values)
 804 
 805         # Status of debug.
 806         if self.debug:
 807             self.fields[u'debug'] = u'1'
 808         else:
 809             self.fields[u'debug'] = u'0'
 810 
 811         # Go through all format strings.
 812         for name in [u'tocheader', u'tocfooter', u'header', u'footer']:
 813             self.fields[u'choose_' + name] = self._chooseformat(name)
 814 
 815         self.fields[u'select_style'] = self._select(u'style')
 816         self.fields[u'select_format'] = self._select(u'format')
 817         self.fields[u'select_linkstyle'] = self._select(u'linkstyle')
 818         self.fields[u'select_size'] = self._select(u'size')
 819         self.fields[u'select_jpeg'] = self._select(u'jpeg')
 820         self.fields[u'select_compression'] = self._select(u'compression')
 821         self.fields[u'select_toclevels'] = self._select(u'toclevels')
 822         self.fields[u'select_pagemode'] = self._select(u'pagemode')
 823         self.fields[u'select_pagelayout'] = self._select(u'pagelayout')
 824         self.fields[u'select_firstpage'] = self._select(u'firstpage')
 825         self.fields[u'select_charset'] = self._select(u'charset')
 826         self.fields[u'select_fontsize'] = self._select(u'fontsize')
 827         self.fields[u'select_bodyfont'] = self._select(u'bodyfont')
 828         self.fields[u'select_headingfont'] = self._select(u'headingfont')
 829         self.fields[u'select_headfootsize'] = self._select(u'headfootsize')
 830         self.fields[u'select_headfootfont'] = self._select(u'headfootfont')
 831         self.fields[u'select_fontspacing'] = self._select(u'fontspacing')
 832 
 833         # Add tabber implementation.
 834         self.request.cfg.html_head += """
 835 <script type="text/javascript">
 836 <!-- //
 837 %s
 838 //-->
 839 </script>
 840 
 841 %s
 842 """ % (tabber_minimized, tabber_minimized_css,)
 843 
 844         form = u''
 845         if self.debug:
 846             form += u'<p class="warning">Debug mode activated.</p>'
 847         if not moinmoin_release[:3] in [u'1.6', u'1.5']:
 848             form += u'<p class="warning">This plugin is not designed for MoinMoin %(moinmoin_release)s.</p>'
 849         form += """
 850 <p class="error">%(error)s</p>
 851 <form method="post" action="">
 852 <input type="hidden" name="action" value="%(action)s"/>
 853 <div class="tabber">
 854 <div class="tabbertab">
 855     <h3>%(label_input)s</h3>
 856     <table>
 857     <tr>
 858         <td class="label"><label>%(label_choose_style)s</label></td>
 859         <td class="content">%(select_style)s</td>
 860         <td>%(help_choose_style)s</td>
 861     </tr>
 862     <tr>
 863         <td class="label"><label>%(label_titletext)s</label></td>
 864         <td class="content"><input type="text" size="30" name="titletext" value="%(titletext)s" /></td>
 865         <td>%(help_titletext)s</td>
 866     </tr>
 867     <tr>
 868         <td class="label"><label>%(label_titlefileimage)s</label></td>
 869         <td class="content"><input type="text" size="30" name="titlefileimage" value="%(titlefileimage)s" /></td>
 870         <td>%(help_titlefileimage)s</td>
 871     </tr>
 872     <tr>
 873         <td class="label"><label>%(label_extra-titledocnumber)s</label></td>
 874         <td class="content"><input type="text" size="30" name="extra-titledocnumber" value="%(extra-titledocnumber)s" /></td>
 875         <td>%(help_extra-titledocnumber)s</td>
 876     </tr>
 877     <tr>
 878         <td class="label"><label>%(label_extra-titleauthor)s</label></td>
 879         <td class="content"><input type="text" size="30" name="extra-titleauthor" value="%(extra-titleauthor)s" /></td>
 880         <td>%(help_extra-titleauthor)s</td>
 881     </tr>
 882     <tr>
 883         <td class="label"><label>%(label_extra-titlecopyright)s</label></td>
 884         <td class="content"><input type="text" size="30" name="extra-titlecopyright" value="%(extra-titlecopyright)s" /></td>
 885         <td>%(help_extra-titlecopyright)s</td>
 886     </tr>
 887     <tr>
 888         <td class="label"><label>%(label_pageinfo)s</label></td>
 889         <td class="checkbox"><input type="checkbox" name="pageinfo" value="checked" %(pageinfo)s /></td>
 890         <td>%(help_pageinfo)s</td>
 891     </tr>
 892     </table>
 893 </div>
 894 <div class="tabbertab">
 895     <h3>%(label_output)s</h3>
 896     <table>
 897     <tr>
 898         <td class="label"><label>%(label_format)s</label></td>
 899         <td class="content">%(select_format)s</td>
 900         <td>%(help_format)s</td>
 901     </tr>
 902     <tr>
 903         <td class="label"><label>%(label_outputoptions)s</label></td>
 904         <td colspan="2"><input type="checkbox" name="grayscale" value="checked" %(grayscale)s />%(label_grayscale)s&nbsp;
 905             <input type="checkbox" name="title" value="checked" %(title)s />%(label_titlepage)s<br />
 906             %(label_compression)s&nbsp:&nbsp;%(select_compression)s&nbsp;
 907             %(label_jpeg)s&nbsp;%(select_jpeg)s</td>
 908     </tr>
 909     </table>
 910 </div>
 911 <div class="tabbertab">
 912     <h3>%(label_page)s</h3>
 913     <table>
 914     <tr>
 915         <td class="label"><label>%(label_choose_size)s</label></td>
 916         <td>%(select_size)s&nbsp;<br /><nobr>%(label_usersize)s&nbsp;<input type="text" size="15" name="usersize" value="%(usersize)s" /></nobr></td>
 917         <td>%(help_choose_size)s<br />%(help_usersize)s</td>
 918     </tr>
 919     <tr>
 920         <td>&nbsp;</td>
 921         <td colspan="2"><input type="checkbox" name="duplex" value="checked" %(duplex)s />&nbsp;%(label_duplex)s&nbsp;
 922             <input type="checkbox" name="landscape" value="checked" %(landscape)s />&nbsp;%(label_landscape)s</td>
 923     </tr>
 924     <tr>
 925         <td class="label"><label>%(label_margin)s</label></td>
 926         <td><table><tr><td>&nbsp;</td><td><nobr><label>%(label_margintop)s</label>&nbsp;<input type="text" name="margintop" value="%(margintop)s" size="7" /></nobr></td><td>&nbsp;</td></tr>
 927             <tr><td><nobr><label>%(label_marginleft)s</label>&nbsp;<input type="text" name="marginleft" value="%(marginleft)s" size="7" /></nobr></td><td>&nbsp;</td><td><nobr><label>%(label_marginright)s</label>&nbsp;<input type="text" name="marginright" value="%(marginright)s" size="7" /></nobr></td></tr>
 928             <tr><td>&nbsp;</td><td><nobr><label>%(label_marginbottom)s</label>&nbsp;<input type="text" name="marginbottom" value="%(marginbottom)s" size="7" /></nobr></td><td>&nbsp;</td></tr></table>
 929         <td>%(help_margin)s</td>
 930     </tr>
 931     %(choose_header)s
 932     %(choose_footer)s
 933     </table>
 934 </div>
 935 <div class="tabbertab">
 936     <h3>%(label_tableofcontents)s</h3>
 937     <table>
 938     <tr>
 939         <td class="label"><label>%(label_no-toc)s</label></td>
 940         <td class="checkbox"><input type="checkbox" name="no-toc" value="checked" %(no-toc)s /></td>
 941         <td>%(help_no-toc)s</td>
 942     </tr>
 943     <tr>
 944         <td class="label"><label>%(label_toclevels)s</label></td>
 945         <td class="content">%(select_toclevels)s</td>
 946         <td>%(help_toclevels)s</td>
 947     </tr>
 948     <tr>
 949         <td>&nbsp;</td>
 950         <td><input type="checkbox" name="numbered" value="checked" %(numbered)s />&nbsp;%(label_numbered)s</td>
 951         <td>%(help_numbered)s</td>
 952     </tr>
 953     <tr>
 954         <td class="label"><label>%(label_toctitle)s</label></td>
 955         <td class="content"><input type="text" size="30" name="toctitle" value="%(toctitle)s" /></td>
 956         <td>%(help_toctitle)s</td>
 957     </tr>
 958     %(choose_tocheader)s
 959     %(choose_tocfooter)s
 960     </table>
 961 </div>
 962 <div class="tabbertab">
 963     <h3>%(label_colors)s</h3>
 964     <table>
 965     <tr>
 966         <td class="label"><label>%(label_bodycolor)s</label></td>
 967         <td class="content"><input type="text" size="6" name="bodycolor" value="%(bodycolor)s" /></td>
 968         <td>%(help_bodycolor)s</td>
 969     </tr>
 970     <tr>
 971         <td class="label"><label>%(label_bodyimage)s</label></td>
 972         <td class="content"><input type="text" size="30" name="bodyimage" value="%(bodyimage)s" /></td>
 973         <td>%(help_bodyimage)s</td>
 974     </tr>
 975     <tr>
 976         <td class="label"><label>%(label_textcolor)s</label></td>
 977         <td class="content"><input type="text" size="6" name="textcolor" value="%(textcolor)s" /></td>
 978         <td>%(help_textcolor)s</td>
 979     </tr>
 980     <tr>
 981         <td class="label"><label>%(label_linkcolor)s</label></td>
 982         <td class="content"><input type="text" size="6" name="linkcolor" value="%(linkcolor)s" /></td>
 983         <td>%(help_linkcolor)s</td>
 984     </tr>
 985     <tr>
 986         <td class="label"><label>%(label_linkstyle)s</label></td>
 987         <td class="content">%(select_linkstyle)s</td>
 988         <td>%(help_linkstyle)s</td>
 989     </tr>
 990     <tr>
 991         <td class="label"><label>%(label_no-links)s</label></td>
 992         <td><input type="checkbox" name="no-links" value="checked" %(no-links)s /></td>
 993         <td>%(help_no-links)s</td>
 994     </tr>
 995     </table>
 996 </div>
 997 <div class="tabbertab">
 998     <h3>%(label_fonts)s</h3>
 999     <table>
1000     <tr>
1001         <td class="label"><label>%(label_fontsize)s</label></td>
1002         <td class="content">%(select_fontsize)s</td>
1003         <td>%(help_fontsize)s</td>
1004     </tr>
1005     <tr>
1006         <td class="label"><label>%(label_fontspacing)s</label></td>
1007         <td class="content">%(select_fontspacing)s</td>
1008         <td>%(help_fontspacing)s</td>
1009     </tr>
1010     <tr>
1011         <td class="label"><label>%(label_bodyfont)s</label></td>
1012         <td class="content">%(select_bodyfont)s</td>
1013         <td>%(help_bodyfont)s</td>
1014     </tr>
1015     <tr>
1016         <td class="label"><label>%(label_headingfont)s</label></td>
1017         <td class="content">%(select_headingfont)s</td>
1018         <td>%(help_headingfont)s</td>
1019     </tr>
1020     <tr>
1021         <td class="label"><label>%(label_headfootsize)s</label></td>
1022         <td class="content">%(select_headfootsize)s</td>
1023         <td>%(help_headfootsize)s</td>
1024     </tr>
1025     <tr>
1026         <td class="label"><label>%(label_headfootfont)s</label></td>
1027         <td class="content">%(select_headfootfont)s</td>
1028         <td>%(help_headfootfont)s</td>
1029     </tr>
1030     <tr>
1031         <td class="label"><label>%(label_charset)s</label></td>
1032         <td class="content">%(select_charset)s</td>
1033         <td>%(help_charset)s</td>
1034     </tr>
1035     <tr>
1036         <td class="label"><label>%(label_embedfonts)s</label></td>
1037         <td class="checkbox"><input type="checkbox" name="embedfonts" value="checked" %(embedfonts)s /></td>
1038         <td>%(help_embedfonts)s</td>
1039     </tr>
1040 </table>
1041 </div>
1042 <div class="tabbertab">
1043     <h3>%(label_pdf)s</h3>
1044     <table>
1045     <tr>
1046         <td class="label"><label>%(label_pagemode)s</label></td>
1047         <td class="content">%(select_pagemode)s</td>
1048         <td>%(help_pagemode)s</td>
1049     </tr>
1050     <tr>
1051         <td class="label"><label>%(label_pagelayout)s</label></td>
1052         <td class="content">%(select_pagelayout)s</td>
1053         <td>%(help_pagelayout)s</td>
1054     </tr>
1055     <tr>
1056         <td class="label"><label>%(label_firstpage)s</label></td>
1057         <td class="content">%(select_firstpage)s</td>
1058         <td>%(help_firstpage)s</td>
1059     </tr>
1060     </table>
1061 </div>
1062 <div class="tabbertab">
1063     <h3>%(label_security)s</h3>
1064     <table>
1065     <tr>
1066         <td class="label"><label>%(label_encryption)s</label></td>
1067         <td><input type="checkbox" name="encryption" value="checked" %(encryption)s /></td>
1068         <td>%(help_numbered)s</td>
1069     </tr>
1070     <tr>
1071         <td class="label"><label>%(label_permissions)s</label></td>
1072         <td><nobr><input type="checkbox" name="permissionprint" value="checked" %(permissionprint)s />&nbsp;%(label_permissionprint)s</nobr>&nbsp;
1073             <nobr><input type="checkbox" name="permissionmodify" value="checked" %(permissionmodify)s />&nbsp;%(label_permissionmodify)s</nobr><br />
1074             <nobr><input type="checkbox" name="permissioncopy" value="checked" %(permissioncopy)s />&nbsp;%(label_permissioncopy)s</nobr>&nbsp;
1075             <nobr><input type="checkbox" name="permissionannotate" value="checked" %(permissionannotate)s />&nbsp;%(label_permissionannotate)s</nobr></td>
1076         <td>%(help_permissions)s</td>
1077     </tr>
1078     <tr>
1079         <td class="label"><label>%(label_user-password)s</label></td>
1080         <td class="content"><input type="password" size="30" name="user-password" value="%(user-password)s" /></td>
1081         <td>%(help_user-password)s</td>
1082     </tr>
1083     <tr>
1084         <td class="label"><label>%(label_owner-password)s</label></td>
1085         <td class="content"><input type="password" size="30" name="owner-password" value="%(owner-password)s" /></td>
1086         <td>%(help_owner-password)s</td>
1087     </tr>
1088     </table>
1089 </div>
1090 <div class="tabbertab">
1091     <h3>%(label_expert)s</h3>
1092     <table>
1093     <tr>
1094         <td class="label"><label>%(label_language)s</label></td>
1095         <td class="content"><input type="text" size="6" name="language" value="%(language)s" /></td>
1096         <td>%(help_language)s</td>
1097     </tr>
1098     </table>
1099 </div>
1100 <div class="tabbertab">
1101     <h3>%(label_about)s</h3>
1102     <p>%(version)s (MoinMoin %(moinmoin_release)s)</p>
1103     <p>%(copyright)s</p>
1104 </div>
1105 </div>
1106 <p>
1107 <input type="hidden" name="debug" value="%(debug)s" /><input type="hidden" name="rev" value="%(rev)s" />
1108 <input type="submit" name="generate_from_form" value="%(button_generate)s" />&nbsp;
1109 <input type="submit" name="remember" value="%(button_remember)s" />&nbsp;
1110 <input type="submit" name="cancel" value="%(button_cancel)s" />&nbsp;
1111 </p>
1112 </form>
1113 """ % self.fields
1114         return Dialog(self.request, content=form)
1115 
1116     def run(self, pagename, request):
1117         """ Main dispatcher for the action."""
1118         self.pagename = pagename
1119         self.request = request
1120         self._ = self.request.getText
1121         self.form = self.request.form
1122         self.cfg = self.request.cfg
1123 
1124         # Canceled by user.
1125         if self.form.has_key(u'cancel'):
1126             # Backward compatiblity with MoinMoin 1.5.
1127             if Page.send_page.func_code.co_varnames[1] == "request":
1128                 return self.request.page.send_page(self.request)
1129             else:
1130                 return self.request.page.send_page()
1131 
1132         # Determine calling parameters.
1133         if self.form.get(u'debug', [u'0']) == [u'1']:
1134             self.debug = True
1135 
1136         # This dict contains all possible values.
1137         self.valid_options = {}
1138 
1139         self.valid_options[u'tocformats'] = {
1140             u'/': self._(u'1/N,2/N Arabic page numbers'),
1141             u':': self._(u'1/C,2/C Arabic chapter page numbers'),
1142             u'1': self._(u'1,2,3,...'),
1143             u'a': self._(u'a,b,c,...'),
1144             u'A': self._(u'A,B,C,...'),
1145             u'c': self._(u'Chapter title'),
1146             u'C': self._(u'Chapter page number'),
1147             u'd': self._(u'Date'),
1148             u'D': self._(u'Date + Time'),
1149             u'h': self._(u'Heading'),
1150             u'i': self._(u'i,ii,iii,iv,...'),
1151             u'I': self._(u'I,II,III,IV,...'),
1152             u't': self._(u'Title'),
1153             u'T': self._(u'Time'),
1154             u'.': self._(u'Blank'),
1155             # TODO: Not supported yet; u'l': self._(u'Logo image'),
1156         }
1157         self.valid_options[u'style'] = {
1158             u'webpage': self._(u'webpage'),
1159             u'book': self._(u'book'),
1160             u'continuous': self._(u'continuous'),
1161         }
1162         self.valid_options[u'size'] = {
1163             u'legal': self._(u'Legal (8.5x14in)'),
1164             u'a4': self._(u'A4 (210x297mm)'),
1165             u'letter': self._(u'Letter (8.5x11in)'),
1166             u'universal': self._(u'Universal (8.27x11in)'),
1167             u'': self._(u'User defined'),
1168         }
1169         self.valid_options[u'format'] = {
1170             u'pdf11': self._(u'PDF 1.1 (Acrobat 2.0)'),
1171             u'pdf12': self._(u'PDF 1.2 (Acrobat 3.0)'),
1172             u'pdf13': self._(u'PDF 1.3 (Acrobat 4.0)'),
1173             u'pdf14': self._(u'PDF 1.4 (Acrobat 5.0)'),
1174             # TODO: Not supported yet:
1175             #u'ps1': self._(u'PostScript Level 1'),
1176             #u'ps2': self._(u'PostScript Level 2'),
1177             #u'ps3': self._(u'PostScript Level 3'),
1178         }
1179         self.valid_options[u'linkstyle'] = {
1180             u'underline': self._(u'Underline'),
1181             u'plain': self._(u'Plain'),
1182         }
1183         self.valid_options[u'firstpage'] = {
1184             u'c1': self._(u'1st chapter'),
1185             u'p1': self._(u'1st page'),
1186             u'toc': self._(u'Contents'),
1187         }
1188         self.valid_options[u'jpeg'] = {
1189             u'0': self._(u'None'),
1190             u'50': self._(u' 50% (Good)'),
1191             u'55': u'55%', u' 60': u' 60%', u' 65': ' 65%', u' 70': ' 70%', u' 75': ' 75%',
1192             u'80': ' 80%', u' 85': ' 85%', u' 90': ' 90%', u' 95': ' 95%',
1193             u'100': self._(u'100% (Best)'),
1194         }
1195         self.valid_options[u'compression'] = {
1196             u'0': self._(u'None'),
1197             u'1': self._(u'1 (Fast)'),
1198             u'2': u'2', u'3': u'3', u'4': u'4', u'5': u'5', u'6': u'6', u'7': u'7', u'8': u'8',
1199             u'9': self._(u'9 (Best)'),
1200         }
1201         self.valid_options[u'toclevels'] = {
1202             u'0': self._(u'None'),
1203             u'1': u'1', u'2': '2', u'3': '3', u'4': '4'
1204         }
1205         self.valid_options[u'pagemode'] = {
1206             u'outline': self._(u'Outline'),
1207             u'document': self._(u'Document'),
1208             u'fullscreen': self._(u'Full-screen'),
1209         }
1210         self.valid_options[u'pagelayout'] = {
1211             u'single': self._(u'Single'),
1212             u'one': self._(u'One column'),
1213             u'twoleft': self._(u'Two column left'),
1214             u'tworight': self._(u'Two column right'),
1215         }
1216         self.valid_options[u'charset'] = {
1217             u'iso-8859-1': self._(u'ISO 8859-1'),
1218             u'iso-8859-2': self._(u'ISO 8859-2'),
1219             u'iso-8859-3': self._(u'ISO 8859-3'),
1220             u'iso-8859-4': self._(u'ISO 8859-4'),
1221             u'iso-8859-5': self._(u'ISO 8859-5'),
1222             u'iso-8859-6': self._(u'ISO 8859-6'),
1223             u'iso-8859-7': self._(u'ISO 8859-7'),
1224             u'iso-8859-8': self._(u'ISO 8859-8'),
1225             u'iso-8859-9': self._(u'ISO 8859-9'),
1226             u'iso-8859-14': self._(u'ISO 8859-14'),
1227             u'iso-8859-15': self._(u'ISO 8859-15'),
1228             u'cp-874': self._(u'cp-847'),
1229             u'cp-1250': self._(u'cp-1250'),
1230             u'cp-1251': self._(u'cp-1251'),
1231             u'cp-1252': self._(u'cp-1252'),
1232             u'cp-1253': self._(u'cp-1253'),
1233             u'cp-1254': self._(u'cp-1254'),
1234             u'cp-1255': self._(u'cp-1255'),
1235             u'cp-1256': self._(u'cp-1256'),
1236             u'cp-1257': self._(u'cp-1257'),
1237             u'cp-1258': self._(u'cp-1258'),
1238             u'koi-8r': self._(u'koi-8r'),
1239         }
1240         self.valid_options[u'bodyfont'] = {
1241             u'courier': self._(u'Courier'),
1242             u'helvetica': self._(u'Helvetica'),
1243             u'monospace': self._(u'Monospace'),
1244             u'sans': self._(u'Sans'),
1245             u'serif': self._(u'Serif'),
1246             u'times': self._(u'Times'),
1247         }
1248         self.valid_options[u'headingfont'] = self.valid_options[u'bodyfont']
1249         self.valid_options[u'headfootfont'] = self.valid_options[u'bodyfont']
1250         # Go through all font types and create fontname{-bold,-oblique,-boldoblique} entries.
1251         for fontname in self.valid_options[u'bodyfont'].keys():
1252             for fontstyle in [u'bold', u'oblique', u'boldoblique']:
1253                 self.valid_options[u'headfootfont'][fontname + u'-' + fontstyle] = u'%s (%s)' % (self.valid_options[u'headfootfont'][fontname], self._(fontstyle),)
1254         # Set possible font sizes.
1255         self._set_fontsize(u'headfootsize', 6, 24, 5)
1256         self._set_fontsize(u'fontsize', 4, 24, 5)
1257         self._set_fontsize(u'fontspacing', 1, 3, 1)
1258 
1259         # Set translated name of table of contents as default.
1260         self.default_values[u'toctitle'] = self._(u'Contents')
1261         
1262         self.default_values[u'titletext'] = self.pagename
1263         self.default_values[u'extra-titledocnumber'] = u'%d' % self.request.page.get_rev()[1]
1264         page_editor = self.request.page.lastEditInfo().get(u'editor', u'')
1265         self.default_values[u'extra-titleauthor'] = wikiutil.escape(getEditorName(self.request))
1266         
1267         # Make sure we create date and time strings in right format.
1268         if self.request.current_lang:
1269             self.default_values[u'language'] = self.request.current_lang
1270         elif self.request.page.language:
1271             self.default_values[u'language'] = self.request.page.language
1272         else:
1273             #self.cfg.language_default or "en"
1274             self.default_values[u'language'] = self.make_isolang(self.cfg.__dict__.get(u'default_language', u'en'))
1275 
1276         self.values = {}
1277 
1278         # If the configuration variable 'createpdfdocument_validoptions' exists we update our
1279         # self.valid_options dict with these values.
1280         if getattr (self.request.cfg, u'createpdfdocument_validoptions', None):
1281             self.valid_options.update (self.request.cfg.createpdfdocument_validoptions)
1282 
1283         # If the configuration variable 'createpdfdocument_defaultvalues' exists we update our
1284         # self.default_values dict with these values.
1285         if getattr (self.request.cfg, u'createpdfdocument_defaultvalues', None):
1286             for key, value in self.request.cfg.createpdfdocument_defaultvalues.items():
1287                 self.default_values[key] = value
1288         
1289         # Scan page to extract default values.
1290         self.set_page_default_values()
1291 
1292         # Create a PDF document direct without any user iteraction from default and page settings.
1293         if self.form.has_key(u'generate'):
1294             self.set_page_values()
1295             self.update_values(useform=False)
1296             return self.do_generate()
1297 
1298         # Create a PDF document from form settings.
1299         if self.form.has_key(u'generate_from_form'):
1300             self.update_values()
1301             return self.do_generate()
1302 
1303         if self.form.has_key(u'remember'):
1304             self.update_values()
1305             return self.do_remember()
1306 
1307         self.set_page_values()
1308         self.update_values(useform=False)
1309         # Backward compatiblity with MoinMoin 1.5.
1310         if Page.send_page.func_code.co_varnames[1] == "request":
1311             return self.request.page.send_page(self.request, msg=self.makeform())
1312         else:
1313             return self.request.page.send_page(msg=self.makeform())
1314 
1315     def update_values(self, useform=True):
1316         """Preset values with they form values or defaults."""
1317         for key, default in self.default_values.items():
1318             # Modify value only if not already set.
1319             if not key in self.values:
1320                 # If the form does not contain the value (e.g. for checkboxes) set the
1321                 # default value (e.g. for checkboxes unset by default).
1322                 if not key in self.form:
1323                     # Special processing for checkboxes in forms. If the key does not exists
1324                     # within the form it is not checked.
1325                     if key in self.form_checkbox and useform:
1326                         self.values[key] = u'unchecked'
1327                     elif useform:
1328                         # Edit fields are missing if they are empty.
1329                         self.values[key] = u''
1330                     else:
1331                         self.values[key] = default
1332                 else:
1333                     self.values[key] = self.form[key][0]
1334         # Check if revision is an integer value.
1335         try:
1336             self.values[u'rev'] = int(self.values.get(u'rev', self.request.page.rev))
1337         except:
1338             self.values[u'rev'] = self.request.page.rev
1339         # Check if page revision exists.
1340         (pagefname, realrev, exists) = self.request.page.get_rev(rev=self.values[u'rev'])
1341         if exists:
1342             self.values[u'rev'] = realrev
1343         else:
1344             # Determine latest revision number.
1345             (pagefname, self.values[u'rev'], exists) = self.request.page.get_rev()
1346 
1347     def do_generate(self):
1348         """Create PDF document."""
1349         # Generate the HTML page using MoinMoin wiki engine.
1350         html = self.get_html()
1351         if html:
1352             pdfdata = self.html2pdf(html)
1353             if pdfdata:
1354                 # Send as application/pdf the generated file by HTMLDOC
1355                 self.send_pdf(pdfdata)
1356                 
1357                 # MoinMoin1.6: send_closing_html() has to be called explicit.
1358                 # MoinMoin1.5: raise MoinMoinNoFooter exception to forbit creation of HTML footer.
1359                 if not 'send_closing_html' in self.request.theme.__dict__:
1360                     from MoinMoin.util import MoinMoinNoFooter
1361                     raise MoinMoinNoFooter
1362 
1363     def do_remember(self):
1364         """Create a message containing information about how to save the form values for future reuse."""
1365         save = u''
1366         for key, value in self.values.items():
1367             if key in [u'user-password', u'owner-password', u'rev', u'debug']:
1368                 continue
1369             if key in self.default_values and value == self.default_values[key]:
1370                 continue
1371             save += u'##pdf %s %s' % (key, value,)
1372             if self.debug:
1373                 if key in self.default_values:
1374                     save += u' <-- default value is "%s" (without quotes)' % self.default_values[key]
1375                 else:
1376                     save += u' <-- keyword missing in defaults'
1377             save += u'\n'
1378         if save:
1379             msg = self._(u'Add follwing lines at the beginning of your page:') + u'<br/><pre>' + save + u'</pre>'
1380         else:
1381             msg = self._(u'All values correspond to they default. Nothing have to be saved.')
1382         # Backward compatiblity with MoinMoin 1.5.
1383         if Page.send_page.func_code.co_varnames[1] == "request":
1384             return self.request.page.send_page(self.request, msg)
1385         else:
1386             return self.request.page.send_page(msg)
1387 
1388     def send_pdf (self, data):
1389         """Send PDF file to HTTP server."""
1390         filename = self.pagename.replace (u'/', u'-') + u'-v' + str(self.values[u'rev']) + u'.pdf'
1391 
1392         # Send HTTP header.
1393         self.request.http_headers([
1394             'Content-Type: %s' % self.contenttype,
1395             'Content-Length: %d' % len(data),
1396             # TODO: fix the encoding here, plain 8 bit is not allowed
1397             # according to the RFCs There is no solution that is
1398             # compatible to IE except stripping non-ascii chars
1399             'Content-Disposition: inline; filename="%s"' % filename.encode(config.charset),
1400             ])
1401 
1402         # Send binary data.
1403         sio = StringIO.StringIO(data)
1404         shutil.copyfileobj(sio, self.request, 8192)
1405 
1406     def get_html(self):
1407         """Generate the HTML body of this page."""
1408         # Save page as HTML.
1409         newreq = RedirectOutputRequest(self.request)
1410         # Do not add edit information.
1411         # Add extra meta tags.
1412         orig_html_head = self.request.cfg.html_head
1413         self.request.cfg.html_head = self.request.cfg.html_head + u"""
1414 <meta name="docnumber" content="%s">
1415 <meta name="author" content="%s">
1416 <meta name="copyright" content="%s">
1417 """ % (wikiutil.escape(self.values['extra-titledocnumber']), wikiutil.escape(self.values['extra-titleauthor']), wikiutil.escape(self.values['extra-titlecopyright']),)
1418         (html, errmsg) = newreq.run(rev = self.values.get(u'rev', None))
1419         # Restore original HTML head configuration.
1420         self.request.cfg.html_head = orig_html_head
1421         if html:
1422             html = self.fixhtmlstr(html)
1423             # Make URLs absolute.
1424             # FIXME: Until MoinMoin is not XHTML compilant we can not use a XML parser
1425             # (e.g. expat) to transform the HTML document. In the meantime we try to
1426             # achive the same with regular expressions subtitution.
1427             base = self.request.getQualifiedURL()
1428             for htmlref in [u'src', u'href']:
1429                 reurlref = r'(%s=[\'"])(/[^\'"]*)[\'"]' % (htmlref,)
1430                 urlref = re.compile (reurlref, re.I)
1431                 for match in urlref.finditer(html):
1432                     foundref = match.groups()
1433                     html = html.replace (foundref[0] + foundref[1], foundref[0] + base + foundref[1])
1434             # Rename title of the document.
1435             titletext_html = self.fixhtmlstr(wikiutil.escape(self.values['titletext']))
1436             html = re.compile(r'<title>[^<]+</title>').sub(u'<title>%s</title>' % titletext_html, html)
1437             if self.values[u'pageinfo'] == u'unchecked':
1438                 # Remove pageinfo by regex. There is no standard way to do that yet.
1439                 # Read the comment in ThemeBase.shouldShowPageinfo().
1440                 html = re.compile(r'<p[^>]+id="pageinfo".*</p>').sub(u'', html)
1441         else:
1442             self.error_msg(self._(u'Could not redirect HTML output for further processing:') + errmsg)
1443 
1444         return html
1445 
1446     def make_isolang (self, language):
1447         return language + u'_' + language.upper()
1448 
1449     def html2pdf (self, html):
1450         """Create a PDF document based on the current parameters."""
1451         # Not all os support environment variable definition in one line with the calling application.
1452         if os.name in ['posix', 'mac']:
1453             htmldocopts = [u'LANG=' + self.values[u'language'], u'HTMLDOC_NOCGI=1']
1454         else:
1455             htmldocopts = []
1456         # Determine UID to access ACL protected sites too (mandatory to download attached images).
1457         htmldocopts += [u'htmldoc', "--cookies", "MOIN_ID=" + self.request.user.id, u'--no-duplex']
1458 
1459         for key in [u'header', u'footer', u'tocheader', u'tocfooter']:
1460             self.values[key] = self.values.get(key + u'left', u'.') + self.values.get(key + u'middle', u'.') + self.values.get(key + u'right', u'.')
1461 
1462         permissions = []
1463         for opt, value in self.values.items():
1464             # Skip alle non-HTMLDOC configuration parameters.
1465             if opt in [u'language', u'debug', u'rev', u'titletext', u'pageinfo'] or opt[:6] == u'extra-':
1466                 continue
1467             
1468             # Skip options without values.
1469             value = value.strip()
1470             if not value:
1471                 continue
1472             
1473             # Skip options for header/footer configuration which differenciate between position (e.g. footerright or tocheadermiddle)
1474             if opt[:6] in [u'header', u'footer'] and opt[6:] or opt[:9] in [u'tocheader', u'tocfooter'] and opt[9:]:
1475                 continue
1476             
1477             if opt == u'titlefileimage':
1478                 # Check if we have a --titlefile or --titleimage option.
1479                 lower_value = value.lower()
1480                 dotpos = lower_value.rfind(u'.')
1481                 if lower_value[dotpos:] in [u'.bmp', u'.gif', u'.jpg', u'.jpeg', u'.png']:
1482                     opt = u'titleimage'
1483                 else:
1484                     opt = u'titlefile'
1485                 value = attachment_fsname(value, self.request.page, self.request)
1486             elif opt == u'bodyimage':
1487                 value = attachment_fsname(value, self.request.page, self.request)
1488             
1489             if opt in [u'style']:
1490                 htmldocopts += [u'--' + value]
1491             elif opt in self.form_checkbox:
1492                 if value == u'checked':
1493                     if opt[:10] == u'permission':
1494                         permissions += [opt[10:]]
1495                     # Reverse meaning of 'no-' options.
1496                     elif opt[:3] != u'no-':
1497                         htmldocopts += [u'--' + opt]
1498                 elif opt[:3] == u'no-':
1499                     htmldocopts += [u'--' + opt]
1500             elif opt[:6] == u'margin':
1501                 htmldocopts += [u'--' + opt[6:], value]
1502             else:
1503                 htmldocopts += [u'--' + opt, value]
1504         if permissions:
1505             htmldocopts += [u'--permission', u','.join (permissions)]
1506         htmldocopts += [u'-']
1507         # Do not forget to escape all spaces!
1508         eschtmldocopts = [shell_quote(arg) for arg in htmldocopts]
1509         cmdstr = u' '.join(eschtmldocopts)
1510         errmsg = None
1511 
1512         pdf = None
1513         if self.debug:
1514             self.request.http_headers()
1515             errmsg = self._(u'HTMLDOC command:') + u'<pre>' + wikiutil.escape(cmdstr) + u'</pre>'
1516             (htmldoc_help, htmldoc_err) = pipeCommand(u'HTMLDOC_NOCGI=1 htmldoc --help')
1517             errmsg += u'<p><pre>%s</pre></p>' % wikiutil.escape(htmldoc_help)
1518             if 'env' in self.request.__dict__:
1519                 reqenv = u'%s' % wikiutil.escape(self.request.env)
1520             else:
1521                 reqenv = u'None'
1522             errmsg += u'<p>MoinMoin release %s<br/>self.request = %s<br/>self.request.env = %s</p>' % (wikiutil.escape(moinmoin_release), wikiutil.escape(type(self.request)), reqenv,)
1523             errmsg += u'<hr/><hr/><hr/>'
1524         else:
1525             (pdf, htmldocmsg) = pipeCommand(cmdstr, html)
1526 
1527             # Check for error message on STDOUT.
1528             if pdf[:8] == u'HTMLDOC ':
1529                 htmldocmsg += pdf
1530                 pdf = None
1531 
1532             if htmldocmsg:
1533                 errmsg = self._(u'Command:') + u'<pre>' + wikiutil.escape(cmdstr) + u'</pre>' + self._('returned:') + u'<pre>' + \
1534                       wikiutil.escape(htmldocmsg).replace(u'\n', u'<br/>') + u'</pre>'
1535 
1536         # As it is difficult to get the htmldoc return code, we check for
1537         # error by checking the produced pdf length
1538         if not pdf and errmsg:
1539             if self.debug:
1540                 self.request.write(u'<html><body>%s</body></hftml>' % errmsg)
1541                 self.request.write(html)
1542             else:
1543                 self.error_msg(errmsg)
1544         elif pdf[:4] != '%PDF':
1545             self.error_msg(self._(u'Invalid PDF document generated') + wikiutil.escape(pdf[:80]))
1546             pdf = None
1547         
1548         return pdf
1549 
1550     def _set_fontsize(self, key, min, max, smallstep):
1551         self.valid_options[key] = {}
1552         for fontsize_big in range(min, max):
1553             for fontsize_step in range(0, 10, smallstep):
1554                 fontsize = u'%d.%d' % (fontsize_big, fontsize_step,)
1555                 self.valid_options[key][fontsize] = self._(fontsize)
1556         self.valid_options[key][u'%d.0' % max] = self._(u'%d.0' % max)
1557 
1558 
1559 def execute (pagename, request):
1560     try:
1561         CreatePdfDocument().run (pagename = pagename, request = request)
1562     except:
1563         raise
1564 
1565 # vim:ts=4:et:sw=4:nu

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.
  • [get | view] (2011-04-14 07:28:03, 4.7 KB) [[attachment:CreateNewPage.py]]
  • [get | view] (2011-04-14 07:26:24, 4.2 KB) [[attachment:CreateNewPage1.6.py]]
  • [get | view] (2006-09-10 21:29:29, 40.4 KB) [[attachment:CreatePdfDocument2_0_3.py]]
  • [get | view] (2006-09-12 06:05:06, 40.5 KB) [[attachment:CreatePdfDocument2_0_4.py]]
  • [get | view] (2006-09-12 12:00:09, 40.6 KB) [[attachment:CreatePdfDocument2_0_5.py]]
  • [get | view] (2006-11-14 21:56:11, 43.5 KB) [[attachment:CreatePdfDocument2_0_6.py]]
  • [get | view] (2006-11-15 17:00:47, 43.8 KB) [[attachment:CreatePdfDocument2_0_7.py]]
  • [get | view] (2006-11-16 22:06:18, 43.8 KB) [[attachment:CreatePdfDocument2_0_8.py]]
  • [get | view] (2006-12-17 15:54:21, 43.6 KB) [[attachment:CreatePdfDocument2_0_9.py]]
  • [get | view] (2007-08-20 09:10:23, 67.2 KB) [[attachment:CreatePdfDocument2_1_0.py]]
  • [get | view] (2007-08-21 07:39:49, 67.1 KB) [[attachment:CreatePdfDocument2_1_1.py]]
  • [get | view] (2007-09-11 19:16:37, 67.3 KB) [[attachment:CreatePdfDocument2_1_2.py]]
  • [get | view] (2007-09-18 20:17:58, 68.1 KB) [[attachment:CreatePdfDocument2_1_3.py]]
  • [get | view] (2007-09-21 13:32:54, 71.1 KB) [[attachment:CreatePdfDocument2_1_4.py]]
  • [get | view] (2007-09-23 20:56:30, 73.4 KB) [[attachment:CreatePdfDocument2_1_5.py]]
  • [get | view] (2007-09-25 20:54:48, 74.5 KB) [[attachment:CreatePdfDocument2_2_0.py]]
  • [get | view] (2008-06-23 21:08:49, 77.0 KB) [[attachment:CreatePdfDocument2_3_0.py]]
  • [get | view] (2008-06-26 19:25:07, 81.0 KB) [[attachment:CreatePdfDocument2_3_1.py]]
  • [get | view] (2008-07-06 05:50:38, 83.1 KB) [[attachment:CreatePdfDocument2_3_2.py]]
  • [get | view] (2008-07-09 17:42:02, 83.3 KB) [[attachment:CreatePdfDocument2_3_3.py]]
  • [get | view] (2008-09-07 11:11:01, 83.5 KB) [[attachment:CreatePdfDocument2_3_4.py]]
  • [get | view] (2009-01-11 15:53:09, 84.3 KB) [[attachment:CreatePdfDocument2_3_5.py]]
  • [get | view] (2009-02-16 06:52:06, 84.2 KB) [[attachment:CreatePdfDocument2_3_6.py]]
  • [get | view] (2010-01-29 11:53:21, 82.8 KB) [[attachment:CreatePdfDocument2_4_0.py]]
  • [get | view] (2010-01-31 14:10:03, 84.6 KB) [[attachment:CreatePdfDocument2_4_1.py]]
  • [get | view] (2010-09-18 16:23:23, 85.6 KB) [[attachment:CreatePdfDocument2_4_2.py]]
  • [get | view] (2006-06-16 20:56:53, 4.9 KB) [[attachment:FlashManager.py-1.5.3-1]]
  • [get | view] (2003-12-07 18:15:53, 3.9 KB) [[attachment:HTML2MoinMoin.py]]
  • [get | view] (2005-10-16 08:24:35, 4.9 KB) [[attachment:HelpOn-1.3.5-4.py]]
  • [get | view] (2006-02-03 19:21:04, 4.9 KB) [[attachment:HelpOn-1.5.1-5.py]]
  • [get | view] (2006-07-04 10:45:22, 4.8 KB) [[attachment:HelpOn-1.5.4-6.py]]
  • [get | view] (2006-07-04 22:39:14, 4.8 KB) [[attachment:HelpOn-1.6.0-7.py]]
  • [get | view] (2006-07-06 13:50:17, 4.0 KB) [[attachment:HelpOn-1.6.0-8.py]]
  • [get | view] (2008-01-10 17:43:24, 4.8 KB) [[attachment:HelpOn-1.6.0-9.py]]
  • [get | view] (2008-08-19 14:44:54, 5.0 KB) [[attachment:HelpOn-1.7.1-10.py]]
  • [get | view] (2005-02-20 18:28:34, 10.8 KB) [[attachment:IRSS.py]]
  • [get | view] (2005-03-09 22:46:23, 2.9 KB) [[attachment:ImportHtml-1.2.py]]
  • [get | view] (2003-12-07 18:15:53, 2.8 KB) [[attachment:ImportHtml.py]]
  • [get | view] (2003-12-07 18:15:53, 1.8 KB) [[attachment:IrcChat.py]]
  • [get | view] (2008-06-09 11:27:20, 4.4 KB) [[attachment:MoinCrypt.py]]
  • [get | view] (2010-11-29 12:08:27, 7.5 KB) [[attachment:PageActions.py]]
  • [get | view] (2006-08-07 15:12:19, 0.5 KB) [[attachment:PermanentLink.py]]
  • [get | view] (2003-12-07 18:15:53, 6.3 KB) [[attachment:PhoneDial.py]]
  • [get | view] (2005-04-17 14:21:47, 3.6 KB) [[attachment:RecommendPage-1.3.4-1.py]]
  • [get | view] (2005-04-19 18:21:52, 5.5 KB) [[attachment:RecommendPage-1.3.4-2.py]]
  • [get | view] (2005-05-02 19:53:09, 5.6 KB) [[attachment:RecommendPage-1.3.4-3.py]]
  • [get | view] (2005-09-03 07:33:35, 6.3 KB) [[attachment:RecommendPage-1.3.4-4.py]]
  • [get | view] (2005-09-05 17:44:03, 6.9 KB) [[attachment:RecommendPage-1.3.5-5.py]]
  • [get | view] (2005-09-07 16:42:26, 7.5 KB) [[attachment:RecommendPage-1.3.5-6.py]]
  • [get | view] (2005-09-08 16:06:28, 7.7 KB) [[attachment:RecommendPage-1.3.5-7.py]]
  • [get | view] (2005-11-01 11:31:51, 9.0 KB) [[attachment:RecommendPage-1.3.5-8.py]]
  • [get | view] (2006-02-03 19:40:51, 8.3 KB) [[attachment:RecommendPage-1.5.1-9.py]]
  • [get | view] (2008-01-11 09:14:35, 6.8 KB) [[attachment:RecommendPage-1.6.0-10.py]]
  • [get | view] (2008-08-19 14:44:59, 6.9 KB) [[attachment:RecommendPage-1.7.1-11.py]]
  • [get | view] (2008-06-09 11:27:40, 1.7 KB) [[attachment:ShowActions.py]]
  • [get | view] (2008-06-09 10:34:02, 5.3 KB) [[attachment:ShowDecrypted.py]]
  • [get | view] (2005-03-30 21:17:28, 7.7 KB) [[attachment:Slideshow.py]]
  • [get | view] (2004-02-02 20:48:31, 2.0 KB) [[attachment:SubscribeUser.py]]
  • [get | view] (2007-01-26 17:08:30, 2.2 KB) [[attachment:Subscribers-1.6.0.py]]
  • [get | view] (2003-12-07 18:15:53, 1.8 KB) [[attachment:Subscribers.py]]
  • [get | view] (2006-03-18 23:16:51, 0.8 KB) [[attachment:UserPreferences.py]]
  • [get | view] (2004-01-05 09:56:25, 8.1 KB) [[attachment:VisualSiteMap.py]]
  • [get | view] (2015-08-30 21:04:23, 11.1 KB) [[attachment:VisualSiteMap_1.10.py]]
  • [get | view] (2004-10-08 10:59:16, 9.3 KB) [[attachment:VisualSiteMap_1.2.py]]
  • [get | view] (2005-03-16 01:30:09, 9.8 KB) [[attachment:VisualSiteMap_1.3.py]]
  • [get | view] (2014-08-19 01:34:10, 10.8 KB) [[attachment:VisualSiteMap_1.9.py]]
  • [get | view] (2007-08-18 18:52:55, 1.0 KB) [[attachment:backlink.py]]
  • [get | view] (2007-03-15 05:53:49, 23.5 KB) [[attachment:findandreplace0.1Beta.py]]
  • [get | view] (2005-03-27 20:32:10, 3.6 KB) [[attachment:gallery2image-1.3.3-1.py]]
  • [get | view] (2005-08-03 20:14:56, 4.0 KB) [[attachment:gallery2image-1.3.3-2.py]]
  • [get | view] (2005-11-13 18:10:26, 20.7 KB) [[attachment:gallery2image-1.3.5-10.py]]
  • [get | view] (2005-11-25 22:03:50, 20.8 KB) [[attachment:gallery2image-1.3.5-11.py]]
  • [get | view] (2005-08-08 17:23:43, 8.4 KB) [[attachment:gallery2image-1.3.5-4.py]]
  • [get | view] (2005-08-13 15:15:45, 13.7 KB) [[attachment:gallery2image-1.3.5-5.py]]
  • [get | view] (2005-08-31 22:05:22, 15.5 KB) [[attachment:gallery2image-1.3.5-6.py]]
  • [get | view] (2005-10-29 20:23:50, 15.9 KB) [[attachment:gallery2image-1.3.5-8.py]]
  • [get | view] (2005-11-01 11:31:24, 17.6 KB) [[attachment:gallery2image-1.3.5-9.py]]
  • [get | view] (2006-01-27 20:52:32, 20.9 KB) [[attachment:gallery2image-1.5.1-12.py]]
  • [get | view] (2006-08-06 09:01:01, 22.1 KB) [[attachment:gallery2image-1.5.4-13.py]]
  • [get | view] (2006-08-11 18:21:40, 22.2 KB) [[attachment:gallery2image-1.5.4-14.py]]
  • [get | view] (2006-11-16 20:23:27, 22.6 KB) [[attachment:gallery2image-1.5.6-16.py]]
  • [get | view] (2006-08-11 18:30:22, 22.2 KB) [[attachment:gallery2image-1.6.0-15.py]]
  • [get | view] (2008-02-06 10:13:45, 22.3 KB) [[attachment:gallery2image-1.6.0-16.py]]
  • [get | view] (2008-05-20 15:51:09, 22.4 KB) [[attachment:gallery2image-1.6.3-17.py]]
  • [get | view] (2006-09-06 06:19:48, 1.3 KB) [[attachment:getmmap.py]]
  • [get | view] (2004-07-18 09:48:00, 1.5 KB) [[attachment:localnames.py]]
  • [get | view] (2005-03-25 15:02:31, 2.6 KB) [[attachment:newpageonly.py]]
  • [get | view] (2005-03-30 09:02:00, 3.5 KB) [[attachment:newpageonly_20050330.py]]
  • [get | view] (2006-06-06 19:12:27, 9.7 KB) [[attachment:pdf.py]]
  • [get | view] (2006-08-30 10:51:51, 36.0 KB) [[attachment:pdf2_0_0.py]]
  • [get | view] (2006-08-30 13:57:36, 36.5 KB) [[attachment:pdf2_0_1.py]]
  • [get | view] (2006-02-04 04:25:29, 1.0 KB) [[attachment:sisterindex.py]]
  • [get | view] (2004-10-28 07:33:10, 0.7 KB) [[attachment:xml.py]]
 All files | Selected Files: delete move to page copy to page

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