r94046 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r94045‎ | r94046 | r94047 >
Date:15:01, 7 August 2011
Author:ialex
Status:deferred
Tags:
Comment:
* Moved PdfBook class to its own file and renamed it to PdfBookHooks
* Made class methods static and removed extension function
* Removed useless LanguageGetMagic hook
* Removed usage of $wgTitle
* Unconditionally define $wgPdfBookTab; was a register_globals vulnerability
Modified paths:
  • /trunk/extensions/PdfBook/PdfBook.hooks.php (added) (history)
  • /trunk/extensions/PdfBook/PdfBook.php (modified) (history)

Diff [purge]

Index: trunk/extensions/PdfBook/PdfBook.php
@@ -18,9 +18,9 @@
1919
2020 define( 'PDFBOOK_VERSION', "1.0.9, 2010-12-17" );
2121
22 -$wgExtensionFunctions[] = 'wfSetupPdfBook';
23 -$wgHooks['LanguageGetMagic'][] = 'wfPdfBookLanguageGetMagic';
24 -$wgExtensionMessagesFiles['PdfBook'] = dirname( __FILE__ ) . '/PdfBook.i18n.php';
 22+$dir = dirname( __FILE__ );
 23+$wgAutoloadClasses['PdfBookHooks'] = $dir . '/PdfBook.hooks.php';
 24+$wgExtensionMessagesFiles['PdfBook'] = $dir . '/PdfBook.i18n.php';
2525
2626 $wgExtensionCredits['parserhook'][] = array(
2727 'path' => __FILE__,
@@ -32,209 +32,16 @@
3333 );
3434
3535 # Whether or not an action tab is wanted for printing to PDF
36 -if( !isset( $wgPdfBookTab ) ) $wgPdfBookTab = false;
 36+$wgPdfBookTab = false;
3737
38 -class PdfBook {
 38+$wgHooks['UnknownAction'][] = 'PdfBookHooks::onUnknownAction';
3939
40 - function __construct() {
41 - global $wgHooks, $wgParser, $wgPdfBookMagic;
42 - global $wgLogTypes, $wgLogNames, $wgLogHeaders, $wgLogActions, $wgPdfBookTab;
43 - $wgHooks['UnknownAction'][] = $this;
 40+# Hooks for pre-Vector and Vector addtabs.
 41+$wgHooks['SkinTemplateTabs'][] = 'PdfBookHooks::onSkinTemplateTabs';
 42+$wgHooks['SkinTemplateNavigation'][] = 'PdfBookHooks::onSkinTemplateNavigation';
4443
45 - # Hooks for pre-Vector and Vector addtabs.
46 - if( $wgPdfBookTab ) {
47 - $wgHooks['SkinTemplateTabs'][] = $this ;
48 - $wgHooks['SkinTemplateNavigation'][] = $this;
49 - }
50 -
51 - # Add a new pdf log type
52 - $wgLogTypes[] = 'pdf';
53 - $wgLogNames ['pdf'] = 'pdflogpage';
54 - $wgLogHeaders['pdf'] = 'pdflogpagetext';
55 - $wgLogActions['pdf/book'] = 'pdflogentry';
56 -
57 - }
58 -
59 -
60 - /**
61 - * Perform the export operation
62 - */
63 - function onUnknownAction( $action, $article ) {
64 - global $wgOut, $wgUser, $wgTitle, $wgParser, $wgRequest;
65 - global $wgServer, $wgArticlePath, $wgScriptPath, $wgUploadPath, $wgUploadDirectory, $wgScript;
66 -
67 - if( $action == 'pdfbook' ) {
68 -
69 - $title = $article->getTitle();
70 - $opt = ParserOptions::newFromUser( $wgUser );
71 -
72 - # Log the export
73 - $msg = wfMsg( 'pdfbook-log', $wgUser->getUserPage()->getPrefixedText() );
74 - $log = new LogPage( 'pdf', false );
75 - $log->addEntry( 'book', $wgTitle, $msg );
76 -
77 - # Initialise PDF variables
78 - $format = $wgRequest->getText( 'format' );
79 - $notitle = $wgRequest->getText( 'notitle' );
80 - $layout = $format == 'single' ? '--webpage' : '--firstpage toc';
81 - $charset = $this->setProperty( 'Charset', 'iso-8859-1' );
82 - $left = $this->setProperty( 'LeftMargin', '1cm' );
83 - $right = $this->setProperty( 'RightMargin', '1cm' );
84 - $top = $this->setProperty( 'TopMargin', '1cm' );
85 - $bottom = $this->setProperty( 'BottomMargin','1cm' );
86 - $font = $this->setProperty( 'Font', 'Arial' );
87 - $size = $this->setProperty( 'FontSize', '8' );
88 - $ls = $this->setProperty( 'LineSpacing', 1 );
89 - $linkcol = $this->setProperty( 'LinkColour', '217A28' );
90 - $levels = $this->setProperty( 'TocLevels', '2' );
91 - $exclude = $this->setProperty( 'Exclude', array() );
92 - $width = $this->setProperty( 'Width', '' );
93 - $width = $width ? "--browserwidth $width" : '';
94 - if( !is_array( $exclude ) ) $exclude = split( '\\s*,\\s*', $exclude );
95 -
96 - # Select articles from members if a category or links in content if not
97 - if( $format == 'single' ) $articles = array( $title );
98 - else {
99 - $articles = array();
100 - if( $title->getNamespace() == NS_CATEGORY ) {
101 - $db = wfGetDB( DB_SLAVE );
102 - $cat = $db->addQuotes( $title->getDBkey() );
103 - $result = $db->select(
104 - 'categorylinks',
105 - 'cl_from',
106 - "cl_to = $cat",
107 - 'PdfBook',
108 - array( 'ORDER BY' => 'cl_sortkey' )
109 - );
110 - if( $result instanceof ResultWrapper ) $result = $result->result;
111 - while ( $row = $db->fetchRow( $result ) ) $articles[] = Title::newFromID( $row[0] );
112 - }
113 - else {
114 - $text = $article->fetchContent();
115 - $text = $wgParser->preprocess( $text, $title, $opt );
116 - if ( preg_match_all( "/^\\*\\s*\\[{2}\\s*([^\\|\\]]+)\\s*.*?\\]{2}/m", $text, $links ) )
117 - foreach ( $links[1] as $link ) $articles[] = Title::newFromText( $link );
118 - }
119 - }
120 -
121 - # Format the article(s) as a single HTML document with absolute URL's
122 - $book = $title->getText();
123 - $html = '';
124 - $wgArticlePath = $wgServer.$wgArticlePath;
125 - $wgPdfBookTab = false;
126 - $wgScriptPath = $wgServer.$wgScriptPath;
127 - $wgUploadPath = $wgServer.$wgUploadPath;
128 - $wgScript = $wgServer.$wgScript;
129 - foreach( $articles as $title ) {
130 - $ttext = $title->getPrefixedText();
131 - if( !in_array( $ttext, $exclude ) ) {
132 - $article = new Article( $title );
133 - $text = $article->fetchContent();
134 - $text = preg_replace( "/<!--([^@]+?)-->/s", "@@" . "@@$1@@" . "@@", $text ); # preserve HTML comments
135 - if( $format != 'single' ) $text .= "__NOTOC__";
136 - $opt->setEditSection( false ); # remove section-edit links
137 - $out = $wgParser->parse( $text, $title, $opt, true, true );
138 - $text = $out->getText();
139 - $text = preg_replace( "|(<img[^>]+?src=\")(/.+?>)|", "$1$wgServer$2", $text ); # make image urls absolute
140 - $text = preg_replace( "|<div\s*class=['\"]?noprint[\"']?>.+?</div>|s", "", $text ); # non-printable areas
141 - $text = preg_replace( "|@{4}([^@]+?)@{4}|s", "<!--$1-->", $text ); # HTML comments hack
142 - $ttext = basename( $ttext );
143 - $h1 = $notitle ? "" : "<center><h1>$ttext</h1></center>";
144 - $html .= utf8_decode( "$h1$text\n" );
145 - }
146 - }
147 -
148 - # $wgPdfBookTab = false; If format=html in query-string, return html content directly
149 - if( $format == 'html' ) {
150 - $wgOut->disable();
151 - header( "Content-Type: text/html" );
152 - header( "Content-Disposition: attachment; filename=\"$book.html\"" );
153 - print $html;
154 - }
155 - else {
156 - # Write the HTML to a tmp file
157 - $file = "$wgUploadDirectory/" . uniqid( 'pdf-book' );
158 - $fh = fopen( $file, 'w+' );
159 - fwrite( $fh, $html );
160 - fclose( $fh );
161 -
162 - $footer = $format == 'single' ? "..." : ".1.";
163 - $toc = $format == 'single' ? "" : " --toclevels $levels";
164 -
165 - # Send the file to the client via htmldoc converter
166 - $wgOut->disable();
167 - header( "Content-Type: application/pdf" );
168 - header( "Content-Disposition: attachment; filename=\"$book.pdf\"" );
169 - $cmd = "--left $left --right $right --top $top --bottom $bottom";
170 - $cmd .= " --header ... --footer $footer --headfootsize 8 --quiet --jpeg --color";
171 - $cmd .= " --bodyfont $font --fontsize $size --fontspacing $ls --linkstyle plain --linkcolor $linkcol";
172 - $cmd .= "$toc --no-title --format pdf14 --numbered $layout $width";
173 - $cmd = "htmldoc -t pdf --charset $charset $cmd $file";
174 - putenv( "HTMLDOC_NOCGI=1" );
175 - passthru( $cmd );
176 - @unlink( $file );
177 - }
178 - return false;
179 - }
180 -
181 - return true;
182 - }
183 -
184 -
185 - /**
186 - * Return a property for htmldoc using global, request or passed default
187 - */
188 - function setProperty( $name, $default ) {
189 - global $wgRequest;
190 - if ( $wgRequest->getText( "pdf$name" ) ) return $wgRequest->getText( "pdf$name" );
191 - if ( isset( $GLOBALS["wgPdfBook$name"] ) ) return $GLOBALS["wgPdfBook$name"];
192 - return $default;
193 - }
194 -
195 -
196 - /**
197 - * Add PDF to actions tabs in MonoBook based skins
198 - */
199 - function onSkinTemplateTabs( $skin, &$actions) {
200 - global $wgTitle;
201 - $actions['pdfbook'] = array(
202 - 'class' => false,
203 - 'text' => wfMsg( 'pdfbook-action' ),
204 - 'href' => $wgTitle->getLocalURL( "action=pdfbook&format=single" ),
205 - );
206 - return true;
207 - }
208 -
209 -
210 - /**
211 - * Add PDF to actions tabs in vector based skins
212 - */
213 - function onSkinTemplateNavigation( $skin, &$actions ) {
214 - global $wgTitle;
215 - $actions['views']['pdfbook'] = array(
216 - 'class' => false,
217 - 'text' => wfMsg( 'pdfbook-action' ),
218 - 'href' => $wgTitle->getLocalURL( "action=pdfbook&format=single" ),
219 - );
220 - return true;
221 - }
222 -}
223 -
224 -
225 -/**
226 - * Called from $wgExtensionFunctions array when initialising extensions
227 - */
228 -function wfSetupPdfBook() {
229 - global $wgPdfBook;
230 - $wgPdfBook = new PdfBook();
231 -}
232 -
233 -
234 -/**
235 - * Needed in MediaWiki >1.8.0 for magic word hooks to work properly
236 - */
237 -function wfPdfBookLanguageGetMagic( &$magicWords, $langCode = 0 ) {
238 - global $wgPdfBookMagic;
239 - $magicWords[$wgPdfBookMagic] = array( $langCode, $wgPdfBookMagic );
240 - return true;
241 -}
 44+# Add a new pdf log type
 45+$wgLogTypes[] = 'pdf';
 46+$wgLogNames ['pdf'] = 'pdflogpage';
 47+$wgLogHeaders['pdf'] = 'pdflogpagetext';
 48+$wgLogActions['pdf/book'] = 'pdflogentry';
Index: trunk/extensions/PdfBook/PdfBook.hooks.php
@@ -0,0 +1,173 @@
 2+<?php
 3+
 4+class PdfBookHooks {
 5+
 6+ /**
 7+ * Perform the export operation
 8+ */
 9+ public static function onUnknownAction( $action, $article ) {
 10+ global $wgOut, $wgUser, $wgParser, $wgRequest;
 11+ global $wgServer, $wgArticlePath, $wgScriptPath, $wgUploadPath, $wgUploadDirectory, $wgScript;
 12+
 13+ if( $action == 'pdfbook' ) {
 14+
 15+ $title = $article->getTitle();
 16+ $opt = ParserOptions::newFromUser( $wgUser );
 17+
 18+ # Log the export
 19+ $msg = wfMsg( 'pdfbook-log', $wgUser->getUserPage()->getPrefixedText() );
 20+ $log = new LogPage( 'pdf', false );
 21+ $log->addEntry( 'book', $article->getTitle(), $msg );
 22+
 23+ # Initialise PDF variables
 24+ $format = $wgRequest->getText( 'format' );
 25+ $notitle = $wgRequest->getText( 'notitle' );
 26+ $layout = $format == 'single' ? '--webpage' : '--firstpage toc';
 27+ $charset = self::setProperty( 'Charset', 'iso-8859-1' );
 28+ $left = self::setProperty( 'LeftMargin', '1cm' );
 29+ $right = self::setProperty( 'RightMargin', '1cm' );
 30+ $top = self::setProperty( 'TopMargin', '1cm' );
 31+ $bottom = self::setProperty( 'BottomMargin','1cm' );
 32+ $font = self::setProperty( 'Font', 'Arial' );
 33+ $size = self::setProperty( 'FontSize', '8' );
 34+ $ls = self::setProperty( 'LineSpacing', 1 );
 35+ $linkcol = self::setProperty( 'LinkColour', '217A28' );
 36+ $levels = self::setProperty( 'TocLevels', '2' );
 37+ $exclude = self::setProperty( 'Exclude', array() );
 38+ $width = self::setProperty( 'Width', '' );
 39+ $width = $width ? "--browserwidth $width" : '';
 40+ if( !is_array( $exclude ) ) $exclude = split( '\\s*,\\s*', $exclude );
 41+
 42+ # Select articles from members if a category or links in content if not
 43+ if( $format == 'single' ) $articles = array( $title );
 44+ else {
 45+ $articles = array();
 46+ if( $title->getNamespace() == NS_CATEGORY ) {
 47+ $db = wfGetDB( DB_SLAVE );
 48+ $cat = $db->addQuotes( $title->getDBkey() );
 49+ $result = $db->select(
 50+ 'categorylinks',
 51+ 'cl_from',
 52+ "cl_to = $cat",
 53+ 'PdfBook',
 54+ array( 'ORDER BY' => 'cl_sortkey' )
 55+ );
 56+ if( $result instanceof ResultWrapper ) $result = $result->result;
 57+ while ( $row = $db->fetchRow( $result ) ) $articles[] = Title::newFromID( $row[0] );
 58+ }
 59+ else {
 60+ $text = $article->fetchContent();
 61+ $text = $wgParser->preprocess( $text, $title, $opt );
 62+ if ( preg_match_all( "/^\\*\\s*\\[{2}\\s*([^\\|\\]]+)\\s*.*?\\]{2}/m", $text, $links ) )
 63+ foreach ( $links[1] as $link ) $articles[] = Title::newFromText( $link );
 64+ }
 65+ }
 66+
 67+ # Format the article(s) as a single HTML document with absolute URL's
 68+ $book = $title->getText();
 69+ $html = '';
 70+ $wgArticlePath = $wgServer.$wgArticlePath;
 71+ $wgPdfBookTab = false;
 72+ $wgScriptPath = $wgServer.$wgScriptPath;
 73+ $wgUploadPath = $wgServer.$wgUploadPath;
 74+ $wgScript = $wgServer.$wgScript;
 75+ foreach( $articles as $title ) {
 76+ $ttext = $title->getPrefixedText();
 77+ if( !in_array( $ttext, $exclude ) ) {
 78+ $article = new Article( $title );
 79+ $text = $article->fetchContent();
 80+ $text = preg_replace( "/<!--([^@]+?)-->/s", "@@" . "@@$1@@" . "@@", $text ); # preserve HTML comments
 81+ if( $format != 'single' ) $text .= "__NOTOC__";
 82+ $opt->setEditSection( false ); # remove section-edit links
 83+ $out = $wgParser->parse( $text, $title, $opt, true, true );
 84+ $text = $out->getText();
 85+ $text = preg_replace( "|(<img[^>]+?src=\")(/.+?>)|", "$1$wgServer$2", $text ); # make image urls absolute
 86+ $text = preg_replace( "|<div\s*class=['\"]?noprint[\"']?>.+?</div>|s", "", $text ); # non-printable areas
 87+ $text = preg_replace( "|@{4}([^@]+?)@{4}|s", "<!--$1-->", $text ); # HTML comments hack
 88+ $ttext = basename( $ttext );
 89+ $h1 = $notitle ? "" : "<center><h1>$ttext</h1></center>";
 90+ $html .= utf8_decode( "$h1$text\n" );
 91+ }
 92+ }
 93+
 94+ # $wgPdfBookTab = false; If format=html in query-string, return html content directly
 95+ if( $format == 'html' ) {
 96+ $wgOut->disable();
 97+ header( "Content-Type: text/html" );
 98+ header( "Content-Disposition: attachment; filename=\"$book.html\"" );
 99+ print $html;
 100+ }
 101+ else {
 102+ # Write the HTML to a tmp file
 103+ $file = "$wgUploadDirectory/" . uniqid( 'pdf-book' );
 104+ $fh = fopen( $file, 'w+' );
 105+ fwrite( $fh, $html );
 106+ fclose( $fh );
 107+
 108+ $footer = $format == 'single' ? "..." : ".1.";
 109+ $toc = $format == 'single' ? "" : " --toclevels $levels";
 110+
 111+ # Send the file to the client via htmldoc converter
 112+ $wgOut->disable();
 113+ header( "Content-Type: application/pdf" );
 114+ header( "Content-Disposition: attachment; filename=\"$book.pdf\"" );
 115+ $cmd = "--left $left --right $right --top $top --bottom $bottom";
 116+ $cmd .= " --header ... --footer $footer --headfootsize 8 --quiet --jpeg --color";
 117+ $cmd .= " --bodyfont $font --fontsize $size --fontspacing $ls --linkstyle plain --linkcolor $linkcol";
 118+ $cmd .= "$toc --no-title --format pdf14 --numbered $layout $width";
 119+ $cmd = "htmldoc -t pdf --charset $charset $cmd $file";
 120+ putenv( "HTMLDOC_NOCGI=1" );
 121+ passthru( $cmd );
 122+ @unlink( $file );
 123+ }
 124+ return false;
 125+ }
 126+
 127+ return true;
 128+ }
 129+
 130+
 131+ /**
 132+ * Return a property for htmldoc using global, request or passed default
 133+ */
 134+ private static function setProperty( $name, $default ) {
 135+ global $wgRequest;
 136+ if ( $wgRequest->getText( "pdf$name" ) ) return $wgRequest->getText( "pdf$name" );
 137+ if ( isset( $GLOBALS["wgPdfBook$name"] ) ) return $GLOBALS["wgPdfBook$name"];
 138+ return $default;
 139+ }
 140+
 141+
 142+ /**
 143+ * Add PDF to actions tabs in MonoBook based skins
 144+ */
 145+ public static function onSkinTemplateTabs( $skin, &$actions) {
 146+ global $wgPdfBookTab;
 147+
 148+ if ( $wgPdfBookTab ) {
 149+ $actions['pdfbook'] = array(
 150+ 'class' => false,
 151+ 'text' => wfMsg( 'pdfbook-action' ),
 152+ 'href' => $skin->getTitle()->getLocalURL( "action=pdfbook&format=single" ),
 153+ );
 154+ }
 155+ return true;
 156+ }
 157+
 158+
 159+ /**
 160+ * Add PDF to actions tabs in vector based skins
 161+ */
 162+ public static function onSkinTemplateNavigation( $skin, &$actions ) {
 163+ global $wgPdfBookTab;
 164+
 165+ if ( $wgPdfBookTab ) {
 166+ $actions['views']['pdfbook'] = array(
 167+ 'class' => false,
 168+ 'text' => wfMsg( 'pdfbook-action' ),
 169+ 'href' => $skin->getTitle()->getLocalURL( "action=pdfbook&format=single" ),
 170+ );
 171+ }
 172+ return true;
 173+ }
 174+}
Property changes on: trunk/extensions/PdfBook/PdfBook.hooks.php
___________________________________________________________________
Added: svn:eol-style
1175 + native

Status & tagging log