Fix #336860 by Limiting Factor: use realpath for the path replacement when using...
[project/print.git] / print_pdf / print_pdf.pages.inc
CommitLineData
b09f08f7 1<?php
3483245d
JV
2// $Id$
3
4/**
5 * @file
6 * Generates the PDF versions of the pages
7 *
8 * This file is included by the print_pdf module and includes the
9 * functions that interface with the PDF generation packages.
10 */
b09f08f7 11
2c3f06f7 12require_once(DRUPAL_ROOT .'/'. drupal_get_path('module', 'print') .'/print.pages.inc');
b09f08f7 13
6a4c89f9
JV
14/**
15 * Generate a PDF version of the printer-friendly page
16 *
17 * @see print_controller()
18 * @see _print_get_template()
19 * @see _print_pdf_dompdf()
20 * @see _print_pdf_tcpdf()
21 */
b09f08f7 22function print_pdf_controller() {
e60934b7
JV
23 global $base_url;
24
5b1b9562 25 $args = func_get_args();
3c90dace 26 // Remove the printpdf/ prefix
5b1b9562 27 $path = implode('/', $args);
20ab24e6 28 $cid = isset($_GET['comment']) ? (int)$_GET['comment'] : NULL;
3c90dace 29
7d62e7c4 30 $print_pdf_pdf_tool = variable_get('print_pdf_pdf_tool', PRINT_PDF_PDF_TOOL_DEFAULT);
b09f08f7 31
0706a465 32 $print = print_controller($path, $cid);
5c9469df
JV
33 if ($print === FALSE) {
34 return;
35 }
36
b09f08f7 37 // Img elements must be set to absolute
7d62e7c4
JV
38 $pattern = '!<(img\s[^>]*?)>!is';
39 $print['content'] = preg_replace_callback($pattern, '_print_rewrite_urls', $print['content']);
40 $print['logo'] = preg_replace_callback($pattern, '_print_rewrite_urls', $print['logo']);
41 $print['footer_message'] = preg_replace_callback($pattern, '_print_rewrite_urls', $print['footer_message']);
e60934b7
JV
42 // And converted from private to public paths
43 $file_downloads = variable_get('file_downloads', FILE_DOWNLOADS_PUBLIC);
44 if ($file_downloads == FILE_DOWNLOADS_PRIVATE) {
968f9c90 45 $pattern = "!(<img\s[^>]*?src\s*?=\s*?['\"]?)${base_url}/(?:(?:index.php)?\?q=)?system/files(/[^>]*?>)!is";
44d16177 46 $replacement = '$1file://'. realpath(file_directory_path()) .'$2';
e60934b7
JV
47 $print['content'] = preg_replace($pattern, $replacement, $print['content']);
48 $print['logo'] = preg_replace($pattern, $replacement, $print['logo']);
49 $print['footer_message'] = preg_replace($pattern, $replacement, $print['footer_message']);
50 }
b09f08f7 51
7d62e7c4 52 $node = $print['node'];
1caf9f9d 53 ob_start();
2c3f06f7 54 include_once(DRUPAL_ROOT .'/'. _print_get_template('pdf', $print['type']));
1caf9f9d
JV
55 $html = ob_get_contents();
56 ob_end_clean();
57
7d62e7c4
JV
58 if (basename($print_pdf_pdf_tool) == 'dompdf_config.inc.php') {
59 _print_pdf_dompdf($print, $html, $path .'.pdf');
b09f08f7 60 }
7d62e7c4
JV
61 elseif (basename($print_pdf_pdf_tool) == 'tcpdf.php') {
62 _print_pdf_tcpdf($print, $html, $path .'.pdf');
b09f08f7
JV
63 }
64 else {
65 return drupal_not_found();
66 }
67}
68
6a4c89f9
JV
69/**
70 * Generate the PDF file using the dompdf library
71 *
72 * @param $print
73 * array containing the configured data
74 * @param $html
75 * contents of the post-processed template already with the node data
76 * @param $filename
77 * name of the PDF file to be generated
78 * @see print_pdf_controller()
79 */
1caf9f9d 80function _print_pdf_dompdf($print, $html, $filename) {
7d62e7c4
JV
81 $print_pdf_pdf_tool = variable_get('print_pdf_pdf_tool', PRINT_PDF_PDF_TOOL_DEFAULT);
82 $print_pdf_paper_size = variable_get('print_pdf_paper_size', PRINT_PDF_PAPER_SIZE_DEFAULT);
83 $print_pdf_page_orientation = variable_get('print_pdf_page_orientation', PRINT_PDF_PAGE_ORIENTATION_DEFAULT);
84 $print_pdf_content_disposition = variable_get('print_pdf_content_disposition', PRINT_PDF_CONTENT_DISPOSITION_DEFAULT);
2c3f06f7 85 require_once(DRUPAL_ROOT .'/'. $print_pdf_pdf_tool);
b09f08f7 86
893ee70f
JV
87 // dompdf seems to have problems with something in system.css so let's not use it
88 $html = preg_replace('!<link.*?modules/system/system.css.*?/>!', '', $html);
89
56bdd124
JV
90 $url_array = parse_url($print['url']);
91
3483245d 92 $protocol = $url_array['scheme'] .'://';
56bdd124 93 $host = $url_array['host'];
3483245d 94 $path = dirname($url_array['path']) .'/';
b09f08f7
JV
95
96 $dompdf = new DOMPDF();
56bdd124
JV
97 $dompdf->set_base_path($path);
98 $dompdf->set_host($host);
6a4c89f9 99 $dompdf->set_paper(drupal_strtolower($print_pdf_paper_size), $print_pdf_page_orientation);
56bdd124
JV
100 $dompdf->set_protocol($protocol);
101
b97f7b85
JV
102 $html = theme('print_pdf_dompdf_footer', $html);
103
d356106f 104 // Convert from UTF-8 to ISO-8859-1 and then to HTML entities
571e2ce9
JV
105 $all_entities = get_html_translation_table(HTML_ENTITIES, ENT_NOQUOTES);
106 $special_entities = get_html_translation_table(HTML_SPECIALCHARS, ENT_NOQUOTES);
107 $no_tags = array_diff($all_entities, $special_entities);
108 $html = strtr(utf8_decode($html), $no_tags);
d356106f
JV
109
110 $dompdf->load_html($html);
3483245d 111
b09f08f7 112 $dompdf->render();
7d62e7c4 113 $dompdf->stream($filename, array('Attachment' => ($print_pdf_content_disposition == 2)));
b09f08f7
JV
114}
115
6a4c89f9
JV
116/**
117 * Generate the PDF file using the TCPDF library
118 *
119 * @param $print
120 * array containing the configured data
121 * @param $html
122 * contents of the post-processed template already with the node data
123 * @param $filename
124 * name of the PDF file to be generated
125 * @see print_pdf_controller()
126 */
1caf9f9d 127function _print_pdf_tcpdf($print, $html, $filename) {
dc300af6 128 global $base_url;
7d62e7c4
JV
129 $print_pdf_pdf_tool = variable_get('print_pdf_pdf_tool', PRINT_PDF_PDF_TOOL_DEFAULT);
130 $print_pdf_paper_size = variable_get('print_pdf_paper_size', PRINT_PDF_PAPER_SIZE_DEFAULT);
131 $print_pdf_page_orientation = variable_get('print_pdf_page_orientation', PRINT_PDF_PAGE_ORIENTATION_DEFAULT);
132 $print_pdf_content_disposition = variable_get('print_pdf_content_disposition', PRINT_PDF_CONTENT_DISPOSITION_DEFAULT);
133
4817021f
JV
134 $pdf_tool_path = realpath(dirname($print_pdf_pdf_tool));
135
7d62e7c4 136 define('K_TCPDF_EXTERNAL_CONFIG', TRUE);
dc300af6
JV
137 define('K_PATH_MAIN', dirname($_SERVER['SCRIPT_FILENAME']));
138 define('K_PATH_URL', $base_url);
4817021f
JV
139 define('K_PATH_FONTS', $pdf_tool_path .'/fonts/');
140 define('K_PATH_CACHE', $pdf_tool_path .'/cache/');
141 define('K_PATH_IMAGES', '');
142 define('K_BLANK_IMAGE', $pdf_tool_path .'/images/_blank.png');
7d62e7c4
JV
143 define('K_CELL_HEIGHT_RATIO', 1.25);
144 define('K_SMALL_RATIO', 2/3);
145
2c3f06f7 146 require_once(DRUPAL_ROOT .'/'. $print_pdf_pdf_tool);
e03112ed 147 if (strpos(PDF_PRODUCER, 'PHP4') === FALSE) {
2c3f06f7 148 require_once(DRUPAL_ROOT .'/'. drupal_get_path('module', 'print_pdf') .'/print_pdf.class.inc');
90263e69
JV
149 }
150 else {
6936e5f6
JV
151 drupal_set_message(t("The PHP4 version of TCPDF is not supported. Please upgrade it."), 'error', FALSE);
152 drupal_goto($_GET['q']);
90263e69 153 }
7d62e7c4 154
455e82fd
JV
155 $font = Array(
156 variable_get('print_pdf_font_family', PRINT_PDF_FONT_FAMILY_DEFAULT),
b2a85b2b 157 '',
455e82fd
JV
158 variable_get('print_pdf_font_size', PRINT_PDF_FONT_SIZE_DEFAULT),
159 );
6a4c89f9 160 $orientation = drupal_strtoupper($print_pdf_page_orientation[0]);
56bdd124
JV
161
162 // create new PDF document
3da84173 163 $pdf = new PrintTCPDF($orientation , 'mm', $print_pdf_paper_size, TRUE);
b09f08f7 164
56bdd124 165 // set document information
7d62e7c4
JV
166 $pdf->SetAuthor(strip_tags($print['submitted']));
167 $pdf->SetCreator(variable_get('site_name', 'Drupal'));
168 $pdf->SetTitle($print['title']);
169 $keys = implode(' ', explode("\n", trim(strip_tags($print['taxonomy']))));
56bdd124 170 $pdf->SetKeywords($keys);
7d62e7c4 171 $pdf->setPDFVersion('1.6');
56bdd124 172
1024f54b
JV
173 $pdf = theme('print_pdf_tcpdf_header', $pdf, $html, $font);
174 $pdf = theme('print_pdf_tcpdf_footer', $pdf, $html, $font);
175 $pdf = theme('print_pdf_tcpdf_page', $pdf);
4817021f
JV
176
177 //initialize document
178 $pdf->AliasNbPages();
179
180 // add a page
181 $pdf->AddPage();
182
1024f54b 183 $pdf = theme('print_pdf_tcpdf_content', $pdf, $html, $font);
4817021f
JV
184
185 // reset pointer to the last page
186 $pdf->lastPage();
187
188 //Close and output PDF document
189 $output_dest = ($print_pdf_content_disposition == 2) ? 'D' : 'I';
190 $pdf->Output($filename, $output_dest);
191}
192
6a4c89f9 193/**
b97f7b85
JV
194 * Format the dompdf footer contents
195 *
196 * @param $html
197 * contents of the body of the HTML from the original node
198 * @see theme_print_pdf_tcpdf_footer()
199 */
3a1f33ce 200function theme_print_pdf_dompdf_footer(&$html) {
b97f7b85
JV
201 preg_match('!<div class="print-footer">(.*?)</div>!si', $html, $tpl_footer);
202 $html = str_replace($tpl_footer[0], '', $html);
203
204 $text = '<script type="text/php">
205 if (isset($pdf)) {
206 $font = Font_Metrics::get_font("verdana");;
207 $size = 10;
208 $color = array(0,0,0);
209 $text_height = Font_Metrics::get_font_height($font, $size);
210
211 $w = $pdf->get_width();
212 $h = $pdf->get_height();
213
214 $footer = $pdf->open_object();
215
216 // Draw a line along the bottom
217 $y = $h - 25;
218 $pdf->line(15, $y, $w - 15, $y, $color, 1);
219
220 $y += $text_height / 2;
38b1c723 221 $pdf->page_text(15, $y, \''. addslashes(strip_tags($tpl_footer[1])) .'\', $font, $size, $color);
b97f7b85
JV
222
223 $pdf->close_object();
224 $pdf->add_object($footer, "all");
225
226 // Center the text
227 $width = Font_Metrics::get_text_width("Page 1 of 2", $font, $size);
228 $pagenumtxt = t("Page !n of !total", array("!n" => "{PAGE_NUM}", "!total" => "{PAGE_COUNT}"));
229 $pdf->page_text($w - 15 - $width, $y, $pagenumtxt, $font, $size, $color);
230 }
231 </script>';
232
233 return str_replace("<body>", "<body>" . $text, $html);
234}
235
236/**
6a4c89f9
JV
237 * Format the TCPDF header
238 *
239 * @param $pdf
240 * current TCPDF object
241 * @param $html
242 * contents of the body of the HTML from the original node
243 * @param $font
244 * array with the font definition (font name, styles and size)
245 * @see theme_print_pdf_tcpdf_header()
246 */
3a1f33ce 247function theme_print_pdf_tcpdf_header(&$pdf, &$html, $font) {
4817021f
JV
248 preg_match('!<div class="print-logo">(.*?)</div>!si', $html, $tpl_logo);
249 preg_match('!<h1 class="print-title">(.*?)</h1>!si', $html, $tpl_title);
250 preg_match('!<div class="print-site_name">(.*?)</div>!si', $html, $tpl_site_name);
251
74df721a 252 $ratio = 0;
4817021f
JV
253 $logo = '';
254 $logo_ret = preg_match('!src\s*=\s*(\'.*?\'|".*?"|[^\s]*)!i', $tpl_logo[1], $matches);
3da84173
JV
255 if ($logo_ret) {
256 $logo = trim($matches[1], '\'"');
4817021f 257 $size = getimagesize($logo);
c64555f4 258 $ratio = $size ? ($size[0] / $size[1]) : 0;
3da84173
JV
259 }
260
4817021f
JV
261 // set header font
262 $pdf->setHeaderFont($font);
263 // set header margin
264 $pdf->SetHeaderMargin(5);
56bdd124 265 // set header data
4817021f 266 $pdf->SetHeaderData($logo, 10 * $ratio, $tpl_title[1], strip_tags($tpl_site_name[1]));
1024f54b
JV
267
268 return $pdf;
4817021f 269}
3da84173 270
6a4c89f9
JV
271/**
272 * Format the TCPDF page settings (margins, etc)
273 *
274 * @param $pdf
275 * current TCPDF object
276 * @see theme_print_pdf_tcpdf_page()
277 */
3a1f33ce 278function theme_print_pdf_tcpdf_page(&$pdf) {
b09f08f7 279 // set margins
4817021f 280 $pdf->SetMargins(15, 20, 15);
c67b9ed4 281 // set auto page breaks
4817021f 282 $pdf->SetAutoPageBreak(TRUE, 15);
b09f08f7 283 // set image scale factor
75628d9a 284 $pdf->setImageScale(4);
973f5b72
JV
285 // set image compression quality
286 $pdf->setJPEGQuality(100);
1024f54b
JV
287
288 return $pdf;
4817021f 289}
973f5b72 290
6a4c89f9
JV
291/**
292 * Format the TCPDF page content
293 *
294 * @param $pdf
295 * current TCPDF object
296 * @param $html
297 * contents of the body of the HTML from the original node
298 * @param $font
299 * array with the font definition (font name, styles and size)
300 * @see theme_print_pdf_tcpdf_content()
301 */
3a1f33ce 302function theme_print_pdf_tcpdf_content(&$pdf, &$html, $font) {
4817021f
JV
303 // set content font
304 $pdf->setFont($font[0], $font[1], $font[2]);
b09f08f7 305
26673803 306 preg_match('!<body.*?>(.*)</body>!sim', $html, $matches);
4817021f 307 $pattern = '!(?:<div class="print-(?:logo|site_name|breadcrumb|footer)">.*?</div>|<hr class="print-hr" />)!si';
3da84173
JV
308 $matches[1] = preg_replace($pattern, '', $matches[1]);
309
4817021f
JV
310 // Since TCPDF's writeHTML is so bad with <p>, do everything possible to make it look nice
311 $matches[1] = preg_replace('!(<p\s*/>|</p>)!i', '<br />', $matches[1]);
e83e4f36
JV
312 $matches[1] = str_replace(array('<div', 'div>'), array('<span', 'span><br />'), $matches[1]);
313
314 $pdf->writeHTML($matches[1]);
1024f54b
JV
315
316 return $pdf;
4817021f 317}
b09f08f7 318
6a4c89f9
JV
319/**
320 * Format the TCPDF footer contents
321 *
322 * @param $pdf
323 * current TCPDF object
324 * @param $html
325 * contents of the body of the HTML from the original node
326 * @param $font
327 * array with the font definition (font name, styles and size)
328 * @see theme_print_pdf_tcpdf_footer()
329 */
3a1f33ce 330function theme_print_pdf_tcpdf_footer(&$pdf, &$html, $font) {
b97f7b85
JV
331 preg_match('!<div class="print-footer">(.*?)</div>!si', $html, $tpl_footer);
332 $footer = trim(preg_replace('!</?div[^>]*?>!i', '', $tpl_footer[1]));
2c779f90 333
4817021f
JV
334 // set footer font
335 $font[2] *= 0.8;
336 $pdf->setFooterFont($font);
337 // set footer margin
338 $pdf->SetFooterMargin(10);
339 // set footer data
b97f7b85 340 $pdf->SetFooterData($footer);
1024f54b
JV
341
342 return $pdf;
b09f08f7 343}
6a4c89f9
JV
344
345/**
346 * Format the TCPDF footer layout
347 *
348 * @param $pdf
349 * current TCPDF object
350 * @see theme_print_pdf_tcpdf_footer2()
351 */
3a1f33ce 352function theme_print_pdf_tcpdf_footer2(&$pdf) {
6a4c89f9 353 //Position at 1.5 cm from bottom
90263e69 354 $pdf->writeHTMLCell(0, 15, 15, 0, $pdf->footer, 0, 0, 0, TRUE, '');
6a4c89f9
JV
355
356 $ormargins = $pdf->getOriginalMargins();
b97f7b85 357 $pagenumtxt = t('Page !n of !total', array('!n' => $pdf->PageNo(), '!total' => $pdf->getAliasNbPages()));
6a4c89f9
JV
358 //Print page number
359 if ($pdf->getRTL()) {
360 $pdf->SetX($ormargins['right']);
361 $pdf->Cell(0, 10, $pagenumtxt, 'T', 0, 'L');
362 }
363 else {
364 $pdf->SetX($ormargins['left']);
365 $pdf->Cell(0, 10, $pagenumtxt, 'T', 0, 'R');
366 }
1024f54b
JV
367
368 return $pdf;
6a4c89f9 369}