Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

file_exists or getimagesize only work with local, absolute file paths, but not with URLs in PHP

I recently updated one of my servers and since then, I have an issue with some specific PHP commands (see below). I believe it is a configuration issue, but I already looked into a couple of things and do not know any further. So maybe one of you has a good idea:

I am using the following code in order to display either a standard logo on an intranet site or a user defined logo:

if(L_HEADER) {
  $logo = L_HEADER;
}
else {
  $logo = 'logo.png';
}
$properties = getimagesize(CONFIG_URL . 'images/' . $logo)

L_HEADER and CONFIG_URL are constants with pre-defined values (another file):

  1. L_HEADER contains "opb_beta.png"
  2. CONFIG_URL contains "http://billing.intranet.opb/"

Concatenating works correctly, which is also confirmed by the error message of the Apache logfile:

PHP Warning: getimagesize(http://billing.intranet.opb/images/opb_beta.png): failed to open stream: HTTP request failed! HTTP/1.1 404 NOT FOUND
in /var/www/billing/templates/header.inc.php on line 42

So the first obvious conclusion would be: the path is wrong. But it is not, believe me. I checked it like 1.000 times. In fact, the first curiosity is that the image is displayed and referenced correctly a couple of lines further down in the code of the same file:

echo '<img src="' . CONFIG_URL . 'images/' . $logo . '"  
  width="' . $properties[0] . '" height = "' . $properties[1] . '" />";

As I get the error mentioned above, height and width are "0", but looking at the source code, the URL is fine, accessing it manually opens the image and when replacing width and height with manual values, the image is displayed just fine.

More curious though (and also my current finx), when changing the getimagesize to the following, it works just fine:

$properties = getimagesize($_SERVER['DOCUMENT_ROOT'] . /public_html/images/' . $logo);

I shall mention that I am using Apache's redirect; this is why in the URL you do not see "public_html", while in the absolute path of the second example you do see it.

The same happens with "file_exists". URL does not work, absolute local path for the same file does.

Another curiosity: in another piece of code, I am checking online for updates. There, I am using a "real", public URL with file_exists and fopen. I looks like this and works perfectly fine:

if(file_exists('http://desk.co.cr/df_stable.txt') {
  if(($handle = fopen('http://desk.co.cr/df_stable.txt', 'r')) !== FALSE) {
    // some other code
  }
}

Now, the things I already checked:

  • File permissions are set correctly, for the whole path, with www-data being group and owner of all files and read and write access for the image file
  • allow_url_fopen in set to "On".
  • open_basedir is set to "no value" and there is no override in Apache's virtual hosts definitions.
  • the file definitively exists and syntax + path are correct.

Some background info:

  • Server is running on Ubuntu 14.04 LTS
  • Apache 2.4.7
  • PHP 5.5.9

For now, I am out of ideas.

like image 508
Sebastian Avatar asked Oct 30 '22 19:10

Sebastian


1 Answers

Buried in your question is this vital clue which you've already found:

Another curiosity: in another piece of code, I am checking online for updates. There, I am using a "real", public URL

So, the URL that is failing is to a non-public domain, which your PC has been configured to look up to the correct IP address. Most likely this has been done either by running a local DNS server, or configuring the PC's "hosts" file to hard-code the address for that domain.

When you request the URL from the server itself, however, a totally different DNS configuration is in play, so probably it simply doesn't know where that server is - even though it's itself! You need to configure the server's DNS settings or /etc/hosts to match what's on your PC.

One related possibility is that the server is configured with the same address lookup, but the router doesn't allow it to connect to itself that way. One way around that is to point the hosts file entry at 127.0.0.1 and configure Apache to match.

If you can get a command-line on the server, you could try:

nslookup billing.intranet.opb
# if that returns the right IP address, see if it's reachable:
ping billing.intranet.opb
# and if it's the right server, it will be listening on port 80:
telnet billing.intranet.opb 80
# telnet will either time out, or connect and give you a prompt

If telnet connects, you can even write an HTTP request manually (a blank line completes the request; don't take too long typing, or the server will bail out) e.g.:

HTTP/1.1 HEAD /
Host: billing.intranet.opb
like image 181
IMSoP Avatar answered Nov 02 '22 09:11

IMSoP