I'm writing a simple upload/download page in PHP. With the following code I can see files being the content of folder above the root but it's impossible to access those files. What could be the reason?
$targetdir="/../cat/";
if ($dir = #opendir($targetdir))
{
while ($file = readdir($dir))
{
if ($file != "." && $file != "..")
echo "<td>".$file."</td>";
}
closedir($dir);
}
You cannot access files above the web root directory, instead you will need to write a script to do this for you.
downloadfile.php?file=somefile.txt
<?php
$file = $_GET['file'];
if (strpos($file, '..') !== false) {
throw new \Exception('Illegal path requested');
}
/**
* this will restrict files to this directory or above as
* to not allow reading of files which you do not want a user to access
*/
$basePath = __DIR __ . '/../cat';
$fullPath = sprintf('%s/%s', $basePath, $file);
/** check to see if the file exists and is readable **/
if (false === is_readable($fullPath)) {
throw \Exception('file does not exist or is not accessible');
}
echo file_get_contents($file);
exit;
You must be very cautious when doing this, as you could allow someone to access files you don't want them to, including your source code, so make sure you're sanitizing the input.
As well you should change $target dir to the following, as it stands you're trying to go to the absolute root of the file system instead relative to the file which started the execution.
/** relative to the file that started the execution **/
$targetdir = "../cat/"
/** relative to the file that contains this variable declaration**/
$target = __DIR__ . "/../cat/"
Related
I'm trying to change every file name in a folder, for e.g if file name is style.css than i want to rename it as style_[md5 value of style].css = style_a1b01e734b573fca08eb1a65e6df9a38.css
here is what I've tried
if ($handle = opendir("D:/web/htdocs/extra/css/")) {
while (false !== ($fileName = readdir($handle))) {
$path_parts = pathinfo($fileName);
$newName = md5($path_parts['filename']);
rename($fileName, $newName);
}
closedir($handle);
}
Where am i wrong?
errors are
Access is denied. (code: 5)
The system cannot find the file specified. (code: 2)
not sure the same happens on a windows, but on a GNU here …
if you printed out what you intend to do instead of trying bluntly you'd see some flaws:
rename( ., d41d8cd98f00b204e9800998ecf8427e)
rename( .., 5058f1af8388633f609cadb75a75dc9d)
when e.g. doing:
echo ("rename( ".$fileName.", ".$newName.")\n");
next thing to check maybe is rights to change files …
// DS to print \ the split between folder
define('DS',DIRECTORY_SEPARATOR);
// APP_PATH to get application path on the the server
define('APP_PATH',__DIR__.DS);
$oldname = APP_PATH.'css'.DS.'style.css';
/*
when you echo $oldname ,you will get the complete path of file
*/
// check the file is exists or No
if (file_exists($oldname)) {
$newName = md5($oldname);
/*add the extension of file that you will rename it */
rename($oldname, ($newName.'.css'));
}
I have a php script that uploads a photo to a main folder and copies it into a subfolder. I also have a php script that deletes the photo. The problem is that it only deletes the photo from the main folder and not the subfolder. This is the code I tried to come up with but nothing happens. Any thoughts?
$deletefile = $galleriesfolder.$folder.$dir.$image;
$deletefile1 = $galleriesfolder.$folder.$dir."/thumbs/".$image;
unlink($deletefile);
if (!is_file($deletefile)):
die("no file");
endif;
unlink($deletefile1);
if (!is_file($deletefile1)):
die("no file");
endif;
Deletes all subfolders and files in a directory recursively
/**
* Deletes a directory and all files and folders under it
* #return Null
* #param $dir String Directory Path
*/
function rmdir_files($dir) {
$dh = opendir($dir);
if ($dh) {
while($file = readdir($dh)) {
if (!in_array($file, array('.', '..'))) {
if (is_file($dir.$file)) {
unlink($dir.$file);
}
else if (is_dir($dir.$file)) {
rmdir_files($dir.$file);
}
}
}
rmdir($dir);
}
}
This is quite a nasty function.
You want to handle it with care. Make sure you don't delete any directories that you do not intend to delete. It will attempt to remove the whole directory, and all files in it.
It does no error checking apart from making sure a directory handle was opened successfully for reading.
This code will deletes all subfolders and files in a directory recursively.
$dir = "/";
$di = new RecursiveDirectoryIterator($dir, FilesystemIterator::SKIP_DOTS);
$ri = new RecursiveIteratorIterator($di, `enter code here`RecursiveIteratorIterator::CHILD_FIRST);
foreach ($ri as $file)
{
$file->isDir() ? rmdir($file) : unlink($file);
}
I want to create a zip file and copy all the folders and files from a directory to it. It is successfully created and contains the files and folders, but the file tree is not preserved, everything being in the root directory.
My directory:
folder/
test.txt
test2.txt
test.php
The zip archive:
folder/
test.txt
test2.txt
test.php
This is my code:
public function createZipFromDir($dir, $zip_file) {
$zip = new ZipArchive();
if(true !== $zip->open($zip_file, ZIPARCHIVE::CREATE | ZIPARCHIVE::OVERWRITE)) {
return false;
}
$this->zipDir($dir, $zip);
return $zip;
}
public function zipDir($dir, $zip) {
$dir = rtrim($dir, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR;
$files = scandir($dir);
foreach($files as $file) {
if(in_array($file, array('.', '..'))) continue;
if(is_dir($dir . $file)) {
$zip->addEmptyDir($file);
$this->zipDir($dir . $file, $zip);
} else {
$zip->addFile($dir . $file, $file);
}
}
}
$zip = $this->createZipFromDir($rootPath, $archiveName);
The issue is that when you create a folder or set the localname (second argument of addFile()) when adding a file to the archive, you only use $file, therefore everything gets put at the root. It is necessary to provide the file hierarchy as well.
Now the obvious solution would be to use $dir.$file instead, but this would only work properly on a folder located in the same directory as the script.
We actually need to keep track of two file trees:
the real tree, as it exists on the machine
the archive tree, relative to the path we want to archive
But since one is just a subset of the other, we can easily keep track of that by splitting the real path in two:
$dir, a prefix pointing to the original path
$subdir, a path relative to $dir
When referring to a file on the machine, we use $dir.$subdir and when referring to a file in the archive we use only $subdir. This requires us to adapt zipDir() to keep track of the prefix by adding a third argument to it and slightly modifying the call to zipDir() in createZipFromDir().
function createZipFromDir($dir, $zip_file) {
$zip = new ZipArchive();
if(true !== $zip->open($zip_file, ZIPARCHIVE::CREATE | ZIPARCHIVE::OVERWRITE)) {
return false;
}
zipDir(
// base dir, note we use a trailing separator from now on
rtrim($dir, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR,
// subdir, empty on initial call
null,
// archive ref
$zip
);
return $zip;
}
function zipDir($dir, $subdir, $zip) {
// using real path
$files = scandir($dir.$subdir);
foreach($files as $file) {
if(in_array($file, array('.', '..')))
continue;
// check dir using real path
if(is_dir($dir.$subdir.$file)) {
// create folder using relative path
$zip->addEmptyDir($subdir.$file);
zipDir(
$dir, // remember base dir
$subdir.$file.DIRECTORY_SEPARATOR, // relative path, don't forget separator
$zip // archive
);
}
// file
else {
// get real path, set relative path
$zip->addFile($dir.$subdir.$file, $subdir.$file);
}
}
}
This code has been tested and is working.
I need to get the contents of several files within a directory but which is the best way of doing this?
I am using
$data = file_get_contents('./files/myfile.txt');
but I want every file without having to specify the file individually as above.
You can use glob to get particular file extention and file_get_contents to get the content
$content = implode(array_map(function ($v) {
return file_get_contents($v);
}, glob(__DIR__ . "/files/*.txt")));
/**
* Change the path to your folder.
* This must be the full path from the root of your
* web space. If you're not sure what it is, ask your host.
*
* Name this file index.php and place in the directory.
*/
// Define the full path to your folder from root
$path = "/home/content/s/h/a/shaileshr21/html/download";
// Open the folder
$dir_handle = #opendir($path) or die("Unable to open $path");
// Loop through the files
while ($file = readdir($dir_handle)) {
$data = file_get_contents('$filet');
}
// Close
closedir($dir_handle);
You can dir the directory and loop through it to get the contents of all files.
<?php
$path = './files';
$d = dir($path);
$contents = '';
while (false !== ($entry = $d->read())) {
if (!($entry == '..' || $entry == '.')) {
$contents .= file_get_contents($path.'/'.$entry);
}
}
$d->close();
?>
If you only want .txt files you can change the if statement of the code above from:
if (!($entry == '..' || $entry == '.')) {
to:
if (substr($entry, -4) == '.txt') {
This will result to a variable $contents that is type string and has all the contents of all the files (or only txt files if you select the 2nd solution) that are in the ./files dir.
I am trying to read a file name current.conf and then use the name of a folder saved in it to opendir(); when I open:
$file = fopen("current.conf","r");
$lines = fread($file,"10");
fclose($file);
$lines = "/".$lines."/";
echo $lines;
$dir=opendir($lines);
$files=array();
while (($file=readdir($dir)) !== false)
{
if ($file != "." and $file != ".." and $file != "index.php")
{
array_push($files, $file);
}
}
closedir($dir);
The current.conf has only one line in it:
2.1-2328
I am not able to open the folder that is named in the conf files. I have a feeling it has to do with the formatting of the conf file but not sure.
I suspect the directory doesn't exist (or you don't have the rights to read it), but without a specific error (opendir is most likely throwing an E_WARNING - check your logs, etc.)
Incidentally, you could re-write your code to reduce its complexity as follows:
<?php
// Grab the contents of the "current.conf" file, removing any linebreaks.
$dirPath = '/'.trim(file_get_contents('current.conf')).'/';
$fileList = scandir($dirPath);
if(is_array($fileList)) {
foreach($fileList as $file) {
// Skip the '.' and '..' in here as required.
echo $file."\n";
}
}
else echo $dirPath.' cound not be scanned.';
?>
In this instance the call to scandir will throw an E_WARNING.