How to check if file handle still points to file - php

Is there any way in PHP to test if a fileHandle resource still points to the file in the file system that it opened? e.g. in this code:
<?php
$filename = './foo.txt';
$fileHandle = fopen($filename, 'c');
$unlinked = unlink($filename);
if (!$unlinked) {
echo "Failed to unlink file.";
exit(0);
}
file_put_contents($filename, "blah blah");
// The file $filename will exist here, but I want to check that
// the $fileHandle still points to the file on the filesystem name $filename.
?>
At the end of that code, the fileHandle still exists but no longer references the file './foo.txt' on the filesystem. It instead still holds a reference to the original file that has been unlinked, i.e. it has no active entry in the filesystem, and writing data to the fileHandle will not affect the contents of the file called $filename.
Is there a (preferably atomic) operation to determine that $fileHandle is now 'invalid' in the sense that it no longer points to the original file?

It's not an atomic operation but on Linux (and other Unix systems) it's possible to check using stat on the filename, and fstat on the fileHandle, and comparing the inodes returned from each of those functions.
This doesn't work on Windows, which is less than optimal.
<?php
$filename = './foo.txt';
$fileHandle = fopen($filename, 'c');
$locked = flock($fileHandle, LOCK_EX|LOCK_NB, $wouldBlock);
if (!$locked) {
echo "Failed to lock file.";
exit(0);
}
$unlinked = unlink($filename);
if (!$unlinked) {
echo "Failed to unlink file.";
exit(0);
}
// Comment out the next line to have the 'file doesn't exist' result.
file_put_contents($filename, "blah blah ");
$originalInode = null;
$currentInode = null;
$originalStat = fstat($fileHandle);
if(array_key_exists('ino', $originalStat)) {
$originalInode = $originalStat['ino'];
}
$currentStat = #stat($filename);
if($currentStat && array_key_exists('ino', $currentStat)) {
$currentInode = $currentStat['ino'];
}
if ($currentInode == null) {
echo "File doesn't currently exist.";
}
else if ($originalInode == null) {
echo "Something went horribly wrong.";
}
else if ($currentInode != $originalInode) {
echo "File handle no longer points to current file.";
}
else {
echo "inodes apparently match, which should never happen for this test case.";
}
$closed = fclose($fileHandle);
if (!$closed) {
echo "Failed to close file.";
exit(0);
}

Related

PHP SSH move file to another directory [duplicate]

I am uploading files to a server using php and while the move_uploaded_file function returns no errors, the file is not in the destination folder. As you can see I am using the exact path from root, and the files being uploaded are lower than the max size.
$target = "/data/array1/users/ultimate/public_html/Uploads/2010/";
//Write the info to the bioHold xml file.
$xml = new DOMDocument();
$xml->load('bioHold.xml');
$xml->formatOutput = true;
$root = $xml->firstChild;
$player = $xml->createElement("player");
$image = $xml->createElement("image");
$image->setAttribute("loc", $target.basename($_FILES['image']['name']));
$player->appendChild($image);
$name = $xml->createElement("name", $_POST['name']);
$player->appendChild($name);
$number = $xml->createElement("number", $_POST['number']);
$player->appendChild($number);
$ghettoYear = $xml->createElement("ghettoYear", $_POST['ghetto']);
$player->appendChild($ghettoYear);
$schoolYear = $xml->createElement("schoolYear", $_POST['school']);
$player->appendChild($schoolYear);
$bio = $xml->createElement("bio", $_POST['bio']);
$player->appendChild($bio);
$root->appendChild($player);
$xml->save("bioHold.xml");
//Save the image to the server.
$target = $target.basename($_FILES['image']['name']);
if(is_uploaded_file($_FILES['image']['tmp_name']))
echo 'It is a file <br />';
if(!(move_uploaded_file($_FILES['image']['tmp_name'], $target))) {
echo $_FILES['image']['error']."<br />";
}
else {
echo $_FILES['image']['error']."<br />";
echo $target;
}
Any help is appreciated.
Eric R.
Most like this is a permissions issue. I'm going to assume you don't have any kind of direct shell access to check this stuff directly, so here's how to do it from within the script:
Check if the $target directory exists:
$target = '/data/etc....';
if (!is_dir($target)) {
die("Directory $target is not a directory");
}
Check if it's writeable:
if (!is_writable($target)) {
die("Directory $target is not writeable");
}
Check if the full target filename exists/is writable - maybe it exists but can't be overwritten:
$target = $target . basename($_FILES['image']['name']);
if (!is_writeable($target)) {
die("File $target isn't writeable");
}
Beyond that:
if(!(move_uploaded_file($_FILES['image']['tmp_name'], $target))) {
echo $_FILES['image']['error']."<br />";
}
Echoing out the error parameter here is of no use, it refers purely to the upload process. If the file was uploaded correctly, but could not be moved, this will still only echo out a 0 (e.g. the UPLOAD_ERR_OK constant). The proper way of checking for errors goes something like this:
if ($_FILES['images']['error'] === UPLOAD_ERR_OK) {
// file was properly uploaded
if (!is_uploaded_File(...)) {
die("Something done goofed - not uploaded file");
}
if (!move_uploaded_file(...)) {
echo "Couldn't move file, possible diagnostic information:"
print_r(error_get_last());
die();
}
} else {
die("Upload failed with error {$_FILES['images']['error']}");
}
You need to make sure that whoever is hosting your pages has the settings configured to allow you to upload and move files. Most will disable these functions as it's a sercurity risk.
Just email them and ask whether they are enabled.
Hope this helps.
your calls to is_uploaded_file and move_uploaded_file vary. for is_uploaded_file you are checking the 'name' and for move_uploaded_file you are passing in 'tmp_name'. try changing your call to move_uploaded_file to use 'name'

How to check a folder contains .csv files?

I need to check whether a folder contains csv files or not. Using PHP
I need to show an error message if someone try to upload any csv into a specific folder if there is already existing a csv.
Use glob() to find all files matching a wildcard. It returns an array of the matches, so you can check if the array is empty.
$files = glob("$dirname/*.csv");
if (!empty($files)) {
die("Error: The directory already has a .csv file");
}
<?php
$filename = '/path/to/foo.txt';
if (file_exists($filename)) {
echo "Die Datei $filename existiert";
} else {
echo "Die Datei $filename existiert nicht";
}
?>
From: http://php.net/manual/de/function.file-exists.php
Loop over the files of directory to check whether it contains csv or not.
$files=scandir("/path/to/dir");
foreach($files as $fileName)
{
if(preg_match("/\.csv$/", $fileName))
{
throw new Exception("/path/to/dir contains csv file with filename: $fileName");
}
}
$dir = 'folder';
echo (count(glob("$dir/*.csv")) === 0) ? 'Empty' : 'Not empty';
You can use glob() function. http://php.net/manual/tr/function.glob.php
Also #Barmar answer is look like doing job well.
<?php
$directory = new DirectoryIterator(__DIR__);
if ($fileinfo->isFile()) {
$fileExt = $fileinfo->getExtension();
if($fileExt=="csv")
{
echo "File found";
}
else
{
echo "File not found";
}
}
?>
Reference:[http://php.net/manual/en/directoryiterator.getextension.php]

PHP unlinking not working with variable

Going out of my mind with php unlinking
Here is my delete file script
$pictures = $_POST['data'];
//print_r ($pictures);
$imageone = $pictures[0];
$filename = "file:///Users/LUJO/Documents/CODE/REVLIVEGIT/wp-content/uploads/dropzone/" . $imageone;
echo $filename;
if (is_file($filename)) {
chmod($filename, 0777);
if (unlink($filename)) {
echo 'File deleted';
} else {
echo 'Cannot remove that file';
}
} else {
echo 'File does not exist';
}
The above does not work, error response is file does not exist
however if i change the filename path to this (the echo data from the echo above)
$filename = "file:///Users/LUJO/Documents/CODE/REVLIVEGIT/wp-content/uploads/dropzone/1420291529-whitetphoto.jpeg "
works fine and deletes the image.
Why can i not use the $imageone variable?
Do a print_r($pictures) to see if $pictures[0] is indeed the filename you're looking for.
Also note that if $pictures[0] is "//windows/*" you'll loose your windows if the user running PHP has administrative rights... so just using $pictures=$_POST["data"] is very VERY unsafe!

How do I know if my image exists on the server? (PHP)

I have a simple code that checks whether a file exists or not in the server.
<?php
$filename = 'www.testserver/upload/productimg/IN.ZL.6L_sml.jpg';
if (file_exists($filename)) {
echo "The file $filename exists";
} else {
echo "The file $filename does not exist";
}
?>
Problem: My local webserver says that the file does not exist even though when I copy paste the url in the browser, I can see the image.
How can I make the condition say that the file does not really exist?
Another option would be, making a request and checking for the response headers:
<?php
$headers = get_headers('http://www.example.com/file.jpg');
if($headers[0]=='HTTP/1.0 200 OK'){
return true; // file exists
}else{
return false; // file doesn't exists
}
?>
Code live example:
http://codepad.viper-7.com/qfnvme
for real path of image you can try:
<?php
$filename = 'www.testserver/upload/productimg/IN.ZL.6L_sml.jpg';
$testImage = #file_get_contents($filename);
if ($testImage != NULL) {
echo "The file $filename exists";
} else {
echo "The file $filename does not exist";
}
?>
Use
$filename = $_SERVER["DOCUMENT_ROOT"]."/upload/productimg/IN.ZL.6L_sml.jpg";
for testing the file.

Issue in secure file upload script using command line AV

I have a secure file upload function that's part of my website
and I'm using an antivirus to help me checking the file a user trying to upload.
This is my uploadprocess.php file
$target_tmp = "D:\avscan\u\\";
$file = basename( $_FILES['uploaded_file']['name']) ;
if($file != "")
$_SESSION['file'] = $file;
$target = 'C:\xampp\htdocs\ssd\Uploads\\';
$file_path = $target_tmp.$file;
if(move_uploaded_file($_FILES['uploaded_file']['tmp_name'], $file_path))
{
$safe_path = escapeshellarg($file_path);
$command = 'scancl'. $safe_path. ' --stdout';
$out = '';
$int = -1;
$output = exec($command, $out, $int);
echo "The output is" .$output;
echo $int;
exit(0);
//Checking for Virus.
if ($int == 0) {
$target = $target.$file;
//echo $target; exit(0);
copy($file_path, $target);
$uploaded = "The file ". $_SESSION['file']. "has been uploaded";
$clean = 'File is Clean.';
$_SESSION['status'] = $clean;
$_SESSION['upload'] = $uploaded;
header("location: ../upload.php");
exit(0);
}
// File is a virus.
else {
$mal = 'Contains Malware';
$deny_up = "Unable to Upload Your File!";
$_SESSION['status'] = $mal;
$_SESSION['upload'] = $deny_up;
header("location: ../upload.php");
exit(0);
}
}
else
{
echo "SORRY, There was a Problem Uploading Your File."; exit(0);
$err_upload = "SORRY, There was a Problem Uploading Your File.";
$_SESSION['err'] = err_upload;
header("location: ../upload.php");
exit(0);
}
It prints me value of 1 for the $int for all files (malicious and non ones) This is my second try with a different AV now I'm using Avira and before I was using clamscan
can someone share me some hints, and tell me what's going on
PS the system is installed on XAMPP if that makes any difference
Can you be more specific about what's not working here? In theory what you doing seems fine at least for ClamAV since it has these return codes (from man clamscan):
RETURN CODES
0 : No virus found.
1 : Virus(es) found.
2 : Some error(s) occured.
Maybe it want to log the output of the exec call, if you are not getting the exit code you expect the reason should be in the output (like missing a command line flag).

Categories