I had an image upload script that worked on my little shared hosting, but just as I switched to Virt Ded, it immediately stopped working. After some research I determined the culprit to be the PHP function imagejpeg() - which was the last bit of code in the script.
It allows me to specify null as the filepath (in which case it prints it to the screen), but does not allow me to enter ANY filepath without return false.
Anybody know what is going on?
First I would see if the PHP install contains all the libgd stuff you need for imagejpeg().
You can check like this:
$extensions = get_loaded_extensions();
if( !in_array( 'gd', $extensions ) )
{
die "libgd is not loaded";
}
If that's good to go you can do something like:
$gd = gd_info();
while( list( $k, $v ) = each( $gd ) )
{
echo "$k: $v";
}
Make sure you see some jpeg stuff listed, if there is none you need some dependent libraries installed.
Related
First of all I would like to mention that I'm a complete noob in php and since I'm playing around with wordpress based websites I started fiddling with PHP code. I have absolutely no background in php and most of my knowledge comes from reading code and using php.net reference to undestand the causal relationships and generally what is happening.
I have come up with a solution for a problem that I have, however I feel that solution is ugly and could be optimized to be more readable and more efficient. I'm asking this question primarily as mean to learn from the answers, so if you honor me with a reply it will be greatly appreciated if you throw in a few lines of argumentation as to why this optimization is viable.
The goal of the code is to take the contents of $image_path which is just a filename of an image that has either jpg, jpeg or png file extension and rewrite that filename by adding -200x100 just before the extension(foo.jpg turns into foo-200x100.jpg). Here is the code I came up with:
if (strpos($image_path, '.jpeg')) {
$image_thumb = substr_replace($image_path, '-200x100.jpeg', strpos($image_path, '.jpeg'));
}
elseif (strpos($image_path, '.jpg')) {
$image_thumb = substr_replace($image_path, '-200x100.jpg', strpos($image_path, '.jpg'));
}
elseif (strpos($image_path, '.png')) {
$image_thumb = substr_replace($image_path, '-200x100.png', strpos($image_path, '.png'));
}
else {
$image_thumb = 'No image';
}
Your solution matches the extension in any part of the path, which is probably not what you want:
$image_path = '/some/path/images.jpeg/this-is-an-image.jpeg';
Result:
/some/path/images-200x100.jpeg
You can use pathinfo() to parse $image_path into its components and then put them back together with modifications:
$pathinfo = pathinfo($image_path);
if (isset($pathinfo['extension']) && in_array($pathinfo['extension'], array('jpeg', 'jpg', 'png'), true)) {
$image_thumb = sprintf('%s/%s-200x100.%s', $pathinfo['dirname'], $pathinfo['filename'], $pathinfo['extension']);
} else {
$image_thumb = 'No image';
}
Result for the previous example:
/some/path/images.jpeg/this-is-an-image-200x100.jpeg
I've already asked a couple of questions regarding this and each step gets me closer however it still doesnt work as intended.
I want to upload an image and write it to the textfile, then when i upload another image that will be written to the end and so on so forth. So ultimately you'll have a long file with lots of images.
As far as i can tell my code should work but it doesn't. Here is a link to the site website for testing. Testing it maybe useful and below is the code.
It also always creates an empty element at the end of the array as you'll see from testing the site.
The PHP:
$sFileName = "imgDB.txt";
for ($i=0 ; $i < count($_FILES) ; $i++) {
move_uploaded_file(
$_FILES['file-'.$i]['tmp_name'],
"img/". $_FILES['file-'.$i]['name']
);
}
$sImgs = file_get_contents($sFileName); //gets a string from the file.
if (json_decode($sImgs, true) != false) {
$ajImgs = json_decode($sImgs, true);
} else {
$ajImgs = array();
}
$aOutPut = array_merge ($ajImgs, $_FILES);
$aSendToFile = json_encode(
$aOutPut,
JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE
);
file_put_contents($sFileName, $aSendToFile);
Some remarks
if the move_uploaded_file call is not protected further, this allows to upload any files, including script files - this opens a security vulnerability in your application - check for MIME-type and file-extension to avoid this
json_decode returns null if the input value is empty or cannot be decoded - not false like in your code
appending to an array is not done with array_merge, this just overrides the properties of $_FILES of the previous execution - use $aOutPut[] = $_FILES; instead
I am facing a little problem with php, I want to write in a file but if is empty and the function file_exists() return true I can proceed with the writing function or to append data, but if the file don't exists I am force to make another option to create the file in this case i use file_put_contents and the function make the file by her self. Any way i want to use only silent function like this: #filesize('file.txt') without the # i get a warning like the file don't exists and pass on, I want to know if is reliable to use the function with the error control operator(#). Thank you in advance!
And my code:
if (#filesize('entries.txt') > 0 ){
file_put_contents('entries.txt', ',' . time(), FILE_APPEND);
}else {
file_put_contents('entries.txt', time());
}
The result i came with is as follow:
if( !file_exists( $entries )) file_put_contents( $entries, '');
$smilliseconds = filesize( $entries ) >= 10? ','. $milliseconds: $milliseconds;
No, you shouldn't use the # operator - ever. It masks problems that you otherwise need to know about and there is nearly always a better approach. For example, you could combine your file_exists check like this:
if (file_exists('entries.txt') && filesize('entries.txt') > 0 ){
I try mime_content_type() / finfo_open(). It is ok for .doc but return 'application/zip' for .docx and nothing for .xls
what is the problem ? is it a issue with my browser?
This question is basically the same: PHP 5.3.5 fileinfo() MIME Type for MS Office 2007 files - magic.mime updates?
And it seems there is no solution. It's not your browser, it's a mime "magic" file that tried to guess, and there is no way to tell the different between docx and a zipfile because docx IS in fact a zipfile!
If you're like me and may or may not be using php>=5.3.0 servers for whatever reason and want to use one set of code for all servers, and perhaps insist on involving the mime_content_type function somehow for servers that do not have Fileinfo, then you can use a half-arsed solution like mine, which is to make a replacement function which is that on php>=5.3.0 it uses Fileinfo, and on lower versions, if the filename ends in a specific string unique to something you want to override, it returns your hardcoded value, and calls mime_content_type() for all other types. However, of course this will NOT work if the file is of a type that mime_content_type() incorrectly detects and where the file name does not end in an extension, but that should be very rare.
Such a solution might look something like this:
function _mime_content_type($filename)
{
//mime_content_type replacement that uses Fileinfo native to php>=5.3.0
if( phpversion() >= '5.3.0' )
{
$result = new finfo();
if (is_resource($result) === true)
{
return $result->file($filename, FILEINFO_MIME_TYPE);
}
}
else
{
if( substr( $filename, -5, 5 ) == '.docx' )
return 'application/vnd.openxmlformats-officedocument.wordprocessingml.document';
else if( substr( $filename, -5, 5 ) == '.xlsx' )
return 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet';
else if( substr( $filename, -5, 5 ) == '.pptx' )
return 'application/vnd.openxmlformats-officedocument.spreadsheetml.presentation';
//amend this with manual overrides to your heart's desire
return mime_content_type( $filename );
}
}
and then you simply have to replace all your calls to mime_content_type with calls to _mime_content_type.
Is there any decent way in PHP to get the mime type?
I have been searching extensively the past few hours and it seems like there are three main ways, which each way having problems:
mime_content_type()
This is deprecated, alot of the times not installed, and if installed will sometimes not find the mime.magic file.
file_info
Wasn't installed on the hosts I tried, doesn't seem to have very good support. Is an extension (PECL).
shell_exec(file -ib . $file)
Doesn't work on windows servers. I tried it on a linux server and it gave me "image/x-3ds2" for a php file. What the hell is that!!!
What is a good, almost bullet proof way to get the mime type of a file?
As workaround you can use the "mime.php" extension from http://upgradephp.berlios.de/
It simulates the mime_content_type() if not available. Made specifically for such cases.
You can install your private mime.magic file and force it with ini_set("mime_magic.magicfile"). This is recommended anyway, so you have the desired settings available.
Chris Jean has developed a function called get_file_mime_type that first tries to use the finfo_open method, then falls back to the mime_content_type, then finally falls back to a simple extension => mime_type array. It works well for me when the first two options were not available on my server. Beats having to write the function myself!
You can use the magic numbers, consult some other file signature lists ( like this one here ), and then check the binary data for the first byte .
function getfiletype($file) {
$handle = #fopen($file, 'r');
if (!$handle)
throw new Exception('File error - Can not open File or file missing');
$types = array( 'jpeg' => "\xFF\xD8\xFF",
'gif' => 'GIF',
'bmp' => 'BM',
'tiff' => '\x49\x20\x49',
'png' => "\x89\x50\x4e\x47\x0d\x0a",
'psd' => '8BPS',
'swf' => 'FWS');
$bytes = fgets($handle, 8);
$filetype = 'other';
foreach ( $types as $type => $header ) {
if ( strpos( $bytes, $header ) === 0) {
$filetype = $type;
break;
}
}
fclose($handle);
return $filetype;
}
This is actually a very simple replacement function for file_info(), which operates in much the same way but on a much extended ( and lower ) level .
Alternative is using an already made external php class like this one for example ..