How to check whether the upload file is PDF in PHP - php

For an upload file type checking , I have implemented:
$_FILES["file"]["type"][$i] == 'application/pdf'
however, this checking will not work on the case I changed the extension name.
So , after some research, I have tried
$finfo = new finfo();
$fileMimeType = $finfo->file($_FILES["file"]["name"][$i] );
OR:
$finfo = finfo_open(FILEINFO_MIME_TYPE);
$fileMimeType = finfo_file($finfo,$_FILES["file"]["name"][$i])
however, $fileMimeType echo nothing.
How to fix the problem? thanks

Read the first 4 bytes of the file and check that they match %PDF.
$filename = "pdffile";
$handle = fopen($filename, "r");
$header = fread($handle, 4);
fclose($handle);
Check $header against %PDF

I guess the problem is using:
$_FILES["my_file"]["name"]
as it only contains the name of the uploaded file. If you want to check the file before moving it using move_uploaded_file you can refer to the temp file using:
$_FILES["my_file"]["tmp_name"]

if you read the file using fread you need to have a dictionary of all the file header type definitions. If you want to use the file shell command
$out = exec("file 'R-intro.pdf' | cut -d: -f2 | cut -d, -f1");
if (trim($out) == "PDF document") {
echo "1";
}
To further expand on how to replace the constant file name with a uploaded file refer below.
$out = exec("file '" . $_FILES['file']['tmp_name'] . "' | cut -d: -f2 | cut -d, -f1");

Related

PHP: how to retrieve the filename of the file contained in .gz?

My test.gz contains for instance : image1.jpg.
How can I decompress the test.gz so it gives me image1.jpg ?
I tried that method:
$file = gzopen($file_name, 'rb');
$out_file = fopen($out_file_name, 'wb');
but it supposes you need to know the filename contained in the .gz file
regards
You need to use PHP PharData to extract and read its content.
To extract tar or tar.gz :
$phar = new PharData('myphar.tar');
$phar->extractTo('/full/path');
And to list all files, you can use :
archive = new PharData('/upload/directory/myphar.tar.gz');
foreach (new RecursiveIteratorIterator($archive) as $file) {
echo $file . "<br />";
}

PHP fopen create a blank line automatically

Platform: Windows 10 & IIS, PHP 5.6
$base_dir = dirname(__DIR__);
$export_dir = 'export/';
if (!file_exists($export_dir)) {
mkdir($export_dir, 0777, true);
}
$date = date_create(date());
$file_name = date_format($date,"Ymd").".txt";
if (file_exists($export_dir.$file_name)) {
unlink($export_dir . $file_name);
}
$file = fopen($export_dir . $file_name, "w");
fclose($file);
The above code seems perfect with BLANK file output, however, when open the blank file, it contains a BLANK line inside and file size is not 0 kb.
I also tried "wt" or "wb" but output is the same.
What can I do to make sure create the .txt file is 0 kb?

PHP: How would you check if the result string of file_get_contents() is a JPG image?

I am using file_get_contents() to pull some images from a remote server and I want to confirm if the result string is a JPG/PNG image before further processing, like saving it locally and create thumbs.
$string = file_get_contents($url);
How would you do this?
I got from this answer the starting bits for a JPG image. So basically what you could do is to check whether the starting bits are equal or not:
$url = 'http://i.stack.imgur.com/Jh3mC.jpg?s=128&g=1';
$jpg = file_get_contents($url);
if(substr($jpg,0,3) === "\xFF\xD8\xFF"){
echo "It's a jpg !";
}
You can use getimagesize()
$url = 'http://www.geenstijl.nl/archives/images/HassVivaCatFight.jpg';
$file = file_get_contents($url);
$tmpfname = tempnam("/tmp", "FOO");
$handle = fopen($tmpfname, "w");
fwrite($handle, $file);
$size = getimagesize($tmpfname);
if(($size['mime'] == 'image/png') || ($size['mime'] == 'image/jpeg')){
//do something with the $file
echo 'yes an jpeg of png';
}
else{
echo 'Not an jpeg of png ' . $tmpfname .' '. $size['mime'];
fclose($handle);
}
I just tested it so it works. You need to make a temp file becouse the image functions work with local data and they only accept local directory path like 'C:\wamp2\www\temp\image.png'
If you do not use fclose($handle); PHP will automatically delete tmp after script ended.
You can use
exif_imagetype()
to evaluate your file. Please do check the php manual.
Edited :
Please note that PHP_EXIF must be enabled. You can read more about it here
Maybe standart PHP function exif_imagetype() http://www.php.net/manual/en/function.exif-imagetype.php

getimagesize() on stream instead of string

I'm using Valum's file uploader to upload images with AJAX. This script submits the file to my server in a way that I don't fully understand, so it's probably best to explain by showing my server-side code:
$pathToFile = $path . $filename;
//Here I get a file not found error, because the file is not yet at this address
getimagesize($pathToFile);
$input = fopen('php://input', 'r');
$temp = tmpfile();
$realSize = stream_copy_to_stream($input, $temp);
//Here I get a string expected, resource given error
getimagesize($input);
fclose($input);
$target = fopen($pathToFile, 'w');
fseek($temp, 0, SEEK_SET);
//Here I get a file not found error, because the image is not at the $target yet
getimagesize($pathToFile);
stream_copy_to_stream($temp, $target);
fclose($target);
//Here it works, because the image is at the desired location so I'm able to access it with $pathToFile. However, the (potentially) malicious file is already in my server.
getimagesize($pathToFile);
The problem is that I want to perform some file validation here, using getimagesize(). getimagesize only supports a string, and I only have resources available, which result in the error: getimagesize expects a string, resource given.
It does work when I perform getimagesize($pathTofile) at the end of the script, but then the image is already uploaded and the damage could already have been done. Doing this and performing the check afterwards and then maybe deleting te file seems like bad practice to me.
The only thing thats in $_REQUEST is the filename, which i use for the var $pathToFile. $_FILES is empty.
How can I perform file validation on streams?
EDIT:
the solution is to first place the file in a temporary directory, and perform the validation on the temporary file before copying it to the destination directory.
// Store the file in tmp dir, to validate it before storing it in destination dir
$input = fopen('php://input', 'r');
$tmpPath = tempnam(sys_get_temp_dir(), 'upl'); // upl is 3-letter prefix for upload
$tmpStream = fopen($tmpPath, 'w'); // For writing it to tmp dir
stream_copy_to_stream($input, $tmpStream);
fclose($input);
fclose($tmpStream);
// Store the file in destination dir, after validation
$pathToFile = $path . $filename;
$destination = fopen($pathToFile, 'w');
$tmpStream = fopen($tmpPath, 'r'); // For reading it from tmp dir
stream_copy_to_stream($tmpStream, $destination);
fclose($destination);
fclose($tmpStream);
PHP 5.4 now supports getimagesizefromstring
See the docs:
http://php.net/manual/pt_BR/function.getimagesizefromstring.php
You could try:
$input = fopen('php://input', 'r');
$string = stream_get_contents($input);
fclose($input);
getimagesizefromstring($string);
Instead of using tmpfile() you could make use of tempnam() and sys_get_temp_dir() to create a temporary path.
Then use fopen() to get a handle to it, copy over the stream.
Then you've got a string and a handle for the operations you need to do.
//Copy PHP's input stream data into a temporary file
$inputStream = fopen('php://input', 'r');
$tempDir = sys_get_temp_dir();
$tempExtension = '.upload';
$tempFile = tempnam($tempDir, $tempExtension);
$tempStream = fopen($tempFile, "w");
$realSize = stream_copy_to_stream($inputStream, $tempStream);
fclose($tempStream);
getimagesize($tempFile);

PHP zip Function issue

Hello I am usign the below code to zip a package on upload:
$nameFile = $_FILES['file']['name'];
$tmpName = $_FILES['file']['tmp_name'];
$download_folder = './CopyrightFiles/';
$zip = new ZipArchive();
$fileconpress = $download_folder.$nameFile.".zip";
$conpress = $zip->open($fileconpress, ZIPARCHIVE::CREATE);
if ($conpress === true)
{
$zip->addFile($tmpName);
$zip->close();
echo $fileconpress."<br/>";
echo "yess !! Success!!!! ";
}
else echo " Oh No! Error";
It seems to work ok.
But there are two issues.
First issue it saves the file also with the original extension, something like : image.JPG.zip
Also when I then move the zip package to my local computer (Mac) and I open the ZIP inside I can find only a tmp folder with a binary file inside and NOT the image or the file that should be there!
What the hell is going on?
Please advise
Thank you
That's because your "binary" file is just the temporary name that PHP used to temporarily stored the uploaded file as. That's why it's "tmp_name" in the $_FILES array.
Try this:
$zip->addFile($tmpName, $nameFile);
The second parameter lets you specify what the file's name should be within the zip.
To prevent 'file.jpg.zip', try:
$fileconpress = $download_folder . pathinfo($_FILES['file']['name'], PATHINFO_FILENAME) . ".zip";
Issue #1:
You need to manually remove the extension:
$filename = explode('.', $_FILES['file']['name']);
$filename = $filename[0];
Issue #2:
$tmpName does not contain the filename of the file. You need to pass the $localname parameter in addFile(). See http://php.net/manual/en/function.ziparchive-addfile.php.

Categories