exePath = $this->addDoubleQuotes(ltrim($exePath)); $this->styleSheets = ''; $this->scripts = ''; $this->fileAttachments = ''; $this->licenseFile = ''; $this->licenseKey = ''; $this->inputType = 'auto'; $this->javascript = false; $this->baseURL = ''; $this->doXInclude = true; $this->httpUser = ''; $this->httpPassword = ''; $this->httpProxy = ''; $this->insecure = false; $this->logFile = ''; $this->fileRoot = ''; $this->embedFonts = true; $this->subsetFonts = true; $this->compress = true; $this->encrypt = false; $this->encryptInfo = ''; } // Add a CSS style sheet that will be applied to each document. // cssPath: The filename of the CSS style sheet. public function addStyleSheet($cssPath) { $this->styleSheets .= '-s "' . $cssPath . '" '; } // Clear all of the CSS style sheets. public function clearStyleSheets() { $this->styleSheets = ''; } // Add a JavaScript script that will be run before conversion. // jsPath: The filename of the script. public function addScript($jsPath) { $this->scripts .= '--script "' . $jsPath . '" '; } // Clear all of the scripts. public function clearScripts() { $this->scripts = ''; } //Add a file attachment that will be attached to the PDF file //filePath: The filename of the file attachment. public function addFileAttachment($filePath) { $this->fileAttachments .= '--attach=' . '"' . $filePath . '" '; } //Clear all of the file attachments. public function clearFileAttachments() { $this->fileAttachments = ''; } //Specify the license file. //file: The filename of the license file. public function setLicenseFile($file) { $this->licenseFile = $file; } //Specify the license key. //key: The license key public function setLicenseKey($key) { $this->licenseKey = $key; } //Specify the input type of the document. //inputType: Can take a value of : "xml", "html" or "auto". public function setInputType($inputType) { $this->inputType = $inputType; } // Specify whether JavaScript found in documents should be run. // js: True if document scripts should be run. public function setJavaScript($js) { $this->javascript = $js; } // Specify whether documents should be parsed as HTML or XML/XHTML. // html: True if all documents should be treated as HTML. public function setHTML($html) { if($html) { $this->inputType = "html"; } else { $this->inputType = "xml"; } } // Specify a file that Prince should use to log error/warning messages. // logFile: The filename that Prince should use to log error/warning // messages, or '' to disable logging. public function setLog($logFile) { $this->logFile = $logFile; } // Specify the base URL of the input document. // baseURL: The base URL or path of the input document, or ''. public function setBaseURL($baseURL) { $this->baseURL = $baseURL; } // Specify whether XML Inclusions (XInclude) processing should be applied // to input documents. XInclude processing will be performed by default // unless explicitly disabled. // xinclude: False to disable XInclude processing. public function setXInclude($xinclude) { $this->doXInclude = $xinclude; } // Specify a username to use when fetching remote resources over HTTP. // user: The username to use for basic HTTP authentication. public function setHttpUser($user) { $this->httpUser = $this->cmdlineArgEscape2($this->cmdlineArgEscape1($user)); } // Specify a password to use when fetching remote resources over HTTP. // password: The password to use for basic HTTP authentication. public function setHttpPassword($password) { $this->httpPassword = $this->cmdlineArgEscape2($this->cmdlineArgEscape1($password)); } //Specify the URL for the HTTP proxy server, if needed. //proxy: The URL for the HTTP proxy server. public function setHttpProxy($proxy) { $this->httpProxy = $proxy; } //Specify whether to disable SSL verification. //insecure: If set to true, SSL verification is disabled. (not recommended) public function setInsecure($insecure) { $this->insecure = $insecure; } //Specify the root directory for absolute filenames. This can be used //when converting a local file that uses absolute paths to refer to web //resources. For example, /images/logo.jpg can be //rewritten to /usr/share/images/logo.jpg by specifying "/usr/share" as the root. //fileRoot: The path to prepend to absolute filenames. public function setFileRoot($fileRoot) { $this->fileRoot = $fileRoot; } // Specify whether fonts should be embedded in the output PDF file. Fonts // will be embedded by default unless explicitly disabled. // embedFonts: False to disable PDF font embedding. public function setEmbedFonts($embedFonts) { $this->embedFonts = $embedFonts; } // Specify whether embedded fonts should be subset. // Fonts will be subset by default unless explicitly disabled. // subsetFonts: False to disable PDF font subsetting. public function setSubsetFonts($subsetFonts) { $this->subsetFonts = $subsetFonts; } // Specify whether compression should be applied to the output PDF file. // Compression will be applied by default unless explicitly disabled. // compress: False to disable PDF compression. public function setCompress($compress) { $this->compress = $compress; } // Specify whether encryption should be applied to the output PDF file. // Encryption will not be applied by default unless explicitly enabled. // encrypt: True to enable PDF encryption. public function setEncrypt($encrypt) { $this->encrypt = $encrypt; } // Set the parameters used for PDF encryption. Calling this method will // also enable PDF encryption, equivalent to calling setEncrypt(true). // keyBits: The size of the encryption key in bits (must be 40 or 128). // userPassword: The user password for the PDF file. // ownerPassword: The owner password for the PDF file. // disallowPrint: True to disallow printing of the PDF file. // disallowModify: True to disallow modification of the PDF file. // disallowCopy: True to disallow copying from the PDF file. // disallowAnnotate: True to disallow annotation of the PDF file. public function setEncryptInfo($keyBits, $userPassword, $ownerPassword, $disallowPrint = false, $disallowModify = false, $disallowCopy = false, $disallowAnnotate = false) { if ($keyBits != 40 && $keyBits != 128) { throw new Exception("Invalid value for keyBits: $keyBits" . " (must be 40 or 128)"); } $this->encrypt = true; $this->encryptInfo = ' --key-bits ' . $keyBits . ' --user-password="' . $this->cmdlineArgEscape2($this->cmdlineArgEscape1($userPassword)) . '" --owner-password="' . $this->cmdlineArgEscape2($this->cmdlineArgEscape1($ownerPassword)) . '" '; if ($disallowPrint) { $this->encryptInfo .= '--disallow-print '; } if ($disallowModify) { $this->encryptInfo .= '--disallow-modify '; } if ($disallowCopy) { $this->encryptInfo .= '--disallow-copy '; } if ($disallowAnnotate) { $this->encryptInfo .= '--disallow-annotate '; } } // Convert an XML or HTML file to a PDF file. // The name of the output PDF file will be the same as the name of the // input file but with an extension of ".pdf". // xmlPath: The filename of the input XML or HTML document. // msgs: An optional array in which to return error and warning messages. // Returns true if a PDF file was generated successfully. public function convert_file($xmlPath, &$msgs = array()) { $pathAndArgs = $this->getCommandLine(); $pathAndArgs .= '"' . $xmlPath . '"'; return $this->convert_internal_file_to_file($pathAndArgs, $msgs); } // Convert an XML or HTML file to a PDF file. // xmlPath: The filename of the input XML or HTML document. // pdfPath: The filename of the output PDF file. // msgs: An optional array in which to return error and warning messages. // Returns true if a PDF file was generated successfully. public function convert_file_to_file($xmlPath, $pdfPath, &$msgs = array()) { $pathAndArgs = $this->getCommandLine(); $pathAndArgs .= '"' . $xmlPath . '" -o "' . $pdfPath . '"'; return $this->convert_internal_file_to_file($pathAndArgs, $msgs); } //Convert multiple XML or HTML files to a PDF file. // xmlPaths: An array of the input XML or HTML documents. // msgs: An optional array in which to return error and warning messages. // Returns true if a PDF file was generated successfully. public function convert_multiple_files($xmlPaths, $pdfPath, &$msgs = array()) { $pathAndArgs = $this->getCommandLine(); foreach($xmlPaths as $xmlPath) { $pathAndArgs .= '"' . $xmlPath . '" '; } $pathAndArgs .= '-o "' . $pdfPath . '"'; return $this->convert_internal_file_to_file($pathAndArgs, $msgs); } // Convert multiple XML or HTML files to a PDF file, which will be passed // through to the output buffer of the current PHP page. // xmlPaths: An array of the input XML or HTML documents. // Returns true if a PDF file was generated successfully. public function convert_multiple_files_to_passthru($xmlPaths) { $pathAndArgs = $this->getCommandLine(); $pathAndArgs .= '--silent '; foreach($xmlPaths as $xmlPath) { $pathAndArgs .= '"' . $xmlPath . '" '; } $pathAndArgs .= '-o -'; return $this->convert_internal_file_to_passthru($pathAndArgs); } // Convert an XML or HTML file to a PDF file, which will be passed // through to the output buffer of the current PHP page. // xmlPath: The filename of the input XML or HTML document. // Returns true if a PDF file was generated successfully. public function convert_file_to_passthru($xmlPath) { $pathAndArgs = $this->getCommandLine(); $pathAndArgs .= '--silent "' . $xmlPath . '" -o -'; return $this->convert_internal_file_to_passthru($pathAndArgs); } // Convert an XML or HTML string to a PDF file, which will be passed // through to the output buffer of the current PHP page. // xmlString: A string containing an XML or HTML document. // Returns true if a PDF file was generated successfully. public function convert_string_to_passthru($xmlString) { $pathAndArgs = $this->getCommandLine(); $pathAndArgs .= '--silent -'; return $this->convert_internal_string_to_passthru($pathAndArgs, $xmlString); } // Convert an XML or HTML string to a PDF file. // xmlString: A string containing an XML or HTML document. // pdfPath: The filename of the output PDF file. // msgs: An optional array in which to return error and warning messages. // Returns true if a PDF file was generated successfully. public function convert_string_to_file($xmlString, $pdfPath, &$msgs = array()) { $pathAndArgs = $this->getCommandLine(); $pathAndArgs .= ' - -o "' . $pdfPath . '"'; return $this->convert_internal_string_to_file($pathAndArgs, $xmlString, $msgs); } // Old name for backwards compatibility public function convert1($xmlPath, &$msgs = array()) { return $this->convert_file($xmlPath, $msgs); } // Old name for backwards compatibility public function convert2($xmlPath, $pdfPath, &$msgs = array()) { return $this->convert_file_to_file($xmlPath, $pdfPath, $msgs); } // Old name for backwards compatibility public function convert3($xmlString) { return $this->convert_string_to_passthru($xmlString); } private function getCommandLine() { $cmdline = $this->exePath . ' --server ' . $this->styleSheets . $this->scripts . $this->fileAttachments; if ($this->inputType == "auto") { } else { $cmdline .= '-i "' . $this->inputType . '" '; } if ($this->javascript) { $cmdline .= '--javascript '; } if ($this->baseURL != '') { $cmdline .= '--baseurl="' . $this->baseURL . '" '; } if ($this->doXInclude == false) { $cmdline .= '--no-xinclude '; } if ($this->httpUser != '') { $cmdline .= '--http-user="' . $this->httpUser . '" '; } if ($this->httpPassword != '') { $cmdline .= '--http-password="' . $this->httpPassword . '" '; } if($this->httpProxy != '') { $cmdline .= '--http-proxy="' . $this->httpProxy . '" '; } if($this->insecure) { $cmdline .= '--insecure '; } if ($this->logFile != '') { $cmdline .= '--log="' . $this->logFile . '" '; } if($this->fileRoot != '') { $cmdline .= '--fileroot="' . $this->fileRoot . '" '; } if($this->licenseFile != '') { $cmdline .= '--license-file="' . $this->licenseFile . '" '; } if($this->licenseKey != '') { $cmdline .= '--license-key="' . $this->licenseKey . '" '; } if ($this->embedFonts == false) { $cmdline .= '--no-embed-fonts '; } if ($this->subsetFonts == false) { $cmdline .= '--no-subset-fonts '; } if ($this->compress == false) { $cmdline .= '--no-compress '; } if ($this->encrypt) { $cmdline .= '--encrypt ' . $this->encryptInfo; } return $cmdline; } private function convert_internal_file_to_file($pathAndArgs, &$msgs) { $descriptorspec = array( 0 => array("pipe", "r"), 1 => array("pipe", "w"), 2 => array("pipe", "w") ); $process = proc_open($pathAndArgs, $descriptorspec, $pipes); if (is_resource($process)) { $result = $this->readMessages($pipes[2], $msgs); fclose($pipes[0]); fclose($pipes[1]); fclose($pipes[2]); proc_close($process); return ($result == 'success'); } else { throw new Exception("Failed to execute $pathAndArgs"); } } private function convert_internal_string_to_file($pathAndArgs, $xmlString, &$msgs) { $descriptorspec = array( 0 => array("pipe", "r"), 1 => array("pipe", "w"), 2 => array("pipe", "w") ); $process = proc_open($pathAndArgs, $descriptorspec, $pipes); if (is_resource($process)) { fwrite($pipes[0], $xmlString); fclose($pipes[0]); fclose($pipes[1]); $result = $this->readMessages($pipes[2], $msgs); fclose($pipes[2]); proc_close($process); return ($result == 'success'); } else { throw new Exception("Failed to execute $pathAndArgs"); } } private function convert_internal_file_to_passthru($pathAndArgs) { $descriptorspec = array( 0 => array("pipe", "r"), 1 => array("pipe", "w"), 2 => array("pipe", "w") ); $process = proc_open($pathAndArgs, $descriptorspec, $pipes); if (is_resource($process)) { fclose($pipes[0]); fpassthru($pipes[1]); fclose($pipes[1]); $result = $this->readMessages($pipes[2], $msgs); fclose($pipes[2]); proc_close($process); return ($result == 'success'); } else { throw new Exception("Failed to execute $pathAndArgs"); } } private function convert_internal_string_to_passthru($pathAndArgs, $xmlString) { $descriptorspec = array( 0 => array("pipe", "r"), 1 => array("pipe", "w"), 2 => array("pipe", "w") ); $process = proc_open($pathAndArgs, $descriptorspec, $pipes); if (is_resource($process)) { fwrite($pipes[0], $xmlString); fclose($pipes[0]); fpassthru($pipes[1]); fclose($pipes[1]); $result = $this->readMessages($pipes[2], $msgs); fclose($pipes[2]); proc_close($process); return ($result == 'success'); } else { throw new Exception("Failed to execute $pathAndArgs"); } } private function readMessages($pipe, &$msgs) { while (!feof($pipe)) { $line = fgets($pipe); if ($line != false) { $msgtag = substr($line, 0, 4); $msgbody = rtrim(substr($line, 4)); if ($msgtag == 'fin|') { return $msgbody; } else if ($msgtag == 'msg|') { $msg = explode('|', $msgbody, 4); // $msg[0] = 'err' | 'wrn' | 'inf' // $msg[1] = filename / line number // $msg[2] = message text, trailing newline stripped $msgs[] = $msg; } else { // ignore other messages } } } return ''; } //Puts double-quotes around space(s) in file path. //This is needed if the file path is used in a command line. private function addDoubleQuotes($str) { $len = strlen($str); $outputStr = ''; $numSpaces = 0; $subStrStart = 0; for ($i = 0; $i < $len; $i++) { if($str[$i] == ' ') { if($numSpaces == 0) { $outputStr .= substr($str, $subStrStart, ($i - $subStrStart)); $spaceStart = $i; } $numSpaces += 1; } else { if($numSpaces > 0) { $outputStr .= chr(34) . substr($str, $spaceStart, $numSpaces) . chr(34); $subStrStart = $i; $numSpaces = 0; } } } $outputStr .= substr($str, $subStrStart, ($i - $subStrStart)); return $outputStr; } //In the input string $argStr, a double quote with zero or more preceding backslash(es) //will be replaced with: n*backslash + doublequote => (2*n+1)*backslash + doublequote private function cmdlineArgEscape1($argStr) { //chr(34) is character double quote ( " ), chr(92) is character backslash ( \ ). $len = strlen($argStr); $outputStr = ''; $numSlashes = 0; $subStrStart = 0; for($i = 0; $i < $len; $i++) { if($argStr[$i] == chr(34)) { $numSlashes = 0; $j = $i - 1; while($j >= 0) { if($argStr[$j] == chr(92)) { $numSlashes += 1; $j -= 1; } else { break; } } $outputStr .= substr($argStr, $subStrStart, ($i - $numSlashes - $subStrStart)); for($k = 0; $k < $numSlashes; $k++) { $outputStr .= chr(92) . chr(92); } $outputStr .= chr(92) . chr(34); $subStrStart = $i + 1; } } $outputStr .= substr($argStr, $subStrStart, ($i - $subStrStart)); return $outputStr; } //Double the number of trailing backslash(es): n*trailing backslash => (2*n)*trailing backslash. private function cmdlineArgEscape2($argStr) { //chr(92) is character backslash ( \ ). $len = strlen($argStr); $numTrailingSlashes = 0; for($i = ($len - 1); $i >= 0; $i--) { if($argStr[$i] == chr(92)) { $numTrailingSlashes += 1; } else { break; } } while($numTrailingSlashes > 0) { $argStr .= chr(92); $numTrailingSlashes -= 1; } return $argStr; } } ?>