Shaping the creation of files in a public directory?
Here's an idea. I am trying to create a file from a PHP script. The file can be created in any public place on the server (in the public root or in its subdirectories). At the bottom of the line, I want to write a function like this (it should work on both unix servers and windows).
function create_file($path, $filename, $content, $overwrite=false) {
# body
...
}
Parameters:
- $ path - path to the file (empty or ends with
/
) - $ filename - any valid filename (requires period + extension)
- $ content - file-content (something)
- $ overwrite - if set to true , the existing file will be overwritten (default is false ).
Result:
The function returns TRUE
and creates a file with the contents or FALSE
, if the file cannot be created for some reason.
Description of the problem:
I expect this function to return TRUE
and create the file $ filename at $ path or FALSE
if for some reason this is not possible. Also, if the file was successfully opened for writing, you need to add $ content to it .
Argument $ path - relative path to a shared directory, $ filename - any valid file name. Of course I want to avoid generating files if the path points are outside the public directory . The function can be called from script subdirectories like this example
# PHP : /scripts/test.php
create_file('../data/', 'test.info', 'some contents');
# result file: /data/test.info
What have I tried so far?
I've tried to do this with fopen () and fwrite () and it works on some servers and doesn't work on some. I guess it's a problem with writing permissions and chmod () , but to be honest, I'm not very familiar with chmod attributes. Also I couldn't check if the $ path is outside the server's public directory.
In short, I want this function to create a file and return TRUE
if the file does not exist or the file exists, and $owerwrite=true
. Otherwise, nothing happens and the function returns FALSE
.
Also, I would like to know the reason why the file cannot be created in some path (in theory). Wrong path / filename is just what's on my mind and I'm sure there is more to this problem.
Thanks in advance for any example / example / suggestion.
update code
So far I have this code ...
function create_file($path, $filename, $content, $overwrite=false) {
$reldir = explode('/', trim(str_replace('\\', '/', dirname($_SERVER['PHP_SELF'])), '/'));
$dirdepth = sizeof($reldir);
$rpadd = $dirdepth > 0 ? '(\.\./){0,' . $dirdepth . '}' : '';
$ptpath = '#^/?' . $rpadd . '([a-z0-9]\w*/)*$#i';
$ptname = '/^[a-z]\w*\.[a-z0-9]+$/i';
if ($res = preg_match($ptpath, $path) && preg_match($ptname, $filename)) {
$res = false;
if ($overwrite === true || !file_exists($path.$filename)) {
if ($f = @fopen($path.$filename, 'w')) {
fwrite($f, $content);
fclose($f);
$res = true;
}
}
}
return $res;
}
source to share
Some suggestions:
- set webserver document root owner: chown -R apache: apache / var / www (assuming / var / www is your document root and that apache webserver is running apache user). Set the root document privileges so that all directories in the document look like with privileges 755 (only owner which apache user can write in / var / www folders and subfolders)
- Block paths that point to your document root / var / www: You are under an issue called http://en.wikipedia.org/wiki/Directory_traversal_attack . How about if $ path is something like: / var / www /../../../ etc / passwd? A basic php function can help you identify this type of malignant pathways. See this post: php directory traversal issue
- To check if a file already exists or not: http://php.net/manual/en/function.file-exists.php
source to share