views:

297

answers:

4

I don't want to specify the ".php" file extension in the link. But when I do that I can't successfully check to see if the file specified in the link exists or not. This is because PHP's built in "file_exists" function takes the .php extension in consideration. And even this doesn't work:

file_exists($file.".php");

Anyway, is there some way to make the following work without speciding the php extension in the html links:

<a href="?file=dude">Some File</a>

<?php

$file = $_GET['file'];

if(file_exists($file.".php"))
{
     include($file.".php");
}
else
     include("404.php");


?>
A: 

Use PHP's glob function to prevent specifying the .php extension. However this may result in a security issue:

http://ar2.php.net/glob

glob($file . ".*")
Johnco
A: 

Try with url rewrite, add this to your .htaccess file:

RewriteCond %{DOCUMENT_ROOT}/$1.php -f 
RewriteRule ^/(([^/]+/)*[^.]+)$ /$1.php [L]
tricat
+4  A: 

Your example should work just fine (I unstriked the previous again as per EDIT 2), provided that the file is in the current working directory (I'll just abbreviate this to cwd from now on).

EDIT
Sorry, what was I thinking. Your example doesn't work of course, because file_exists() should be provided with the full path to the file. So prepend the file with the directory you want to pull the files out of the directory. My warning about sanatizing and whitelisting, etc. still count nonetheless though.
END EDIT

EDIT 2
Wow, sorry, I'm messing up bigtime. file_exists() should work just fine with relative paths. Looking at the documentation, it does however warn about safe mode restrictions. Maybe these apply to your situation, I don't know.
END EDIT 2

You can test what is the cwd with getcwd(). Under normal circumstances the cwd is the same as the entry point of your application. So, if for instance /usr/www/your_site_root/index.php is the entry point, then /usr/www/your_site_root/ is the cwd.

Therefor the files you try to include with you examples should reside in said directory.

A word of advice though:
You may be aware of this already, but your example is not very secure. You don't sanitize the input from the user in any way ($_GET[ 'file' ] in this case). This way, the visitor will be able to include all sorts of php files with unwanted results.

Therefor I'ld advice you to keep a whitelist of files that are allowed to be fetched. Something like:

<?php

$whiteList = array(
    'dude',
    'chick',
    'mom'
);

// and just to be safe, you should probably strip stuff like ../ etc. here too.
$requestedFileBaseName = $_GET[ 'file' ];

if( !in_array( $requestedFileBaseName, $whileList ) )
{
    include( '404.php' );
}
else
{
    include( $requestedFileBaseName . '.php' );
}
fireeyedboy
+1 for the security issues here.
ceejayoz
Are you sure? I just tested file_exists() locally and it works without full path.
Kevin
@Kevin: yes that was a slip up on my part, sorry. I tested it myself also, and indeed it works. Thanks for pointing it out anyway.
fireeyedboy
A: 

use :

$file = dirname(__FILE__).'/../relativepathfromcurrentscript/'.$_GET['file'].'.php';
useless