I am using Jquery uploader to upload images to my website. It uses a file called uploadhandler.php to manipulate the files. Inside the uploadhandler.php is the following function which appears to make changes to how the filename is formatted etc.
The problem I am having is if I upload a file with spaces in the file name it doesn't appear to be removing the spaces in the file name. Does anyone know how I can edit it to add an extra command to remove any spaces in the file name, or point me in the right direction on how to do it ?.
protected function trim_file_name($name, $type, $index, $content_range) {
// Remove path information and dots around the filename, to prevent uploading
// into different directories or replacing hidden system files.
// Also remove control characters and spaces (\x00..\x20) around the filename:
$file_name = trim(basename(stripslashes($name)), ".\x00..\x20");
// Add missing file extension for known image types:
if (strpos($file_name, '.') === false &&
preg_match('/^image\/(gif|jpe?g|png)/', $type, $matches)) {
$file_name .= '.'.$matches[1];
}
while(is_dir($this->get_upload_path($file_name))) {
$file_name = $this->upcount_name($file_name);
}
$uploaded_bytes = $this->fix_integer_overflow(intval($content_range[1]));
while(is_file($this->get_upload_path($file_name))) {
if ($uploaded_bytes === $this->get_file_size(
$this->get_upload_path($file_name))) {
break;
}
$file_name = $this->upcount_name($file_name);
}
return $file_name;
}
The line:
$file_name = trim(basename(stripslashes($name)), ".\x00..\x20");
Will remove spaces "around" the filename, such as "foo " because of the x20 bit which is a space. You could simply add directly after this line:
$file_name = str_replace(" ", "", $file_name);
Easy as that! Also remember, when you use the 2nd parameter in trim() you remove the "default" list of characters listed in the manual ( http://php.net/trim ) and replace it with your own ...
I would also point out, I would never use the filename as given by the browser in $_FILES[$x]['name'] ... It simply opens too many questions and possibilities up. One technique to avoid the issue altogether might be to simply use the md5() or sha1() or similar of the file's contents, example:
$file_name = md5_file($_FILES['your_file_tag_name']['tmp_name']);
That way in theory, you never ever have spaces in the files, or "dirty" filenames ... And in addition, if a user uploads two files with the precise same contents, you simply need to check for the file's existance, and if it already exists, you already have that exact same file. Hope this helps, this all assumes you're doing file uploads, which I'm not 100% certain you are.
Related
I have a PHP program which scans a folder named output (which contains all image files in any format) for images. The image files are the screenshots of the output in terminal (I'm using Linux) of various Java programs. The image files are named according to the class name in which the main() function resides. So for example if the main() function resides inside the public Example class, then the output screenshot will be named Example with the extension of either .jpg, .jpeg, .png or .gif. The PHP program has a front page which scans for Java files and lists them in an unordered list with links the user can click to go on the next page. The next page reads the particular file and displays the source code along with the output screenshot. Now since I'm using Fedora and Fedora takes screenshots in png format, that is quite easy like:
echo '<img src="' . $file_name . '".png>'
But what if someone uploads a Java program with the output screenshot in any format? (jpg, jpeg, png, gif). How to then load the appropriate image file since I don't know what the extension will be?
I have an answer to use foreach loop and read through every image file there is within the output folder and then use an if condition for checking the appropriate file names with the various extensions but I think it will not be a very good programming practice.
I generally try to avoid conditions while programming and use more mathematical approach cause that gives me the challenge I need and I feel my code looks different and unique compared to others' but I don't seem to make it work this time.
I'm feeling that this can be done using regular expressions but I don't know how to do it. I know regular expressions but I'm clueless to even how to use them for this. Any answer to not use regular will be appreciated but I want to make this work using regular expressions because in that way I'll also add a little bit of knowledge to my regular expression concepts.
Thanks.
Here's an alternative to MM's that uses RegEx:
function getImageFilename ($basename, $directory) {
$filenames = scandir($directory);
$pattern = "/^" . $basename . "\.(jpeg|png|jpg|gif)$/";
foreach($filenames as $filename) {
preg_match($pattern, $filename, $matches);
if($matches) {
return $filename;
}
}
return false;
}
You can't avoid using a loop. You either loop through the possible file names and check for their existence, or you get a list of all the files in the directory and loop through them whilst performing a pattern match.
If there aren't a lot of files in the directory then this function might perform better because it only needs to call the OS once (to get a list of the files in the directory), whereas asking the OS to check for file existence multiple times requires multiple system calls. (I think that's right...)
One possible solution, you could check if the file exists with that extension (assuming you won't have multiple images with the same name but different extensions):
function get_image($file_name) {
if (file_exists($file_name . '.png')) {
return $file_name . '.png';
} elseif (file_exists($file_name . '.jpg')) {
return $file_name . '.jpg';
} elseif (file_exists($file_name . '.gif')) {
return $file_name . '.gif';
}
return false;
}
echo '<img src="' . get_image($file_name) . '">';
You define the pattern as an or list of the various extensions:
$pattern = '/\.(jpg|png|gif)$/i';
We are also making sure this is an extension by including the match with a dot (escaped) and making sure it's at the end of the string ($). The "i" at the end of that enables case-insensitive matching, so that the regex still picks up GIF or JPG in filenames.
After that, the test is fairly simple:
if (preg_match($pattern, $filename)) {
echo "File $filename is an image";
}
Putting it together in an example, you can see:
$filename = 'test.png';
$pattern = '/\.(jpg|png|gif)$/i';
if (preg_match($pattern, $filename)) {
echo "File $filename is an image";
}
https://eval.in/618651
Whether you want to wrap that in a function, is up to you, as you would have to decide what to return in case the filename does not match one of the extensions provided.
Also note that the test is based on the extension only and not on the content.
if(isset($_POST['submit']))
{
$file = $_FILES['file']['name'];
$fh = fopen($file,'r+');
// string to put username and passwords
$users = '';
while(!feof($fh)) {
$user = explode(' ',fgets($fh));
foreach ($user as $value)
{
$number= rand(1000,10000);
$final_number[] = $value .','. $number;
}
}
//print_r($final_number);
file_put_contents($_FILES['file']['name'], $final_number);
}
this is my code for appending a random text to a string with comma and save it in text file but when i am saving it it is not saving properly after comma it is going to next line which should not happen plzz.. help me
Your code starts with a very big issue: you try to open and read from a file that, most probably, doesn't exist.
$file = $_FILES['file']['name'];
$fh = fopen($file,'r+');
As you can read in the documentation, assuming that your form contains an input element of type file having the name file, $_FILES['file']['name'] is the original name of the uploaded file, on the user's computer. It is only the name and it is not the name of the file on the server. It is provided just as a hint for the file's content (check the filename extension) but you cannot rely on it.
The content of the file is temporarily stored on the webserver in a file whose path can be found in $_FILES['file']['tmp_name']. You should pass it to the PHP function is_uploaded_file() to be sure the file was uploaded and your script is not the victim of an injection attempt then, if you need to keep it, use move_uploaded_file() to move it where you need. If you don't move it, when your script ends the temporary file is deleted.
Another problem of your code is on the lines:
$user = explode(' ',fgets($fh));
foreach ($user as $value)
As explained in the documentation, the function fgets() called without a second argument reads a line from the input file, including the newline character that ends it. Since you split the line into words I think you don't need the newline character. You can remove it by using trim() with the string returned by fgets() before passing it to explode().
The last issue of the code is:
file_put_contents($_FILES['file']['name'], $final_number);
Because $final_number is an array1, file_put_contents() joins its elements to get a string and writes the string into file. This operation concatenates the random value generated for a $value with the next $value and there is no way to tell which is which after the data is stored in the file. You probably need to keep them on separate lines. Use function implode() on $final_number, with "\n" as its first argument and write the generated string into the file instead.
The last one: don't write the generated content to $_FILES['file']['name']. It is not safe! It contains a string received from the browser; a malicious user can put whatever path they want there and your script will overwrite a file that it shouldn't change.
Create a directory dedicated to store files generated by your code and generate filenames based on an always incremented counter (the current time() or microtime() f.e.) for the files you store there. Never trust the data you receive from the browser.
1 $final_number is used as $final_number[] = ... and, because it is not defined when this line of code is executed for the first time, PHP creates an empty array for you and stores it in $final_number. Don't rely on this feature. Always initialize your variables before their first use. Put $final_number = array(); before the while().
I am going to use a different approach than you, let's say that the data you want to save to the file is stored in the variable $data.
So to append this data to the file with a comma at first, we can use just two lines of code:
$previousFileContent = file_get_contents("filename.txt");
file_put_contents("filename.txt", trim($previousFileContent . "," . $data));
I have coded a little upload script that works just fine in every case when I use it, but I always get messages from my client that he gets an error that I die() when the upload goes wrong/doesn't work.
I believe that this was caused by the special characters they use. Because they are Austrians they have special chars like äÄöÖüÜß in their filenames. Plus they use whitespaces in there filenames.
Therefore I used a regex to replace special characters into underlines(_).
$moveFile = function($tmpname,$name,$time) {
// the regex to resolve the special chars problem
$name = preg_replace('/[^a-zA-Z0-9\.]/s', '_', $name);
if (!move_uploaded_file($tmpname,'assets/siteContents/bewerbungen/'.$time.'_'.$name)) {
die('something went wrong while uploading');
}
};
// move application_files__image
$moveFile($_FILES['application_files__image']['tmp_name'],
$_FILES['application_files__image']['name'],
$time);
// move application_files__image
$moveFile($_FILES['application_files__cv']['tmp_name'],
$_FILES['application_files__cv']['name'],
$time);
// move application_files__certificates
if (count($_FILES['application_files__certificates']['name'])) {
foreach ($_FILES['application_files__certificates']['name'] as $i => $name) {
$moveFile($_FILES['application_files__certificates']['tmp_name'][$i],
$_FILES['application_files__certificates']['name'][$i],
$time);
$a_list[] = 'assets/siteContents/bewerbungen/'.$time.'_'.preg_replace('/[^a-zA-Z0-9\.]/s', '_',$_FILES['application_files__certificates']['name'][$i]);
}
}
If the error isn't caused by the special chars in the filename I am not sure what the problem might be.
The function returns FALSE on this conditions:
If filename is not a valid upload file, then no action will occur, and
move_uploaded_file() will return FALSE.
If filename is a valid upload file, but cannot be moved for some
reason, no action will occur, and move_uploaded_file() will return
FALSE. Additionally, a warning will be issued.
(Source: PHP.NET)
You are filtering your filename with this regex /[^a-zA-Z0-9\.]/s but this will only replace the first occurence of a special char not all.
Try adding the "g" modifier: /[^a-zA-Z0-9\.]/sg
Are you sure your client has the right permissions to move the file
to the desired location? I would double check them.
I'm at a loss as to how I could build a loop to pdftotext and entire directory through a shell_exec() statement.
Something like :
$pdfs = glob("*.pdf");
foreach($pdfs as $pdfs) {
shell_exec('pdftotext '.$pdfs.' '.$pdfs'.txt');
}
But I'm unsure how I can drop the .pdf extension the 2nd time I call $pdfs in my shell_exec() statement and replace that with .txt
Not really sure this loop is correct either....
Try
foreach(glob("*.pdf") as $src) {
// Manually remove file extension because glob() may return a dir path component
$parts = explode('.', $src);
$parts[count($parts) - 1] = 'txt';
$dest = implode('.', $parts);
// Escape shell arguments, just in case
shell_exec('pdftotext '.escapeshellarg($src).' '.escapeshellarg($dest));
}
Basically, loop the PDF files in the directory and execute the command for each one, using just the name component of the file name (extracted with pathinfo())see edit for the output file (so test.pdf becomes test.txt).
Using the result of glob() directly in foreach easily avoids the variable naming collision you had in the code above.
EDIT
I have change the above code to manually remove the file extension when generating the output file name. This is because glob() may return a directory component of the path strings, as well as just a file name. Using pathinfo() or basename() will strip this off, and since we know that a . will be present in the file name (the rule passed to glob() dictates this) we can safely remove everything after the last one. I have also added escapeshellarg() for good measure - it is highly unlikely (if not impossible) that a file name that already exists would fall foul of this, but it is best to be safe.
$pdfs = glob("*.pdf");
$fmt='/path/to/pdftotext "%s" "%s.txt"';
foreach($pdfs as $thispdf) {
shell_exec(sprintf($fmt, $thispdf, basename($thispdf, ".pdf")));
}
I want to store a path (pointing to a directory) in a text file and open the path when required in PHP. Here's what I have done, which is quite simple but doesn't really work.
$dir = file_get_contents('./dir_file');
$dir_content = get_fname($dir);
function get_fname($dir) {
$dirhandle = opendir($dir);
if (!dirhandle) { exit; }
.........
}
The value of $dir is what it is in the text file. The code doesn't work. The function exits in the if statement.
I tried to replace the first line with
$dir = '/home/user/work'; //which is the path stored in the text file.
It works. So I suspect it's the problem of opendir. I can't figure out what causes this problem.
Any help will be appreciated. Many thanks.
Check if the file you're reading from has any line breaks, spaces, etc... after the actual path part. If you pass those in to opendir, it's going to look for a directory which has those literal characters in it, and most likely fail.
Adding a trim() call may help:
$dir = trim(file_get_contents('./dir_file'));
which will remove any such whitespace characters.