1
|
<?php
|
2
|
|
3
|
/**
|
4
|
* @file
|
5
|
* Generates the PDF version using wkhtmltopdf.
|
6
|
*
|
7
|
* This file is included by the print_pdf_wkhtmltopdf module and includes the
|
8
|
* functions that interface with the wkhtmltopdf library.
|
9
|
*
|
10
|
* @ingroup print
|
11
|
*/
|
12
|
|
13
|
/**
|
14
|
* Implements hook_print_pdf_generate().
|
15
|
*/
|
16
|
function print_pdf_wkhtmltopdf_print_pdf_generate($html, $meta, $paper_size = NULL, $page_orientation = NULL) {
|
17
|
$pdf_tool = explode('|', variable_get('print_pdf_pdf_tool', PRINT_PDF_PDF_TOOL_DEFAULT));
|
18
|
if (empty($paper_size)) {
|
19
|
$paper_size = variable_get('print_pdf_paper_size', PRINT_PDF_PAPER_SIZE_DEFAULT);
|
20
|
}
|
21
|
if (empty($page_orientation)) {
|
22
|
$page_orientation = variable_get('print_pdf_page_orientation', PRINT_PDF_PAGE_ORIENTATION_DEFAULT);
|
23
|
}
|
24
|
$wkhtmltopdf_options = variable_get('print_pdf_wkhtmltopdf_options', PRINT_PDF_WKHTMLTOPDF_OPTIONS);
|
25
|
|
26
|
$dpi = 96;
|
27
|
|
28
|
if (!empty($wkhtmltopdf_options) && isset($meta['node'])) {
|
29
|
$wkhtmltopdf_options = token_replace($wkhtmltopdf_options, array('node' => $meta['node']), array('clear' => TRUE));
|
30
|
}
|
31
|
|
32
|
// Build array of single quoted parts, and the same escaped.
|
33
|
preg_match_all("!'.+?'!", $wkhtmltopdf_options, $matches);
|
34
|
$quoted = array();
|
35
|
foreach ($matches[0] as $match) {
|
36
|
$quoted[escapeshellcmd($match)] = $match;
|
37
|
}
|
38
|
|
39
|
// Prevent options that could result in execution of arbitrary commands.
|
40
|
$wkhtmltopdf_options = escapeshellcmd($wkhtmltopdf_options);
|
41
|
|
42
|
// Replace sections that were single quoted with original content.
|
43
|
foreach ($quoted as $search => $replace) {
|
44
|
$wkhtmltopdf_options = str_replace($search, $replace, $wkhtmltopdf_options);
|
45
|
}
|
46
|
|
47
|
$version = print_pdf_wkhtmltopdf_pdf_tool_version($pdf_tool[1], FALSE);
|
48
|
|
49
|
// 0.10.0 beta2 identifies itself as 0.9.9.
|
50
|
if (version_compare($version, '0.9.9', '>=')) {
|
51
|
$wkhtmltopdf_options = '--disable-local-file-access ' . $wkhtmltopdf_options;
|
52
|
}
|
53
|
elseif (version_compare($version, '0.9.6', '>=')) {
|
54
|
$wkhtmltopdf_options = '--disallow-local-file-access ' . $wkhtmltopdf_options;
|
55
|
}
|
56
|
else {
|
57
|
drupal_goto($meta['url']);
|
58
|
exit;
|
59
|
}
|
60
|
|
61
|
// Use basic http authentication to fetch included CSS, etc.
|
62
|
if (isset($_SERVER['PHP_AUTH_USER']) && isset($_SERVER['PHP_AUTH_PW'])) {
|
63
|
$wkhtmltopdf_options .= ' --username ' . escapeshellarg($_SERVER['PHP_AUTH_USER']) . ' --password ' . escapeshellarg($_SERVER['PHP_AUTH_PW']);
|
64
|
}
|
65
|
|
66
|
$use_input_file = variable_get('print_pdf_wkhtmltopdf_use_input_file', PRINT_PDF_WKHTMLTOPDF_USE_INPUT_FILE_DEFAULT);
|
67
|
if ($use_input_file) {
|
68
|
$temp_html = file_unmanaged_save_data($html, drupal_tempnam('temporary://', 'c_html_') . '.html', FILE_EXISTS_RENAME);
|
69
|
if ($temp_html === FALSE) {
|
70
|
watchdog('print_pdf', 'wkhtmltopdf: could not create temporary html file: %file', array('%file' => $temp_html));
|
71
|
drupal_goto($meta['url']);
|
72
|
return NULL;
|
73
|
}
|
74
|
$html_input_parameter = drupal_realpath($temp_html);
|
75
|
}
|
76
|
else {
|
77
|
$temp_html = '';
|
78
|
$html_input_parameter = '-';
|
79
|
}
|
80
|
|
81
|
$descriptor = array(
|
82
|
0 => array('pipe', 'r'),
|
83
|
1 => array('pipe', 'w'),
|
84
|
2 => array('pipe', 'a'),
|
85
|
);
|
86
|
$cmd = '"' . realpath($pdf_tool[1]) . "\" -q --page-size $paper_size --orientation $page_orientation --dpi $dpi $wkhtmltopdf_options $html_input_parameter -";
|
87
|
|
88
|
$process = proc_open($cmd, $descriptor, $pipes, NULL, NULL);
|
89
|
|
90
|
if (is_resource($process)) {
|
91
|
if (!$use_input_file) {
|
92
|
fwrite($pipes[0], $html);
|
93
|
fclose($pipes[0]);
|
94
|
}
|
95
|
|
96
|
$pdf = stream_get_contents($pipes[1]);
|
97
|
fclose($pipes[1]);
|
98
|
|
99
|
stream_set_blocking($pipes[2], 0);
|
100
|
$error = stream_get_contents($pipes[2]);
|
101
|
fclose($pipes[2]);
|
102
|
|
103
|
$retval = proc_close($process);
|
104
|
if (!empty($error) || ($retval != 0)) {
|
105
|
if (empty($error)) {
|
106
|
$error = 'No stderr output available.';
|
107
|
}
|
108
|
watchdog('print_pdf', 'wkhtmltopdf [%cmd] (returned %ret): %error',
|
109
|
array('%cmd' => $cmd, '%ret' => $retval, '%error' => $error));
|
110
|
}
|
111
|
}
|
112
|
if ($use_input_file) {
|
113
|
file_unmanaged_delete($temp_html);
|
114
|
}
|
115
|
|
116
|
if (!empty($pdf)) {
|
117
|
// Remove anything before actual PDF content.
|
118
|
$pdf = substr($pdf, strpos($pdf, '%PDF-'));
|
119
|
|
120
|
return $pdf;
|
121
|
}
|
122
|
else {
|
123
|
drupal_set_message(t('Unable to generate PDF file.'), 'error');
|
124
|
drupal_goto($meta['url']);
|
125
|
return NULL;
|
126
|
}
|
127
|
}
|