How to download the file uploaded to a BLOB field using PhpMyAdmin? - php

I'm running a localhost mysql server with PhpMyAdmin version 4.2. I created a table with a MEDIUMBLOB column to store file. I can upload *.doc files correctly, but when I click the file link, it downloads it as a "tablename-columnname.bin" bin file.
Then I tried to manually rename this "tablename-columnname.bin" to "original_file.doc" and the doc can be opened correctly.
Question: Why phpmyadmin does not download the file as is? What can I do to fix it? I know a bit of php
Thanks!

Use the 'header' before echo the file
header('Content-type: application/msword');
for dynamic way to find the 'Content type' use to store the 'file name' with 'extension' in database.

To make it a bit dynamic (based on MIME) I did the following change:
In tbl_get_field.php file, last few lines:
$mime = PMA_detectMIME($result);
switch($mime){
case 'image/jpeg':
$extension = 'jpg';
case 'image/gif':
$extension = 'gif';
case 'image/png':
$extension = 'png';
case 'application/pdf':
$extension = 'pdf';
default:
$extension = 'bin';
}
PMA_downloadHeader(
$table . '-' . $_GET['transform_key'] . '.' . $extension,
$mime,
strlen($result)
);
echo $result;
Code above should output the file with correct extension instead of always ".bin".
In mime.lib.php file, we need to detect more MIME cases:
function PMA_detectMIME(&$test)
{
$len = strlen($test);
if ($len >= 2 && $test[0] == chr(0xff) && $test[1] == chr(0xd8)) {
return 'image/jpeg';
}
if ($len >= 3 && substr($test, 0, 3) == 'GIF') {
return 'image/gif';
}
if ($len >= 4 && substr($test, 0, 4) == "\x89PNG") {
return 'image/png';
}
return 'application/octet-stream';
}
I want to add pdf and word doc in this, but I dont know how to determine their MIME type base on the stream characters

Related

PHP+Image type detection

I have a email script that sends file trough attachment from server. The email is sent using phpmailer and the attached file is attached in code like this:
$_img = (object) ($img);
if (!empty($_img->src)) {
$ext = substr($_img->src, -3);
$imginfo_array = getimagesize($_img->src);
$mime_type = $imginfo_array['mime'];
switch($mime_type) {
case "image/jpeg":
$type = "image/jpeg";
break;
case "image/png":
$type = "image/png";
break;
case "image/gif":
$type = "image/gif";
break;
}
$string = file_get_contents($_img->src);
$mail->AddStringAttachment($string, $i . '.' . $ext, 'base64', $type);
}
The problem occurs when a image is not properly saved before adding it to server. If one user decides that the file 'test.jpg' shoul be 'test.png' the attached file will not be visible via email.
The $_img->src is a file saved on server.
I am trying to check for mime type but still with no success.
I want to be able to tell the script that the correct file type is the one auto detected not determined by the extension.
Could someone give me a clue about how this could be done?
$_img = (object) ($img);
if (!empty($_img->src)) {
//$ext = substr($_img->src, -3);
// better solution for get file extension (with variable length: "jpeg" or "jpeg")
$ext = pathinfo($_img->src, PATHINFO_EXTENSION);
$imginfo_array = getimagesize($_img->src);
$mime_type = $imginfo_array['mime'];
switch($mime_type) {
case "image/jpeg":
$type = "image/jpeg";
$ext = 'jpg';
break;
case "image/png":
$type = "image/png";
$ext = 'png';
break;
case "image/gif":
$type = "image/gif";
$ext = 'gif';
break;
// fix for others mime type
default:
$type = "application/octet-stream";
}
// for binary file use AddAttachment()
//$string = file_get_contents($_img->src);
//$mail->AddStringAttachment($string, $i . '.' . $ext, 'base64', $type);
// I hope that the variable $i is set from previous code
$mail->AddAttachment($_img->src, $i . '.' . $ext, 'base64', $type)
}
You can detect the type of the image with the IMAGETYPE_XXX constants at index 2 of the returned imginfo_array. The returned mime field you are using is much less reliable.
See documentation:
http://php.net/manual/en/function.getimagesize.php
Type contants:
http://php.net/manual/en/image.constants.php

Creating thumbnail from an uploaded image in Joomla 2.5

I'm really new to joomla, I don't have idea what should I do to make it done. I just have this kind of code in administrator table, it refers to uploading files.
//Support for file field: cover
if(isset($_FILES['jform']['name']['cover'])):
jimport('joomla.filesystem.file');
jimport('joomla.filesystem.file');
$file = $_FILES['jform'];
//Check if the server found any error.
$fileError = $file['error']['cover'];
$message = '';
if($fileError > 0 && $fileError != 4) {
switch ($fileError) :
case 1:
$message = JText::_( 'File size exceeds allowed by the server');
break;
case 2:
$message = JText::_( 'File size exceeds allowed by the html form');
break;
case 3:
$message = JText::_( 'Partial upload error');
break;
endswitch;
if($message != '') :
JError::raiseWarning(500,$message);
return false;
endif;
}
else if($fileError == 4){
if(isset($array['cover_hidden'])):;
$array['cover'] = $array['cover_hidden'];
endif;
}
else{
//Check for filesize
$fileSize = $file['size']['cover'];
if($fileSize > 10485760):
JError::raiseWarning(500, 'File bigger than 10MB' );
return false;
endif;
//Replace any special characters in the filename
$filename = explode('.',$file['name']['cover']);
$filename[0] = preg_replace("/[^A-Za-z0-9]/i", "-", $filename[0]);
//Add Timestamp MD5 to avoid overwriting
$filename = md5(time()) . '-' . implode('.',$filename);
$uploadPath = JPATH_ADMINISTRATOR.DIRECTORY_SEPARATOR.'components'.DIRECTORY_SEPARATOR.'com_comic'.DIRECTORY_SEPARATOR.'images'.DIRECTORY_SEPARATOR.$filename;
$fileTemp = $file['tmp_name']['cover'];
if(!JFile::exists($uploadPath)):
if (!JFile::upload($fileTemp, $uploadPath)):
JError::raiseWarning(500,'Error moving file');
return false;
endif;
endif;
$array['cover'] = $filename;
}
endif;
I could upload the file (in this case, an image) from the codes above, but what I'll do next is creating a thumbnail for the uploaded image. I searched for the php codes through the internet but it doesn't seem to work since I can't synchronize it into joomla codes. Umm.. I've made a folder named thumbnail in images folder. So what should I do next?
I'll be so happy and grateful if any of you could help me with this. Thanks.
Well i can share technique I'm using, i hope it will help:
In table's method check after the all validation is done (at the end of the method, just before returning true) i add the following code:
$input = JFactory::getApplication()->input;
$files = $input->files->get('jform');
if (!is_null($files) && isset($files['image']))
$this->image = $this->storeImage($files['image']);
The i create a new method called storeImage() :
protected $_thumb = array('max_w' => 200, 'max_h' => 200);
private function storeImage($file) {
jimport('joomla.filesystem.file');
$filename = JFile::makeSafe($file['name']);
$imageSrc = $file['tmp_name'];
$extension = strtolower(JFile::getExt($filename));
// You can add custom images path here
$imagesPath = JPATH_ROOT . '/media/';
if (in_array($extension, array('jpg', 'jpeg', 'png', 'gif'))) {
// Generate random filename
$noExt = rand(1000, 9999) . time() . rand(1000, 9999);
$newFilename = $noExt . '.' . $extension;
$imageDest = $imagesPath . $newFilename;
if (JFile::upload($imageSrc, $imageDest)) {
// Get image size
list($w, $h, $type) = GetImageSize($imageDest);
switch ($extension) {
case 'jpg':
case 'jpeg':
$srcRes = imagecreatefromjpeg($imageDest);
break;
case 'png':
$srcRes = imagecreatefrompng($imageDest);
break;
case 'gif':
$srcRes = imagecreatefromgif($imageDest);
break;
}
// Calculating thumb size
if($w > $h) {
$width_ratio = $this->_thumb['max_w'] / $w;
$new_width = $this->_thumb['max_w'];
$new_height = $h * $width_ratio;
} else {
$height_ratio = $this->_thumb['max_w'] / $h;
$new_width = $w * $height_ratio;
$new_height = $this->_thumb['max_w'];
}
$destRes = imagecreatetruecolor($new_width, $new_height);
imagecopyresampled($destRes, $srcRes, 0, 0, 0, 0, $new_width, $new_height, $w, $h);
// Creating resized thumbnail
switch ($extension) {
case 'jpg':
case 'jpeg':
imagejpeg($destRes, $imagesPath . 'thumb_' . $newFilename, 100);
break;
case 'png':
imagepng($destRes, $imagesPath . 'thumb_' . $newFilename, 1);
break;
case 'gif':
imagegif($destRes, $imagesPath . 'thumb_' . $newFilename, 100);
break;
}
imagedestroy($destRes);
// Delete old image if it was set before
if (($this->image != "") && JFile::exists($imagesPath . $this->image)) {
JFile::delete($imagesPath . $this->image);
JFile::delete($imagesPath . 'thumb_' . $this->image);
}
return $newFilename;
}
}
}
}
return null;
}
This method returns uploaded file filename, which table stores in 'image' column. It creates two files, one original image and resized thumb with file prefix '_thumb'.
I hope it helps :)
I used Jimage : https://api.joomla.org/cms-3/classes/JImage.html
$JImage = new JImage($img_path);
$size_thumb = '150x150';
$JImage->createThumbs($size_thumb,1,$path.'/thumb');
Short, simple and efficient.

Suggest file extension from file type

I have an image file name without extension (lets assume it is image_file_name - NOTE IT IS MISSING THE EXTENSION) and I also know the file type (lets assume the file type is image/jpeg). Now is there a php function that returns the file extension given its type? As explained in the following pseudo code:
$extension = get_extension('image/jpeg'); // Will return 'jpg'
$file_name = 'image_file_name' . '.' . $extension; // Will result in $file_name = image_file_name.jpg
Please note that the image above was only an example, the file name could be of any file type, such as a web page file name or anything else. and the extension could be anything as well, it could be html, css ...etc.
Is it possible to do the above? And how?
$ext = substr(image_type_to_extension(exif_imagetype('dev.png')), 1); //example png
This will give you the extension correctly and is more reliable than $_FILE['image']['type'].
You can use finfo to perform mime-magic to determine the file type.
$finfo = finfo_open(FILEINFO_MIME, "/path/to/mimiemagic.file");
$res = $finfo->file($filename);
list($type, $encoding) = explode(";", $res);
$typeToExt = array(
"image/jpeg"=>"jpg",
"image/png"=>"png",
"text/html"=>"html",
"text/plain"=>"txt",
"audio/mpeg"=>"mp3",
"video/mpeg"=>"mpg"
);
$ext = $typeToExt[$type];
You can use FILEINFO_MIME directly to determine MIME type and then use a switch case to add extension. There is this mime_content_type(), but it seems deprecated.
$finfo = new FileInfo(null, 'image_file_name');
// Determine the MIME type of the uploaded file
switch ($finfo->file($_FILES['image']['tmp_name'], FILEINFO_MIME) {
case 'image/jpg':
$extension = 'jpg'
$file_name = 'image_file_name' . '.' . $extension;
break;
case 'image/png':
$extension = 'png'
$file_name = 'image_file_name' . '.' . $extension;
break;
case 'image/gif':
$extension = 'gif'
$file_name = 'image_file_name' . '.' . $extension;
break;
}
For more extensions, keep adding cases to switch.

Downloading files as attachment filesize incorrect

I'm trying to force a link to download a file as an attachment. This is stuff I have done before but something is going wrong and I'm not sure what it is. The file types I am trying to send as attachments are all mp4 files. Here is what I am doing:
<?php
if(isset($_GET['file']))
{
$file_path = dirname(__FILE__) . "/videos/$_GET[file]";
if(file_exists($file_path))
{
$file_url = "/videos/$_GET[file]";
header ("Content-type: video/mp4");
header("Content-Transfer-Encoding: binary");
header("Content-disposition: attachment; filename=\"".basename($_GET['file']) ."\"");
header("Content-Length: ".filesize($file_path));
echo readfile($file_url);
}
}
?>
As you can see I am checking to see if the file exists before trying to serve it. What happens is I get the file, it's type is correct(MP4 Video) but the file is only around 100 btyes in size. As I was debugging I tested to see if the filesize is correct, it is. I've changed the readfile() line to:
header("location:/videos/$_GET[file]");
and it takes me to the video. I've done a fair bit of Googling and I havn't come up with a reason for this behavoiur. Has anyone seen this type of thing before? Any ideas on what could be causing this? Any help would be very much appreciated, thanks much!
If you open the contents of that file you downloaded in a text editor, you will no doubt see an error message. This is probably because your path starts with /. When you open files from disk, the doc root of your server path is meaningless. You need to specify the real path.
Also, your script is terribly insecure! Anyone can download any file they want off your server. Make sure to check that the file is within the doc root before serving it up. Never let a user just specify any file they want without restriction. You don't want some doing ?file=../../../etc/passwd.
Use these functions, it help you.
function getRemoteFilesize($url)
{
$file_headers = #get_headers($url, 1);
if($size =getSize($file_headers)){
return $size;
} elseif($file_headers[0] == "HTTP/1.1 302 Found"){
if (isset($file_headers["Location"])) {
$url = $file_headers["Location"][0];
if (strpos($url, "/_as/") !== false) {
$url = substr($url, 0, strpos($url, "/_as/"));
}
$file_headers = #get_headers($url, 1);
return getSize($file_headers);
}
}
return false;
}
function getSize($file_headers){
if (!$file_headers || $file_headers[0] == "HTTP/1.1 404 Not Found" || $file_headers[0] == "HTTP/1.0 404 Not Found") {
return false;
} elseif ($file_headers[0] == "HTTP/1.0 200 OK" || $file_headers[0] == "HTTP/1.1 200 OK") {
$clen=(isset($file_headers['Content-Length']))?$file_headers['Content-Length']:false;
$size = $clen;
if($clen) {
switch ($clen) {
case $clen < 1024:
$size = $clen . ' B';
break;
case $clen < 1048576:
$size = round($clen / 1024, 2) . ' KiB';
break;
case $clen < 1073741824:
$size = round($clen / 1048576, 2) . ' MiB';
break;
case $clen < 1099511627776:
$size = round($clen / 1073741824, 2) . ' GiB';
break;
}
}
return $size;
}
return false;
}
usage:
echo getRemoteFilesize('https://stackoverflow.com/questions/14679268/downloading-files-as-attachment-filesize-incorrect');

PHP File Upload Recognition help!

SOLVED MY OWN QUESTION! THANKS EVERYONE FOR THE HELP :)
Ok. I'm having trouble with the code below recognizing the upload FILE TYPE and running the correct function. I can upload PNG just fine and it will convert and resize like it should, but GIF and JPEG don't and just return a black image. If I remove the png code and try the others individually they work. I can't figure this out at the moment why when I combine them they won't work. It's like together they all use whatever function comes first, instead of going by the FILE TYPE
if ($width > $max_width){
$scale = $max_width/$width;
if ($_FILE['image']['type'] = "image/png"){
$uploaded = resizeImagePNG($large_image_location,$width,$height,$scale);
} elseif ($_FILE['image']['type'] = "image/gif"){
$uploaded = resizeImageGIF($large_image_location,$width,$height,$scale);
} elseif ($_FILE['image']['type'] = "image/jpeg" || $_FILE['image']['type'] = "image/pjpeg"){
$uploaded = resizeImageJPG($large_image_location,$width,$height,$scale);
}
session_start();
$_SESSION['image2resize'] = $large_image_location;
}else{
$scale = 1;
if ($_FILE['image']['type'] = "image/png"){
$uploaded = resizeImagePNG($large_image_location,$width,$height,$scale);
} elseif ($_FILE['image']['type'] = "image/gif"){
$uploaded = resizeImageGIF($large_image_location,$width,$height,$scale);
} elseif ($_FILE['image']['type'] = "image/jpeg" || $_FILE['image']['type'] = "image/pjpeg"){
$uploaded = resizeImageJPG($large_image_location,$width,$height,$scale);
}
session_start();
$_SESSION['image2resize'] = $large_image_location;
}
}
edit: combined with Pekka's method for the mime, and rewritten for clarity
You have an error in all your if/elseif comparations. You need to put double == instead of single =
You may use this code that should do the same, but in a cleaner and safer way
$info = getimagesize(($_FILE['image']['tmp_name']);
$mime = $info["mime"];
if ($width > $max_width){
$scale = $max_width/$width;
} else {
$scale = 1;
}
switch ($mime)
{
case "image/png":
$uploaded = resizeImagePNG($large_image_location,$width,$height,$scale);
break;
case "image/gif":
$uploaded = resizeImageGIF($large_image_location,$width,$height,$scale);
break;
case "image/jpeg":
$uploaded = resizeImageJPG($large_image_location,$width,$height,$scale);
break;
default:
// do a better handling of the error
die('image type not supported');
}
session_start();
$_SESSION['image2resize'] = $large_image_location;
Also, don't rely on $_FILE['image']['type'], as this value is sent by the browser and an attacker can forge it. Use the getimagesize() method for obtaining the filetype as Pekka suggested in his answer.
#Carlos answers your question.
As a side note, I wouldn't rely on the MIME type server by the user's browser at all, and use getimagesize() to detect the file type instead.
$info = getimagesize(($_FILE['image']['tmp_name']);
$mime = $info["mime"];
that is safer.
FIGURED IT OUT!!!!!!!! The verification was screwing things up. Instead of checking if it's not a image, I checked if it was and it started working. NEW verification -> if ($mime == 'image/gif' || $mime == 'image/jpeg' || $mime == 'image/pjpeg' || $mime == 'image/png' || $_FILES['image']['size'] < 3000000){ working code here } else { error code here } . Thanks for all the help!

Categories