Forum How do I...?

Trouble getting Prince to work through PHP

douglas.sesar
Hello,

I am very new to Prince xml and have recently had Prince 8.0 installed onto my Linux Centos 5.7 server with Apache 2.3 and PHP 5.3.8 through the hosting company with all dependencies. It has been installed and is available at /usr/lib/prince/bin/prince on the server. Msttcorefonts, chkfontconfig, libgif, and cabextract have been installed also.

The program runs correctly through command line, but something seems to be preventing it from being called through PHP;

I have Atomic Secured Linux on the server. I have went through each php function in prince.php to make sure it was allowed on ASL.


http://mrbconline.org/new_prince/test4.php is my testing php code:

<?php
//header('Content-Type: application/pdf');
header('Content-Disposition: inline; filename="file.pdf"');
?>

</head>

<body>

<?php
require "prince.php";

$prince = new Prince('/usr/lib/prince/bin/prince');
if(!$prince) die("<p>Prince instantiation failed</p>");
else echo "Prince instantiation OK<br />";

echo("<p>Server Document Root = " . $_SERVER['DOCUMENT_ROOT'] . "</p>");
$logLoc = $_SERVER['DOCUMENT_ROOT'] . '/new_prince/prince_error.log';
echo("<p>Log file to $logLoc</p>");

if(!$prince->setLog($logLoc))die("<p>Error setting error log to $logLoc</p>");
$xmlString="<h1>Hello World</h1><p>This is a test. Did you guess?</p>";
if(!$prince->convert_string_to_passthru($xmlString))die("Error running Prince");

convert_string_to_passthru($xmlString);

?>


The log file is http://mrbconline.org/new_prince/prince_error.log

I requested help from my host and this was their response:

We have manually set the permissions on the log file, allowing both your site user and apache to write to it.

Hi, am not a php expert to troubleshoot this issue through to a resolution. The php scripts appear to be executed as 'apache' uid. I have tested and can confirm that both 'apache' and 'mrbconline' are able to write to that logfile. I have made the .php echo some lines into the logfile and that worked successfully as well. The linked test4.php script appears to be calling a function that attempts to set a variable. This variable is properly set but the script thinks that it has failed. I am able to make the script realize it did not fail by adding a 'return 1' to the setLog function in prince.php.

After this issue the script appears to attempt to convert a file as a test. It is claiming that this test fails. The prince_error.log shows the following:

Fri Feb 10 01:47:46 2012: Loading document...
Fri Feb 10 01:47:46 2012: -:1: error: Extra content at the end of the document
Fri Feb 10 01:47:46 2012: -: error: could not load input file
Fri Feb 10 01:47:46 2012: error: no input documents to process
Fri Feb 10 01:47:46 2012: finished: failure
Fri Feb 10 01:47:46 2012: ---- end

The function that is called for this is convert_string_to_passthru which calls it with a line of text as an argument. This function appears to be expecting a path to a file instead. As a result I believe these tests failing are issues with the php coding but I cannot spend much time debugging a test script.

Best Regards,


I actually still cannot get anything to write to prince_error.log like this host support did.

I have been trying to get Prince to run through PHP for a few weeks now, fixing what I could through your great forum. I would love some help on this issue.

Take Care,
Doug
mikeday
Call prince->setHTML(1), otherwise Prince will parse the string as XML, which it isn't. We're going to make this the default in future.
douglas.sesar
new code:
<?php
header('Content-Type: application/pdf');
header('Content-Disposition: inline; filename="file.pdf"');
?>

</head>

<body>

<?php
require "prince.php";

$prince = new Prince('/usr/lib/prince/bin/prince');
if(!$prince) die("<p>Prince instantiation failed</p>");
else echo "Prince instantiation OK<br />";

$prince->setHTML(1);

echo("<p>Server Document Root = " . $_SERVER['DOCUMENT_ROOT'] . "</p>");
$logLoc = $_SERVER['DOCUMENT_ROOT'] . '/new_prince/prince_error.log';
echo("<p>Log file to $logLoc</p>");

if(!$prince->setLog($logLoc))die("<p>Error setting error log to $logLoc</p>");
$xmlString="<h1>Hello World</h1><p>This is a test. Did you guess?</p>";
if(!$prince->convert_string_to_passthru($xmlString))die("Error running Prince");

convert_string_to_passthru($xmlString);


This code returns the error:
File does not begin with '$PDF-'.
mikeday
Comment out the Content-Disposition header, save the PDF file and check if it begins with some HTML or other content generated by the PHP page, or if it is zero size.
douglas.sesar
It would only allow me to save a pdf file if I left the Content-Disposition header in. If I commented out that line, I could only save a php script from the browser (in google chrome). I got no results at all with mozilla firefox.

When I saved the PDF file by right-clicking in google chrome, it was 1KB, but I could not open it to see what was inside. It said:
Acrobat could not open 'file.pdf' because it is either not a supported file type or because the file has been damaged (for example, it was sent as an email attachment and wasn't correctly decoded).

To create an Adobe PDF document, go to the source application. Then print the document to Adobe PDF.
mikeday
You will need to open it in an editor, eg. Notepad.
douglas.sesar
This is the text of file.pdf when opened with a text editor:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Untitled Document</title>

</head>

<body>

Prince instantiation OK<br /><p>Server Document Root = /var/www/vhosts/mrbconline.org/httpdocs</p><p>Log file to /var/www/vhosts/mrbconline.org/httpdocs/new_prince/prince_error.log</p><p>Error setting error log to /var/www/vhosts/mrbconline.org/httpdocs/new_prince/prince_error.log</p>
mikeday
So the PHP page is generating lots of HTML. It can't do that if you want to use convert_string_to_passthru() to return a PDF directly to the browser, otherwise the generated HTML will be mixed up with the generated PDF. You must make sure that the PHP page does not emit any HTML at all if the content-type is application/pdf.
douglas.sesar
Thank you so much!

I had no idea that the document was not allowed to return any html.

Here is the entire test code and result:

<?php
header('Content-Type: application/pdf');
header('Content-Disposition: inline; filename="file.pdf"');
?>

<?php
require "prince.php";

$prince = new Prince('/usr/lib/prince/bin/prince');
if(!$prince) die("Prince instantiation failed");


$prince->setHTML(1);



$xmlString="<h1>Hello World</h1><p>This is a test. Did you guess?</p>";
if(!$prince->convert_string_to_passthru($xmlString))die("Error running Prince");

convert_string_to_passthru($xmlString);

?>



Thank you for your patience with me on this issue.
  1. file.pdf30.3 kB
    FINALLY!
mikeday
That's just about perfect output. There does seem to be a single blank line at the beginning of the file that isn't necessary, perhaps that is caused by the gap between the two PHP sections:
header('Content-Disposition: inline; filename="file.pdf"');
?>

<?php

Maybe you could merge these into one section?