Forum How do I...?

1 2 Next

Loading network or remote https images

oamobile
I’m using the PHP wrapper and am producing a PDF with the pass through string method.

I ideally want to include some images stored on a network share but have been unable to get it to work. Logs state no such file or directory.

I have then tried to use a external url to pull the images but still I can’t get it to work. Logs state cannot resolve host.

Is there a switch of some sort that is preventing loading the images? It works fine as html viewed in the browser?

Many thanks
mikeday
Can you try running Prince from the command-line first and see if you encounter similar issues?
oamobile
I don’t think I can as the html is generated dynamically in PHP
mikeday
Perhaps access the page with the browser and save the HTML it generates? At the very least it helps to see exactly what is ending up in the input document.

Are the image paths absolute? If they are relative then you will need to make sure that the document has a valid base URL to resolve them against.
oamobile
Hi - urls are absolute (they are referring to an external website). It works when I use the command line. When through PHP though it just shows the href alt description.

I would actually prefer to use a mapped network drive rather than pulling them across the internet. I’ve tried mapping the drive in PHP and also in Windows but neither seem to work. If this isn’t possible then pulling from the internet is the fallback option
oamobile
Hi Mike - any pointers for getting either of these methods to work? Seems to work with the command line but not in PHP
mikeday
Would you be able to email me (mikeday@yeslogic.com) the log showing the errors?
oamobile
Hi Mike, the logs show nothing but these two lines depending if I try the network path or https url... (i've removed the domain for security - have confirmed the url is valid and opens in a browser)

URL:
https://xxxxx.co.uk/images/012E486C-DA2C-47BE-91BA-2B9B53238D3E.jpg: warning: Could not resolve host: xxxxx.co.uk

Network:
E://images/FF52B545-9356-4D3C-9795-D45F1026A108.jpg: warning: can't open input file: No such file or directory
oamobile
I've just tried a different web server with a different domain, checked the url definitely is valid and still says it can't resolve the host xxxxx.com
oamobile
This works...
$file = "C:/Images/".$img['filename'];
$tablesHtml .= '<a href="'.$img['url'].'" target="_blank"><img class="tbl-photo" src="'.$file.'" alt="'.$img['filename'].'"></a>';

This doesn't...
$file = "E:/Images/".$img['filename'];
$tablesHtml .= '<a href="'.$img['url'].'" target="_blank"><img class="tbl-photo" src="'.$file.'" alt="'.$img['filename'].'"></a>';

This doesn't either...
$tablesHtml .= '<a href="'.$img['url'].'" target="_blank"><img class="tbl-photo" src="'.$img['url'].'" alt="'.$img['filename'].'"></a>';


PHP can definitely write to the E: drive, as the images are placed there by a PHP script to start with.

I've tried adding file:// or file://// to the path but still no sucesss

Edited by oamobile

mikeday
It's starting to look as if Prince is being run with reduced permissions or under a different user that prevents it from making network requests or accessing network shared drives. Could you check the security settings for your web server in relation to external programs?
oamobile
Thanks Mike, I'm not really sure where to find such settings, i'm using IIS. I am creating the image files in PHP and storing them on the network share so I'm not sure if this rules out permissions or not. I can also load the images in a simple php script and display in the browser
oamobile
Hi Mike, still struggling with this, I can't find anything that might be restricting the permissions anywhere, do you have any ideas that could point me in the right direction?

Many thanks
mikeday
I see various similar questions online like this one, but your PHP script can successfully access the shared drive itself when run through the web server, is that correct?

It seems that you can check which user it will run external programs as like this, then perhaps you can see what permissions that user has?
oamobile
Thanks Mike.

I haven't got the network path to work in the browser when I output as an html page. When I paste the path to the image using either the mapped drive (file:///E:/images...) or the full UNC path (file://///192.168.1.5...) into the browser, the images displays though, so I'm wondering if its something to do with browser restrictions not showing the images as an html page.

I've tried setting the network share to full access to everyone and still no joy.

The external https URLs do work in the browser however, perhaps it will be easier to get this working rather than the network access as it removes the permissions out the process completely but I can't find any reason why Prince can't resolve the host name for the URL and won't pull the images?

Edited by oamobile

oamobile
I've just tried using a URL to an image on the Prince site, works fine when outputting to an html page, doesn't work on the PDF.

Code:
<img class="report-photo" src="https://www.princexml.com/images/Prince14-banner.png" alt="https://www.princexml.com/images/Prince14-banner.png">

Prince Log:
Mon Oct 4 12:28:32 2021: ---- begin
Mon Oct 4 12:28:32 2021: https://www.princexml.com/images/Prince14-banner.png: warning: Could not resolve host: www.princexml.com
Mon Oct 4 12:28:33 2021: finished: success
Mon Oct 4 12:28:33 2021: ---- end

mikeday
It looks like the program doesn't have access to the network when run under PHP/IIS, but at this stage I'm not sure exactly where that issue is coming from. Presumably the starting point is figuring out which user is used for external programs launched with proc_open as discussed in the second link above, then what permissions that user account currently has.
oamobile
I've just tried using an IP address in the url instead of a domain name and it works!

So it seems that the log saying Prince can't resolve the hostname is correct, perhaps it cannot access DNS for some reason?
oamobile
I think I have a workaround, it seems it can access the web server using its internal IP address when used in a URL rather than a UNC path.

I've therefore created another website on the web server, changed the default port to one that isn't port-forwarded from the router and therefore can be used internally only and then using the IP address of the server instead of the public domain name.

Therefore the code is as follows:

<img src="http://192.168.1.5:8082/images/img01.jpg">


It doesn't resolve the problem of not being able to access the network share or the resolving domain names but its a solution for now.

Many thanks for your help

Edited by oamobile

alfie
Hi oamobile,

> When I paste the path to the image using either the mapped drive
> (file:///E:/images...) or the full UNC path (file://///192.168.1.5...) into
> the browser, the images displays though, so I'm wondering if its
> something to do with browser restrictions not showing the images
> as an html page.
>
> ...
>
> The external https URLs do work in the browser however, perhaps
> it will be easier to get this working rather than the network access
> as it removes the permissions out the process completely but I
> can't find any reason why Prince can't resolve the host name for the
> URL and won't pull the images?

From my reading of the above, it looks like your browser directly accessing these paths does not have any issues at all, and so the problem is somewhere within your IIS configuration.

> I think I have a workaround, it seems it can access the web server
> using its internal IP address when used in a URL rather than a UNC
> path.

This is starting to sound like a DNS issue to me. To rule out if Prince is the issue here, and to confirm it is DNS, are you able to run the following two PHP scripts from IIS so we can debug further?

1:

$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, "103.102.166.224");
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
echo curl_exec($curl);

2:
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, "https://www.wikipedia.org");
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
echo curl_exec($curl);

Both scripts should return a HTML response from Wikipedia's web server. If however the second one fails, that would suggest that your IIS server is blocking DNS queries, and so Prince won't be able to resolve anything on the network.


oamobile
Hi Alfie, thanks for the reply.

I've tried both and they both work
alfie
Thanks for confirming that DNS works from IIS.

I'm now suspecting it's a permissions issue. The PHP Wrapper uses `proc_open()` underneath, so the following should test if DNS is working within that system call under IIS:

  $fds = [
      ["pipe", "r"],
      ["pipe", "w"],
  ];


  $process = proc_open("curl https://www.wikipedia.org", $fds, $pipes, "");
  echo stream_get_contents($pipes[1]);


Again, if it's all working ok, you should see a HTML response from Wikipedia's servers.

Edited by alfie

oamobile
Thanks Alfie,

This fails. I get the following...

Warning: proc_open(): CreateProcess failed, error code: 123 in C:\inetpub\wwwroot\create_pdf.php on line 20

Warning: Trying to access array offset on value of type null in C:\inetpub\wwwroot\create_pdf.php on line 20

Fatal error: Uncaught TypeError: stream_get_contents(): Argument #1 ($stream) must be of type resource, null given in C:\inetpub\wwwroot\create_pdf.php:20 Stack trace: #0 C:\inetpub\wwwroot\create_pdf.php(20): stream_get_contents() #1 {main} thrown in C:\inetpub\wwwroot\create_pdf.php on line 20
oamobile
After a look on the web, I've tried the following:

$descriptorspec = array(
       0 => array("pipe", "r"),
       1 => array("pipe", "w"), 
       2 => array("file", "C:/inetpub/wwwroot/error-output.txt", "a") 
    );

    $process = proc_open('curl https://www.wikipedia.org', $descriptorspec, $pipes);

    if (is_resource($process)) {

    fwrite($pipes[0], '<?php print_r($_ENV); ?>');
    fclose($pipes[0]);

    echo stream_get_contents($pipes[1]);
    fclose($pipes[1]);


    $return_value = proc_close($process);

    echo "command returned $return_value\n";


Output is...
command returned 1 



The error log states...
'curl' is not recognized as an internal or external command,
operable program or batch file.


So there is a problem running curl by the looks of it, I guess its not installed (I'm running IIS on Windows)

Edited by oamobile

oamobile
Not sure if this is a conclusive test but but I tried changing the proc_open curl command to "nslookup 8.8.8.8" and it correctly returns the google domain name and vice versa, it can return the IP address of google.com

Edited by oamobile

alfie
Great that you got proc_open() is working.

Are you able to tell me the following versions of:

- Windows
- IIS
- PHP

As for curl, on my Windows 10 machine curl is installed at c:\Windows\System32\curl.exe, but if it's not there, you can find the path (if it's installed on your server) with the following:

  cd \
  dir curl.exe /s


However, as you've shown that the nslookup 8.8.8.8 command works, let's stick with that command for now. Could you try replacing nslookup 8.8.8.8 with nolookup google.com please? If DNS is working via proc_open(), you should see something like the following and paste the output:

  Non-authoritative answer:
  Name:	google.com
  Address: 142.250.187.174

Edited by alfie

oamobile
Thanks Alfie - yes its able to resolve google.com (and others I've tested) and returns the IP addresses

I'm running Windows 2016 Server, IIS v10.0.14 and PHP v8

I don't have curl installed
oamobile
I've stripped back all my code to just the following lines and still the same error in the log of cannot resolve hostname...

$prince = new Prince('C:\Program Files (x86)\Prince\engine\bin\prince.exe');
$prince->setLog('C:\\inetpub\\wwwroot\\prince.log');
$html = '<img src="https://www.princexml.com/images/Prince14-banner.png" alt="Image here">';
$file = "C:/inetpub/wwwroot/output.pdf";
$result = $prince->convert_string_to_file($html, $file);


Wed Oct  6 11:20:27 2021: ---- begin
Wed Oct  6 11:20:27 2021: https://www.princexml.com/images/Prince14-banner.png: warning: Could not resolve host: www.princexml.com
Wed Oct  6 11:20:27 2021: finished: success
Wed Oct  6 11:20:27 2021: ---- end


echo $html works no problem

Edited by oamobile

oamobile
Just found I do have curl, i missed the /s switch off the dir command.

Tried it, I got "curl: (1) Protocol https not supported or disabled in libcurl" in the error log

I changed the url to an http url and it displays the site, so confirms that DNS is working for curl also

Edited by oamobile

alfie
Ok, great. Now that we have curl, let's see if we can narrow down the problem to the host itself vs an IIS+PHP configuration issue.

Are you able to run the following on the server command line please:

curl https://www.wikipedia.org


Just to confirm, there's a "s" there to indicate Secure HTTP. You should see a stream of HTML fly past. If that doesn't work, could you do the same curl command but without the "s" to indicate plain-text.

Let us know how you go.
oamobile
With https I get the following in the error log...
curl: (1) Protocol https not supported or disabled in libcurl


if it change it to http it doesn't do much but if it change it to a site I know works on http, it loads the site in the browser, which must confirms DNS is working for curl?
alfie
If it's loading in the browser, then yes, it does look like DNS is working from your browser. However, Prince uses curl under the hood to fetch network resources, so I'm trying to see where the problem may be.

Although it sounds unlikely, I've just found many forum posts online that curl can behave funny on Windows unless double quotes are used (and "Protocol https not supported or disabled in libcurl" being the error everyone seems to be getting).

From the command line, can you try this please:

  curl "https://www.wikipedia.org"
oamobile
Same error
curl: (1) Protocol https not supported or disabled in libcurl
oamobile
Don't know if its relevant but curl is installed from Visual Studio...

C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\Common7\IDE\Extensions\aqwf5fqp.2lv\lib\knockout-mapping\build\tools>
alfie
Thinking about how curl is used in Prince, I don't think it matters as we ship our own version of the library. However, the fact that it's still not working from the command line does seem relevant to your problem.

Could you turn on debugging, and past everything you see up until the "<!DOCTYPE html>" line (should be within the first 100 lines). Again, from the command line and not within IIS+PHP:

  curl -v https://www.wikipedia.org
oamobile
When you say turn on debugging is that an additional step or just the cmd above?

If just the cmd then I just get the same error as before
oamobile
Also, just to add, I tried loading an image from an http address into the PDF instead of an https address and it still doesn't resolve the hostname
alfie
> When you say turn on debugging is that an additional step or just the cmd above?

Yes, the -v turns on debugging for curl.

Are you able to paste the actual output of that command (from the beginning to the "<!DOCTYPE html>" line) so I can try and see where the issue is?
oamobile
It doesn't output anything other than error. I'm running this from the Windows Command Prompt, is that right?
oamobile
I get the verbose output if I swich it to http. Https just that error
oamobile
Maybe the version of curl I have doesn't support https.

Should we try and troubleshoot using http as it presents the same error with the PHP wrapper?
alfie
Yes, it looks like your curl doesn't support https for some reason.

Ok, let's try a plaintext website - first on the command line, and then in IIS+PHP:

On the command line, can you please do the following, and let me know if you see HTML output. Also note here that the URL is surrounded in double quotes:

curl "http://neverssl.com/"


If you do see HTML output from that website, can you then try that URL inside the PHP example from before.
oamobile
Thanks Alfie - both command line and PHP return the website
alfie
I'm back to thinking this is a permissions problem within IIS' configuration.

For now, let's remove Prince from the equation for now and go back to your drive mappings. You said above that C:\ is accessible from PHP but not E:\ as you got "E://images/FF52B545-9356-4D3C-9795-D45F1026A108.jpg: warning: can't open input file: No such file or directory"

Are you able to confirm that PHP can access these paths leading up all the way to the image itself? That should tell us that if it's a permission issue with IIS itself, or when it passes restricted permissions down to Prince.

In a PHP script run from IIS, can you do the following please:

  echo shell_exec('dir c:\');
  echo
  echo shell_exec('dir e:\');
  echo
  echo shell_exec('dir e:\images\');
  echo


The first should work given what you said above. The second line should confirm to us that E: is definitely accessible from PHP, and the third line should show that PHP can definitely see the files within in that directory.

Edited by alfie

oamobile
Yes, all works correctly
alfie
Ok, great. Now that we've confirmed that shell_exec() can see the images, let's see if the problem lies with proc_open(). Please try the following 3 examples:

1:
  $fds = array(
    0 => array("pipe", "r"),
    1 => array("pipe", "w"), 
    2 => array("file", "C:/inetpub/wwwroot/error-output.txt", "a") 
  );

  $process = proc_open('dir c:\', $fds, $pipes);
  echo stream_get_contents($pipes[1]);


2:
  $fds = array(
    0 => array("pipe", "r"),
    1 => array("pipe", "w"), 
    2 => array("file", "C:/inetpub/wwwroot/error-output.txt", "a") 
  );

  $process = proc_open('dir e:\', $fds, $pipes);
  echo stream_get_contents($pipes[1]);


3:
  $fds = array(
    0 => array("pipe", "r"),
    1 => array("pipe", "w"), 
    2 => array("file", "C:/inetpub/wwwroot/error-output.txt", "a") 
  );

  $process = proc_open('dir e:\images\', $fds, $pipes);
  echo stream_get_contents($pipes[1]);
oamobile
proc_open could't access the mapped drive. The following error was returned:

The system cannot find the path specified.


The mapped drive is created in PHP using system("net use...")

I've just tried mapping the drive manually from the command and that doesn't work either (this normally doesn't work anyway, it has to be created in PHP)
alfie
So it beginning to confirm that the problem here is permissions based. Let's see if there are any permissions differences there are between shell_exec() and proc_open().

Can you run the following please from IIS+PHP:

1:
  echo shell_exec('whoami');


2:
  $fds = array(
      0 => array("pipe", "r"),
      1 => array("pipe", "w"), 
      2 => array("file", "C:/inetpub/wwwroot/error-output.txt", "a") 
    );

    $process = proc_open('whoami', $fds, $pipes);
    echo stream_get_contents($pipes[1]);


If there is a difference between the above, the I'm going to guess that the proc_open() user does not have same permissions as the shell_exec() user i.e 1) access mapped drives, and 2) access https. If so, you will need to update that user's permissions so that Prince can work properly.
oamobile
shell_exec uses the built in user account IUSR and proc_open uses the IIS apppool.

The confusing thing is neither of these accounts have permissions set on the network share, I have set up a local user account on the network server and use those credentials to map the drive in PHP.

I guess shell_exec is using the mapped credentials and proc_open doesn't.

I had assumed the network access was down to permissions which is why I started focusing on getting the https to work instead. Maybe I need to somehow get proc_open to use IUSR.

Do you think the unable to resolve the hostname is related to this also or something different? I guess since proc_open can run nslookup successfully they must be different issues

Edited by oamobile

oamobile
For the sake of testing, I've set read & write permissions on the network share and still proc_open cannot see the drive
1 2 Next
Showing 1 - 50 of 55