print_pdf_wkhtmltopdf.pages.inc 4.2 KB

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