Replace save files if from same User - php

I have a directory called resale_certificates where I save files to but encrypt the name using parts of their email and codes assigned to them.
NOTE: The encryption is the same every time but unique to each user!
When they upload image.png it will save the file to theirEncrypt.png
If they upload another image.png it will replace theirEncrypt.png
However when they upload image.jpg now there will be theirEncrypt.jpg and theirEncrypt.png in the resale_certificates directory.
What is the best way to handle this? I'm looking for advice and open to changing how I'm saving it or tricks I could do to prevent this!
Thank You!

Well, you could use an image library to transform their uploaded image to whatever format you want, i.e. if they upload a .JPG you can use image libraries like Imagick or GD to output a .PNG file and upload those.
However, if you don't mind either the .JPG or .PNG ( or .GIF for that matter) you can scan the directory with PHP to look for all files ( can be really intensive though! ) to look for files with the name given.
For example:
<?php
foreach( scandir('/path/to/resale_certificates/') as $file ){
if( $file != '.' && $file != '..'){
// explode so we remove the last extension path ( not type safe ! )
$arguments = explode('.', $file);
// store the last part
$ext = end($arguments);
// pop the extension from the $arguments array so we are left
// with whatever was left
array_pop($arguments);
// concatenate the $arguments into a single string again
$filename = implode('.', $arguments);
// now we can check the filename again
if( $filename == $theirEncrypt){
unlink('/path/to/resale_certificates/' . $filename . '.' . $ext);
}
}
}
edit:
the $file is a string from the $files array returned by the scandir(); function. The single and double dot are a ways to navigate to the current (.) and the parent (..) directory and are therefore symlinks. Another option would be to check if the $file is actually a file. You could replace the comparison line with a is_file('/path/to/resale_certificates/' . $file) to check if it's a file or a symlink ( like the . and the .. ) but it's even more intensive then to check string comparison. In your usecase it is not neccesary.
On a related note, this is quite intensive, depending on the number of clients and certificates you have, you could, as an alternative, store the filename to storage (i.e. database or something similiar) and just unlink the file find there, this would save you to iterate over each file and simply unlink the file directly.

If you know a name of previously uploaded image then you can do the following before saving a new image:
<?php
$previousImageName = 'theirEncrypt.png';
unlink(APP_DIR . "/resale_certificates/" . $previousImageName);

Related

PHP fileupload type check

Ok here is my code for uploading files
$ext_whitelist = array('pdf','doc','doc','mkv','mp4','mpg','mpeg','avi','flv','wma','ogg');
if(in_array($ext, $ext_whitelist))
{
$uniqid_file = uniqid('', true)."_".$file['name'];
$lokacija = $folder . "/" . $uniqid_file;
$encoded_uniqid_file = base64_encode($uniqid_file);
move_uploaded_file($file['tmp_name'], $lokacija);
$base_url= base_url("forms/fdownload/$encoded_uniqid_file/$path");
$form_data[$key] = "$uniqid_file ";
}
This checks file extension, so easy some could rename file, can someone help me to check file type proper?
Insted of a comment, I'll write a bit more as an answer.
Mimetype checking is a good thing if you want to know the type of the file, but it's not secure if you want to allow/deny the files at upload, because it's very easy to fake the mimetype.
Just try it, you can change it with a proxy or you can create a simple image, then add some php code at the end and rename it to .php. If you only check the mimetype, you can upload this .php file and run it on the server.
If you upload .jpg with php code in it, it's okay, the server won't push it through the php parser. (Except when you change the default configuration. (Apache: AddType, nginx: AddHandler )
There are some "secure" ways to check the uploaded files:
1. Check the extension and compare it to a whitelist.
This is the example in the question, but I'd like to write a complete solution. (A common mistake to check only the first think after the ., because there could be file names like: something.txt.php so always check the last postfix.)
$ext = array_pop(explode(".", $fileName));
$whitelist = array('pdf','doc','doc','mkv','mp4','mpg','mpeg','avi','flv','wma','ogg');
if (in_array($ext, $whitelist) {
//OK the extension is good, handle the upload.
} else {
//Wrong type, add error message.
}
If you use something like this, be careful and never allow extensions like .php and anything wich is in the server config.
2. Rename the file and drop the extension.
This is an another good way, but maybe you want to keep the original file name, the extension and the mimetype. You can store them in a database!
For this solution just take the original filename, add some random data (because if you upload into a single folder and you trie to upload something.jpg 2 time that would be a bad idea), then store this.
For example:
$newName = sha1($fileName.time());
move_uploaded_file($file['tmp_name'], $uploadPath . $newName);
Because the file doesn't have an extension, the server wont try to run it. (But if it's for example an image it'll work in the browsers, because they use the mimetype to determine the type and we didn't changed that.)
You can use
perl-file-mimeinfo
Ex:-
$file_path = '/tmp/temp.jpg';
$mimetype = trim(shell_exec("/usr/bin/mimetype -bi ".escapeshellarg($file_path)));
$info = null;
if(strpos($mimetype, "video/")===0 || strpos($mimetype, 'x-flash-video') > 0){
$info = 'video';
}elseif(strpos($mimetype, "audio/")===0){
$info = 'audio';
}elseif(strpos($mimetype, "image/")===0){
$info = 'image';
}

Changing the filename of a file stored on Amazon S3 upon download

So I have an upload service with many people uploading the same files to my Amazon S3 bucket. I changed my app design so the SHA1 of the file is calculated upon upload and checked against the list of uploaded files.
If it exists, I simply assign the file to the new uploader as well.
The problem with this is, the file being named as the first uploader named it. All subsequent uploaders will get the same first name.
I can use download="" attribute in HTML5 but it doesn't work in IE:
http://caniuse.com/#search=download
The files are stored remotely so I can't change the header unless I download it first to my local server which is illogical.
Please advice.
The only way I see this possible is to add a meta-data just before redirecting user to download.
You can add meta-data to your files in S3. With key as "Content-Disposition" and value as 'attachment; filename="~actual file name~"'. You can force the name and trigger download.
This way, you don't have to download any files to local file system.
The caveat to this is if someone else is also requesting the same file with in milli-seconds, first user might get the name as requested by second user.
use the rename() method
example:
$file = "boo.png";
$newName = "scary";
$ext = substr( $file, strpos( "." ), strlen( $file ) );
$path = "/images/downloaded/";
rename($path . $file, $path . $newName . $ext);
php documentation

How can I change the name of an image that is being uploaded to my server?

When someone uploads an image to my server, it uploads as the name they have for the image on their computer. I want the image name to become a short number as the name instead of the name, because when someone uploads an image as the same name, it overwrites it.
Here is my script where the names are defined:
if(isset($_FILES['fileup']) && strlen($_FILES['fileup']['name']) > 1) {
$uploadpath = $uploadpath . basename( $_FILES['fileup']['name']);
$sepext = explode('.', strtolower($_FILES['fileup']['name']));
$type = end($sepext);
list($width, $height) = getimagesize($_FILES['fileup']['tmp_name']);
$err = '';
This is a piece of (working) code I wrote a few years ago, that I still use to this day.
You probably may have to modify it to fit your script as well as the position in the script and the path.
However, I did replace my own original name (photo) with your fileup name.
Plus there are a few other goodies in there you probably could use, somewhere down the line.
$file_name = $HTTP_POST_FILES['fileup']['name'][0];
// should there be spaces in the uploaded file, replace them with an underscore
$file_name = str_replace(" ","_",$file_name);
$random_digit = substr(number_format(time() * rand(),0,'',''),0,10);
$new_file_name=$random_digit._.$file_name;
$path1= "./uploads/".$new_file_name;
// you can also use (my original write):
// copy($HTTP_POST_FILES['fileup']['tmp_name'][0], $path1);
move_uploaded_file($HTTP_POST_FILES['fileup']['tmp_name'][0], $path1);
$path_to_file_web = "http://www.example.com/uploads/$new_file_name";
The original script that I wrote was used on an older server with an older PHP version.
However, copy() will still work.
I do something like this:
i am just add some random string at beginning of file name
$new=generate_name(10);
$name=$new.$name;
Function generate_name();
function generate_name($long){
$cadena="[^A-Z0-9]";
return substr(eregi_replace($cadena, "", md5(rand())) .
eregi_replace($cadena, "", md5(rand())) .
eregi_replace($cadena, "", md5(rand())),
0, $long);
}
and generate this name:
03f396a35902-06-2013.csv
from 02-06-2013.csv file.
Not only do you not have to use the name provided when uploading a file, you shouldn't do so - like any user input, it is untrusted and could be used as a security hole.
So all you need to do is generate a random image name, and ensure it is not one that you've already used (e.g. by checking with file_exists() and using a do ... while loop to keep generating random names until that returns false). Then use that as the argument to move_uploaded_file(), which is the correct function to use for putting the file into a final location.
If you don't mind too much about the length and format, uniqid() is a good way to generate your filenames, because it is based on the current time so is unlikely to produce collisions.

How can I improve this PHP code?

I have the php code below which help me get a photo's thumbnail image path in a script
It will take a supplied value like this from a mysql DB '2/34/12/thepicture.jpg'
It will then turn it into this '2/34/12/thepicture_thumb1.jpg'
I am sure there is a better performance way of doing this and I am open to any help please
Also on a page with 50 user's this would run 50 times to get 50 different photos
// the photo has it is pulled from the DB, it has the folders and filename as 1
$photo_url = '2/34/12/thepicture_thumb1.jpg';
//build the full photo filepath
$file = $site_path. 'images/userphoto/' . $photo_url;
// make sure file name is not empty and the file exist
if ($photo_url != '' && file_exists($file)) {
//get file info
$fil_ext1 = pathinfo($file);
$fil_ext = $fil_ext1['extension'];
$fil_explode = '.' . $fil_ext;
$arr = explode($fil_explode, $photo_url);
// add "_thumb" or else "_thumb1" inbetween
// the file name and the file extension 2/45/12/photo.jpg becomes 2/45/12/photo_thumb1.jpg
$pic1 = $arr[0] . "_thumb" . $fil_explode;
//make sure the thumbnail image exist
if (file_exists("images/userphoto/" . $pic1)) {
//retunr the thumbnail image url
$img_name = $pic1;
}
}
1 thing I am curious about is how it uses pathinfo() to get the files extension, since the extension will always be 3 digits, would other methods of getting this value better performance?
Is there a performance problem with this code, or are you just optimizing prematurely? Unless the performance is bad enough to be a usability issue and the profiler tells you that this code is to blame, there are much more pressing issues with this code.
To answer the question: "How can I improve this PHP code?" Add whitespace.
Performance-wise, if you're calling built-in PHP functions the performance is excellent because you're running compiled code behind the scenes.
Of course, calling all these functions when you don't need to isn't a good idea. In your case, the pathinfo function returns the various paths you need. You call the explode function on the original name when you can build the file name like this (note, the 'filename' is only available since PHP 5.2):
$fInfo = pathinfo($file);
$thumb_name = $fInfo['dirname'] . '/' . $fInfo['filename'] . '_thumb' . $fInfo['extension'];
If you don't have PHP 5.2, then the simplest way is to ignore that function and use strrpos and substr:
// gets the position of the last dot
$lastDot = strrpos($file, '.');
// first bit gets everything before the dot,
// second gets everything from the dot onwards
$thumbName = substr($file, 0, $lastDot) . '_thumb1' . substr($file, $lastDot);
The best optimization for this code is to increase it's readability:
// make sure file name is not empty and the file exist
if ( $photo_url != '' && file_exists($file) ) {
// Get information about the file path
$path_info = pathinfo($file);
// determine the thumbnail name
// add "_thumb" or else "_thumb1" inbetween
// the file name and the file extension 2/45/12/photo.jpg
// becomes 2/45/12/photo_thumb.jpg
$pic1 = "{$path_info['dirname']}/{$path_info['basename']}_thumb.{$fil_ext}";
// if this calculated thumbnail file exists, use it in place of
// the image name
if ( file_exists( "images/userphoto/" . $pic1 ) ) {
$img_name = $pic1;
}
}
I have broken up the components of the function using line breaks, and used the information returned from pathinfo() to simplify the process of determining the thumbnail name.
Updated to incorporate feedback from #DisgruntledGoat
Why are you even concerned about the performance of this function? Assuming you call it only once (say, when the "main" filename is generated) and store the result, its runtime should be essentially zero compared to DB and filesystem access. If you're calling it on every access to re-compute the thumbnail path, well, that's wasteful but it's still not going to be significantly impacting your runtime.
Now, if you want it to look nicer and be more maintainable, that's a worthwhile goal.
The easiest way to fix this is to thumbnail all user profile pics before hand and keep it around so you don't keep resizing.
$img_name = preg_replace('/^(.*)(\..*?)$/', '\1_thumb\2', $file);
Edit: bbcode disappeared with \.

I made an upload script in PHP. How do I avoid overwriting files?

I've made an image upload script using the move_uploaded_file function. This function seems to overwrite any preexisting file with the new one. So, I need to check if the target location already has a file. If it does then I need to append something to the filename(before the extension so that the file name is still valid) so the filename is unique. I'd like to have the change be minimal instead of something like appending the datetime, if possible.
How can I do this with PHP?
When uploading files I will nearly always rename them. Typically there will be some kind of database record for that file. I use the ID of that to guarantee uniqueness of the file. Sometimes I'll even store what the client's original filename was in the database too but I'll never keep it or the temporary name because there is no guarantee that information is good, that your OS will support it or that it's unique (which is your issue).
So just rename it to some scheme of your own devising. That's my advice.
If you don't have any database reference, then you could use file_exists() for this but there's no guarantee that between the time of checking if something exists and moving it that something else won't use that same filename that you'll then overwrite. This is a classic race condition.
http://us3.php.net/manual/en/function.file-exists.php
Don't use file_exists() for the reason that it returns true (on *nix systems at least, since directories are specialized files) if the value is a directory. Use is_file() instead.
For example, say something fails and you have a string like:
$path = "/path/to/file/" . $file; // Assuming $file is an empty value, if something failed for example
if ( true === file_exists($path) ) { echo "This returns true"; }
if ( true === is_file($path) ) { echo "You will not read this"; }
It's caused a few problems in the past for me, so I always use is_file() rather than file_exists().
I use date and time functions to generate a random file name based on the time of upload.
Let's assume you are submitting a file from a form where you have an input named incomingfile like this:
<input type="file" id="incomingfile" name="incomingfile" />
First of all I use to "depure" the filename and copy it from the default temporary directory to a temporary directory. This is necessary to deal with special characters. I had troubles when I didn't adopt this practice.
$new_depured_filename = strtolower(preg_replace('/[^a-zA-Z0-9_ -.]/s', '_', $_FILES["incomingfile"]["name"]));
copy($_FILES["incomingfile"]["tmp_name"], 'my_temp_directory/'.$new_depured_filename);
With the following piece of code I check if the file exists, if so, I find a new name and finally copy it. For example if I want to write a file called myimage.jpg and it already exists I rename the pending file to myimage__000.jpg. If this exists as well I rename the pending file to myimage__001.jpg and so on until I find a non-existing filename.
$i=0; // A counter for the tail to append to the filename
$new_filename = $new_depured_filename;
$new_filepath='myfiles/music/'.$new_filename;
while(file_exists($new_filepath)) {
$tail = str_pad((string) $i, 3, "0", STR_PAD_LEFT); // Converts the integer in $i to a string of 3 characters with left zero fill.
$fileinfos = pathinfo($new_filepath); // Gathers some infos about the file
if($i>0) { // If we aren't at the first while cycle (where you have the filename without any added strings) then delete the tail (like "__000") from the filename to add another one later (otherwise you'd have filenames like myfile__000__001__002__003.jpg)
$previous_tail = str_pad((string) $i-1, 3, "0", STR_PAD_LEFT);
$new_filename = str_replace('__'.$previous_tail,"",$new_filename);
}
$new_filename = str_replace('.'.$fileinfos['extension'],"",$new_filename); // Deletes the extension
$new_filename = $new_filename.'__'.$tail.'.'.$fileinfos['extension']; // Append our tail and the extension
$new_filepath = 'myfiles/music/'.$new_filename; // Crea il nuovo percorso
$i++;
}
copy('my_temp_directory/'.$new_depured_filename, $new_filepath); // Finally we copy the file to its destination directory
unlink('my_temp_directory/'.$new_depured_filename); // and delete the temporary one
Used functions:
strtolower
preg_replace
copy
file_exists
str_pad
pathinfo
str_replace
unlink
To check if a file exists, you can use the file_exists function.
To cut the filename, you can use the pathinfo function.
I use
$file_name = time() . "_" . $uploaded_file_name;

Categories