views:

266

answers:

3

I'm using php and I have the following code to convert an absolute path to a url.

function make_url($path, $secure = false){
    return (!$secure ? 'http://' : 'https://').str_replace($_SERVER['DOCUMENT_ROOT'], $_SERVER['HTTP_HOST'], $path);
}

My question is basically, is there a better way to do this in terms of security / reliability that is portable between locations and servers?

+2  A: 

I don't think security is going to be effected, simply because this is a url, being printed to a browser... the worst that can happen is exposing the full directory path to the file, and potentially creating a broken link.

As a little side note, if this is being printed in a HTML document, I presume you are passing the output though something like htmlentities... just in-case the input $path contains something like a [script] tag (XSS).

To make this a little more reliable though, I wouldn't recommend matching on 'DOCUMENT_ROOT', as sometimes its either not set, or won't match (e.g. when Apache rewrite rules start getting in the way).

If I was to re-write it, I would simply ensure that 'HTTP_HOST' is always printed...

function make_url($path, $secure = false){
    return (!$secure ? 'http://' : 'https://').$_SERVER['HTTP_HOST'].str_replace($_SERVER['DOCUMENT_ROOT'], '', $path);
}

... and if possible, update the calling code so that it just passes the path, so I don't need to even consider removing the 'DOCUMENT_ROOT' (i.e. what happens if the path does not match the 'DOCUMENT_ROOT')...

function make_url($path, $secure = false){
    return (!$secure ? 'http://' : 'https://').$_SERVER['HTTP_HOST'].$path;
}

Which does leave the question... why have this function?

On my websites, I simply have a variable defined at the beggining of script execution which sets:

$GLOBALS['webDomain'] = 'http://' . (isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : '');
$GLOBALS['webDomainSSL'] = $GLOBALS['webDomain'];

Where I use GLOBALS so it can be accessed anywhere (e.g. in functions)... but you may also want to consider making a constant (define), if you know this value won't change (I sometimes change these values later in a site wide configuration file, for example, if I have an HTTPS/SSL certificate for the website).

Craig Francis
A: 

I think this is the wrong approach.

URLs in a HTML support relative locations. That is, you can do <A href="filename.php">link</a> to refer to a page that has the same path in its URL as the corrent page. You can also do <a href="/dir/filename.php">link</a> to provide a full path to the same website. These two tricks mean your website code doesn't really need to know where it is to provide working URLs.

That said, you might need some tricks so you can have one website on http://www.example.com/dev/site.php and another on http://www.example.com/testing/site.php. You'll need some code to figure out which directory prefix is being used, but you can use a configuration value to do that. By which I mean a value that belongs to that (sub-)site's configuration, not the version-controlled code!

staticsan
+2  A: 

The HTTP_HOST variable is not a reliable or secure value as it is also being sent by the client. So be sure to validate its value before using it.

Gumbo