Forum How do I...?

Cannot get Prince to apply stylesheet from php

zambianmadness
HI there,
I am having trouble applying a stylesheet to the generated PDF when called from PHP. After modifing the prince interface code to get around apache running as a less privileged user I started getting PDF reports but despite attempting lots of different ways of specifing the stylesheet, it never gets applied through my php code. The prince interface change I made was:
	$process = proc_open(escapeshellcmd($pathAndArgs), $descriptorspec, $pipes, NULL, NULL,
    array('bypass_shell' => TRUE));


I added some debug to the php interface class to show me the command being run. Output is as follows:
C:/Program Files/Prince/Engine/bin/prince.exe --server -s ^"C:/Documents and Settings/All Users/Documents/eclipse/svn/taonga/trunk/web/styles.css^" --input=html --log=^"C:^\Temp^\errors.log^" --silent -

I have run a similiar command from the command line, leaving out the server argument and adding the input/output arguments and everything works fine.

I have tried the following in my code
1.
$prince = new Prince('C:/Program Files/Prince/Engine/bin/prince.exe');

$prince -> setHTML(true);
$prince -> setBaseURL("http://127.0.0.1/taonga");
$prince -> addStyleSheet('http://127.0.0.1/taonga/styles.css');
$prince -> setLog("C:\\Temp\\errors.log");
$result = $prince -> convert_string_to_passthru($html);


2.
$prince = new Prince('C:/Program Files/Prince/Engine/bin/prince.exe');

$prince -> setHTML(true);

$prince -> addStyleSheet('C:/styles.css');
$prince -> setLog("C:\\Temp\\errors.log");
$result = $prince -> convert_string_to_passthru($html);


Interstingly, I can't get the code to produce an error log either (perhaps because the pdf is being created?) and even though I have also enabled the verbose (-v) option I am unable to debug what is going on.

Any help would be greatly appreciated as it seems like a pretty straightforward process but I'm obviously missing something...

Thanks in advance,
David
http://zambianmadness.blogspot.com/

Caffeine Free Coder

mikeday
An error log would help here. Does the PHP script have write access to C:\Temp? How about C:\Windows\Temp?
zambianmadness
Hi Mike,
Yes, I agree a log would be very useful. However I don't seem to be able to generate one, either in C:\Temp, C:\Windows\Temp or my desktop (C:\Documents and Settings\General\Desktop). Interestingly when I view the properties of any folder in my windows environment using the properties menu option, every directory is marked as readonly but I can still write in there either as a regular user or as a service (e.g. MySQL writing to C:\Documents and Settings\All Users\Application Data\MySQL\MySQL Server 5.1\data). This may be a side-effect of running two users on my computer (a "limited account" and an administrator account). I have tried generating a report using both accounts but as expected (because the service runs using the system account) the result was the same in both cases. Finally I tried setting the logon account of the service as the administrator account. This only resulted in creating a prince process for every request and each process continuously used 50% CPU. When I made a second request from the php page, another prince process was created bringing my CPU usage to 100%. I duely undid the change :)

If I do an ls -l at C:\ with cygwin then I see
drwxrwxrwt+ 1 General        None              0 Mar  9 09:21 Temp

so the service should be able to write to this directory.

Any ideas Mike?
Thanks in advance...
David

Caffeine Free Coder

mikeday
Okay, if you can't create a log file, try calling the convert_file() method and pass an empty msgs array to collect any error/warning messages there. You don't care if the PDF is actually generated, just about any messages that are produced during the process. Your PHP script can echo these in its HTML output so that you can see them in the browser.
zambianmadness
Hi Mike,
Thanks so much for the pointer, didn't look at the method signature for any of the other methods. I duly made the change you suggested, then made my own change to actually populate $msgs (???) as follows
	    
    private function readMessages($pipe, &$msgs)
    {
	while (!feof($pipe))
	{
	    $line = fgets($pipe);
	    array_push($msgs, $line);
                 ...
. Otherwise I can't see how $msgs gets populated and I was getting an empty array when I used print_r on the returned array.

Anyway, I digress. The problem seemed to be the space between Program and Files in C:\Program Files\Prince. I uninstalled and reinstalled prince in C:\Prince and now it is happy. I get the output I wanted and a load of fun messages in $msgs (which I list below for reference). I still have to try the passthru method but am feeling confident. I'm still not sure why it was ok when I tried it on the command line but regardless, I am a very happy camper.

Thanks Mike!

sta|Loading document... msg|inf||loading HTML input: - Arraymsg|inf||loading style sheet: C:/styles.css Arraymsg|inf||loading style sheet: styles.css Arraymsg|wrn|styles.css|can't open input file: No such file or directory Arraysta|Converting document... prg|0 msg|inf||used font: Times New Roman, Bold Arraymsg|inf||used font: Times New Roman, Regular Arrayprg|25 prg|25 prg|51 prg|51 prg|74 prg|74 prg|100 fin|success Array ( [0] => sta|Loading document... [1] => msg|inf||loading HTML input: - [2] => Array ( [0] => inf [1] => [2] => loading HTML input: - ) [3] => msg|inf||loading style sheet: C:/styles.css [4] => Array ( [0] => inf [1] => [2] => loading style sheet: C:/styles.css ) [5] => msg|inf||loading style sheet: styles.css [6] => Array ( [0] => inf [1] => [2] => loading style sheet: styles.css ) [7] => msg|wrn|styles.css|can't open input file: No such file or directory [8] => Array ( [0] => wrn [1] => styles.css [2] => can't open input file: No such file or directory ) [9] => sta|Converting document... [10] => prg|0 [11] => msg|inf||used font: Times New Roman, Bold [12] => Array ( [0] => inf [1] => [2] => used font: Times New Roman, Bold ) [13] => msg|inf||used font: Times New Roman, Regular [14] => Array ( [0] => inf [1] => [2] => used font: Times New Roman, Regular ) [15] => prg|25 [16] => prg|25 [17] => prg|51 [18] => prg|51 [19] => prg|74 [20] => prg|74 [21] => prg|100 [22] => fin|success ) 

Caffeine Free Coder

mikeday
I thought this code later on was to populate $msgs with the exploded message:
$msg = explode('|', $msgbody, 4);

// $msg[0] = 'err' | 'wrn' | 'inf'
// $msg[1] = filename / line number
// $msg[2] = message text, trailing newline stripped

$msgs[] = $msg;