I got ascript which helps me to add some data into a csv file, based on the fact if a image is inside a folder or not (exits or not). Files are images, so I need to check if the file exists, and if it is a png, jpg, jpeg, gif.
So far it only check if it a JPG but I would like it to find the file exists if it's a PNG or JPEG or even GIF.
<?php
$columns = array("row1","row2","row3","row4","row5","row6","row7","row8","row9",
"row10","row11","row12","row13","row14","row15","row16","row17","row18"
);
$rootDir = "/path/to/images/folder/files";
$file = fopen("database.csv", "r") or die('fopen database failed');
$newFile = fopen("newdata.csv", "w") or die('fopen newdata.csv failed');
while (($data = fgetcsv($file, 999999, ";")) !== FALSE) {
$row = array_combine($columns, $data);
$filename = $row['row4'].".jpg"; // could be png or jpEg, or even gif
if (file_exists("$rootDir/$filename")) {
$row['image'] = .$filename; //also needs correct extension of image which exists.
$row['small_image'] = .$filename;
$row['thumbnail'] = .$filename;
}
fputcsv($newFile, array_values($row), ";",'"' );
}
fclose($file);
fclose($newFile);
?>
You can do something like this:
// your code
$possible_extensions = array("jpg", "jpeg", "png", "gif");
$row = array_combine($columns, $data);
foreach($possible_extensions as $ext){
$filename = $row['row4'] . "." . $ext;
if (file_exists("$rootDir/$filename")) {
$row['image'] = .$filename;
$row['small_image'] = .$filename;
$row['thumbnail'] = .$filename;
break;
}
}
fputcsv($newFile, array_values($row), ";",'"' );
// your code
Edited:
If you want to perform case-insensitive file_exists() check then here's the solution,
The following fileExists() function returns the full path file if found, and false if not.
function fileExists($fileName, $caseSensitive = true) {
if(file_exists($fileName)) {
return $fileName;
}
if($caseSensitive) return false;
// Handle case insensitive requests
$directoryName = dirname($fileName);
$fileArray = glob($directoryName . '/*', GLOB_NOSORT);
$fileNameLowerCase = strtolower($fileName);
foreach($fileArray as $file) {
if(strtolower($file) == $fileNameLowerCase) {
return $file;
}
}
return false;
}
Here's the source:
PHP Case Insensitive Version of file_exists()
And now your code,
// your code
$possible_extensions = array("jpg", "jpeg", "png", "gif");
$row = array_combine($columns, $data);
foreach($possible_extensions as $ext){
$filename = $row['row4'] . "." . $ext;
if ($filename = fileExists("$rootDir/$filename", false)) {
$row['image'] = .$filename; //also needs correct extension of image which exists.
$row['small_image'] = .$filename;
$row['thumbnail'] = .$filename;
break;
}
}
fputcsv($newFile, array_values($row), ";",'"' );
// your code
Related
I am developing a module for my client to upload and browse file in Opencart.
when I am uploading file from my back-end server I am getting the output as file.zip.xyzasdf. Where I just want to remove this .xyzasdf
Can any one suggest me how to remove sanitize from the following code...
public function upload() {
$this->load->language('catalog/download');
$json = array();
// Check user has permission
if (!$this->user->hasPermission('modify', 'catalog/download')) {
$json['error'] = $this->language->get('error_permission');
}
if (!$json) {
if (!empty($this->request->files['file']['name']) && is_file($this->request->files['file']['tmp_name'])) {
// Sanitize the filename
$filename = basename(html_entity_decode($this->request->files['file']['name'], ENT_QUOTES, 'UTF-8'));
// Validate the filename length
if ((utf8_strlen($filename) < 3) || (utf8_strlen($filename) > 128)) {
$json['error'] = $this->language->get('error_filename');
}
// Allowed file extension types
$allowed = array();
$extension_allowed = preg_replace('~\r?\n~', "\n", $this->config->get('config_file_ext_allowed'));
$filetypes = explode("\n", $extension_allowed);
foreach ($filetypes as $filetype) {
$allowed[] = trim($filetype);
}
if (!in_array(strtolower(substr(strrchr($filename, '.'), 1)), $allowed)) {
$json['error'] = $this->language->get('error_filetype');
}
// Allowed file mime types
$allowed = array();
$mime_allowed = preg_replace('~\r?\n~', "\n", $this->config->get('config_file_mime_allowed'));
$filetypes = explode("\n", $mime_allowed);
foreach ($filetypes as $filetype) {
$allowed[] = trim($filetype);
}
if (!in_array($this->request->files['file']['type'], $allowed)) {
$json['error'] = $this->language->get('error_filetype');
}
// Check to see if any PHP files are trying to be uploaded
$content = file_get_contents($this->request->files['file']['tmp_name']);
if (preg_match('/\<\?php/i', $content)) {
$json['error'] = $this->language->get('error_filetype');
}
// Return any upload error
if ($this->request->files['file']['error'] != UPLOAD_ERR_OK) {
$json['error'] = $this->language->get('error_upload_' . $this->request->files['file']['error']);
}
} else {
$json['error'] = $this->language->get('error_upload');
}
}
if (!$json) {
$file = $filename . '.' . token(32);
move_uploaded_file($this->request->files['file']['tmp_name'], DIR_FOLDER . $file);
$json['filename'] = $file;
$json['mask'] = $filename;
$json['success'] = $this->language->get('text_upload');
}
$this->response->addHeader('Content-Type: application/json');
$this->response->setOutput(json_encode($json));
}
Any help would be greatly appreciated...
Thanks
Removing the random string that is added to the filename is simple. Just change
move_uploaded_file($this->request->files['file']['tmp_name'], DIR_UPLOAD . $file);
to:
move_uploaded_file($this->request->files['file']['tmp_name'], DIR_UPLOAD . $filename);
But keep in mind that this will bring problems.
OpenCart saves the random string in the database at the time of file upload, so it will later use it to identify the file.
If you delete this feature, the uploaded files in the admin panel will not be available.
im trying to remove the file extension from each file name in a loop so ball.jpg can be echoed as ball, but it isnt working for me
I have this code
$files = array();
foreach($src_files as $file)
{
$ext = strrchr($file, '.');
if(in_array($ext, $extensions))
{
array_push( $files, $file);
$thumb = $src_folder.'/'.$file;
$fileName = basename($file);
$place = preg_replace("/\.[^.]+$/", "", $fileName);
}
}
Try this:
$src_files = array('/tmp/path/file1.txt', '/tmp/path/file2.txt.php', '/tmp/not.ext');
$extensions = array('.txt', '.php');
$files = array();
foreach ($src_files as $file)
{
$ext = strrchr($file, '.');
var_dump($ext);
if (in_array($ext, $extensions))
{
array_push($files, $file);
//$thumb = $src_folder.'/'.$file;
$pathInfo = pathinfo($file);
$fileName = $pathInfo['basename'];
$place = $pathInfo['filename'];
var_dump($pathInfo);
}
}
If you just want the filename, without extension, use pathinfo($fileName, PATHINFO_FILENAME);. See here for more information.
If you don't want to use pathinfo(), you can also use string manipulation techniques:
$place = substr($fileName, 0 , (strrpos($fileName, ".")));
strrpos() is like strpos(), but searches for a character starting from the end of the string and working backwards.
I have a folder and have multiple files over there. The file has the below pattern for example.
The file names should be renamed from
file1.mp4.png
file2.flv.png
file3.xxx.png (xxx - can be anything)
to as follows (the last extension remains).
file1.png
file2.png
file3.png
Files having non-png extension should be left untouched.
I am using the logic mentioned in Bulk Rename Files in a Folder - PHP
$handle = opendir("path to directory");
if ($handle) {
while (false !== ($fileName = readdir($handle))) {
$newName = (how to get new filename) // I am struck here
rename($fileName, $newName);
}
closedir($handle);
}
How best I can do this to do a bulk update?
<?php
// Select all PNG Files
$matches = glob("*.[pP][nN][gG]");
// check if we found any results
if ( is_array ( $matches ) ) {
// loop through all files
foreach ( $matches as $filename) {
// rename your files here
$newfilename = current(explode(".", $filename)).".png";
rename($filename, $newfilename);
echo "$filename -> $newfilename";
}
}
?>
try this
$handle = opendir("path to directory");
if ($handle) {
while (false !== ($fileName = readdir($handle))) {
$arr_names = explode(".", $fileName);
$size = sizeof($arr_names);
$ext = $arr_names[$size-1];
if($fileName=="." || $fileName==".." || is_dir($fileName))
{
continue; // skip png
}
if($ext=='png' || $ext=='PNG')
{
$newName = $arr_names[0].".".$ext;
rename($fileName, $newName);
}
}
closedir($handle);
}
Shortest using regex
$handle = opendir("path to directory");
if ($handle) {
while (false !== ($fileName = readdir($handle))) {
$newName = preg_replace("/\.(.*?)\.png$/", '', $fileName); // removes .xxx.png
rename($fileName, ($newName . '.png')); // renames file1.png
}
closedir($handle);
}
I'm working on a system that uses images, and the images are named by a md5-ed email. And I'd like to add a -1 -2 etc after the newly uploaded image if an image with the md5-ed email name already exists. Here's my code:
public function upload() {
global $email;
$fileName = $_FILES['userfile']['name'];
$tmpName = $_FILES['userfile']['tmp_name'];
$fileSize = $_FILES['userfile']['size'];
$fileType = $_FILES['userfile']['type'];
$user = $_SESSION['user'];
$fp = fopen($tmpName, 'r');
$content = fread($fp, filesize($tmpName));
$content = addslashes($content);
fclose($fp);
if(!get_magic_quotes_gpc()) {
$fileName = addslashes($fileName);
}
$new_file_name = md5($email);
$fileExists = file_exists("../lib/uploads/" . $new_file_name);
$query = mysql_query("SELECT * FROM avatars WHERE ( name='$fileName' ) OR ( name='$new_file_name' ) ");
$num_rows = mysql_num_rows($query);
if ( $fileExists ) {
$fileName = $new_file_name;
$first = 1;
$separator = '-';
while ( file_exists("../lib/uploads/" . $fileName) ) {
preg_match('/(.+)'.$separator.'([0-9]+)$/', $fileName, $match);
$new_file_name = isset($match[2]) ? $match[1].$separator.($match[2] + 1) :$fileName.$separator.$first;
$first++;
}
$fileName = $new_file_name;
} elseif ( empty( $fileName ) ) {
echo '<div class="error">Please Select a file first.</div>';
} else {
move_uploaded_file($_FILES["userfile"]["tmp_name"],
"lib/avatars/" . $fileName);
echo "<div class='success'>File $fileName Uploaded.</div>";
}
} // ends upload() function
But I don't know what's wrong, it uploads the image with it's original name. Not even with the md5-ed email as name.
In short
You've messed up your if statements.
In detail
This is very veryu very simple. In your last else (the one that executes when the file doesnt exist) you have
move_uploaded_file($_FILES["userfile"]["tmp_name"],
"lib/avatars/" . $fileName);
But if you trace back, you will see that $fileName is set to
$fileName = $_FILES['userfile']['name'];
and not the md5 of the email. You have to remove the final else condition and have its code execute EVERY time. Of course as long as the $fileName is not empty.
So your code should be:
if ( $fileExists ) {
$fileName = $new_file_name;
$first = 1;
$separator = '-';
while ( file_exists("../lib/uploads/" . $new_file_name ) ) {
preg_match('/(.+)'.$separator.'([0-9]+)$/', $new_file_name, $match);
$new_file_name = isset($match[2]) ? $match[1].$separator.($match[2] + 1) :$new_file_name.$separator.$first;
$first++;
}
}
// <----
// Moved this one outside, since it always executes
// ---->
$fileName = $new_file_name;
// <----
// Separated this if, since it has nothing to do with the above
// ---->
if ( empty( $fileName ) ) {
echo '<div class="error">Please Select a file first.</div>';
} else {
move_uploaded_file($_FILES["userfile"]["tmp_name"],
"lib/avatars/" . $fileName);
echo "<div class='success'>File $fileName Uploaded.</div>";
}
} // ends upload() function
How you can optimize it
This depends if you are expecting single users to have lot's of images. If this is NOT the case, then leave it as is.
Otherwise, you will quickly end up having to wait for a long time after uploading 10th, 20th photo.
One way to improve it would be to search for files in a directory that fit a pattern (in this case your md5). For example like this:
foreach (glob($md5 . "*") as $filename) {
echo "$filename size " . filesize($filename) . "\n";
}
This way you instantly know if there are already files with this md5 and how many of them.
I've been doing research on image file upload security for a while but can't seem to crack it. I want to add some security to the fantastic Valums Ajax Uploader by checking whether or not a file is actually an image before saving to a server. The only extensions allowed are .jpg, .png and .gif, which of course the extensions are checked but I'm looking to validate it's an image file via GD processing. I know very little about this subject so I'm taking cues from this and this post. As it stands now, I can easily save a random file with an image extension and it will be saved the server, which I want to prevent. Here is the script I've come up with thus far, which I've added to the handleUpload function in the php.php file. Unfortunately the result is that it returns an error no matter what file I upload, valid image or not. Please excuse my utter newbishness.
$newIm = #imagecreatefromjpeg($uploadDirectory . $filename . '.' . $ext);
$newIm2 = #imagecreatefrompng($uploadDirectory . $filename . '.' . $ext);
$newIm3 = #imagecreatefromgif($uploadDirectory . $filename . '.' . $ext);
if (!$newIm && !$newIm2 && !$newIm3) {
return array('error' => 'File is not an image. Please try again');
}else{
imagedestroy($newIm);
imagedestroy($newim2);
imagedestroy($newIm3);
}
Here's most of my php.php file. By the way, my files are not being submitted via a regular form but by the default uploader:
class qqUploadedFileXhr {
/**
* Save the file to the specified path
* #return boolean TRUE on success
*/
function save($path) {
$input = fopen("php://input", "r");
$temp = tmpfile();
$realSize = stream_copy_to_stream($input, $temp);
fclose($input);
if ($realSize != $this->getSize()){
return false;
}
$target = fopen($path, "w");
fseek($temp, 0, SEEK_SET);
stream_copy_to_stream($temp, $target);
fclose($target);
return true;
}
function getName() {
return $_GET['qqfile'];
}
function getSize() {
if (isset($_SERVER["CONTENT_LENGTH"])){
return (int)$_SERVER["CONTENT_LENGTH"];
} else {
throw new Exception('Getting content length is not supported.');
}
}
}
/**
* Handle file uploads via regular form post (uses the $_FILES array)
*/
class qqUploadedFileForm {
/**
* Save the file to the specified path
* #return boolean TRUE on success
*/
function save($path) {
if(!move_uploaded_file($_FILES['qqfile']['tmp_name'], $path)){
return false;
}
return true;
}
function getName() {
return $_FILES['qqfile']['name'];
}
function getSize() {
return $_FILES['qqfile']['size'];
}
}
class qqFileUploader {
private $allowedExtensions = array();
private $sizeLimit = 2097152;
private $file;
function __construct(array $allowedExtensions = array(), $sizeLimit = 2097152){
$allowedExtensions = array_map("strtolower", $allowedExtensions);
$this->allowedExtensions = $allowedExtensions;
$this->sizeLimit = $sizeLimit;
$this->checkServerSettings();
if (isset($_GET['qqfile'])) {
$this->file = new qqUploadedFileXhr();
} elseif (isset($_FILES['qqfile'])) {
$this->file = new qqUploadedFileForm();
} else {
$this->file = false;
}
}
private function checkServerSettings(){
$postSize = $this->toBytes(ini_get('post_max_size'));
$uploadSize = $this->toBytes(ini_get('upload_max_filesize'));
if ($postSize < $this->sizeLimit || $uploadSize < $this->sizeLimit){
$size = max(1, $this->sizeLimit / 1024 / 1024) . 'M';
die("{'error':'increase post_max_size and upload_max_filesize to $size'}");
}
}
private function toBytes($str){
$val = trim($str);
$last = strtolower($str[strlen($str)-1]);
switch($last) {
case 'g': $val *= (1024 * 1024 * 1024);
case 'm': $val *= (1024 * 1024);
case 'k': $val *= 1024;
}
return $val;
}
/**
* Returns array('success'=>true) or array('error'=>'error message')
*/
function handleUpload($uploadDirectory, $replaceOldFile = FALSE){
if (!is_writable($uploadDirectory)){
return array('error' => "Server error. Upload directory isn't writable.");
}
if (!$this->file){
return array('error' => 'No files were uploaded.');
}
$size = $this->file->getSize();
if ($size == 0) {
return array('error' => 'File is empty');
}
if ($size > $this->sizeLimit) {
return array('error' => 'File is too large, please upload files that are less than 2MB');
}
$pathinfo = pathinfo($this->file->getName());
$filename = $pathinfo['filename'];
//$filename = md5(uniqid());
$ext = $pathinfo['extension'];
if($this->allowedExtensions && !in_array(strtolower($ext), $this->allowedExtensions)){
$these = implode(', ', $this->allowedExtensions);
return array('error' => 'File has an invalid extension, it should be one of '. $these . '.');
}
if(!$replaceOldFile){
/// don't overwrite previous files that were uploaded
while (file_exists($uploadDirectory . $filename . '.' . $ext)) {
$filename .= rand(10, 99);
}
}
$newIm = #imagecreatefromjpeg($uploadDirectory . $filename . '.' . $ext);
$newIm2 = #imagecreatefrompng($uploadDirectory . $filename . '.' . $ext);
$newIm3 = #imagecreatefromgif($uploadDirectory . $filename . '.' . $ext);
if (!$newIm && !$newIm2 && !$newIm3) {
return array('error' => 'File is not an image. Please try again');
}else{
imagedestroy($newIm);
imagedestroy($newim2);
imagedestroy($newIm3);
}
if ($this->file->save($uploadDirectory . $filename . '.' . $ext)){
// At this point you could use $result to do resizing of images or similar operations
if(strtolower($ext) == 'jpg' || strtolower($ext) == 'jpeg' || strtolower($ext) == 'gif' || strtolower($ext) == 'png'){
$imgSize=getimagesize($uploadDirectory . $filename . '.' . $ext);
if($imgSize[0] > 100 || $imgSize[1]> 100){
$thumbcheck = make_thumb($uploadDirectory . $filename . '.' . $ext,$uploadDirectory . "thumbs/" . $filename ."_thmb" . '.' . $ext,100,100);
if($thumbcheck == "true"){
$thumbnailPath = $uploadDirectory . "thumbs/" . $filename ."_thmb". '.' . $ext;
}
}else{
$this->file->save($uploadDirectory . "thumbs/" . $filename ."_thmb" . '.' . $ext);
$thumbnailPath = $uploadDirectory . "thumbs/" . $filename ."_thmb". '.' . $ext;
}
if($imgSize[0] > 500 || $imgSize[1] > 500){
resize_orig($uploadDirectory . $filename . '.' . $ext,$uploadDirectory . $filename . '.' . $ext,500,500);
$imgPath = $uploadDirectory . $filename . '.' . $ext;
$newsize = getimagesize($imgPath);
$imgWidth = ($newsize[0]+30);
$imgHeight = ($newsize[1]+50);
}else{
$imgPath = $uploadDirectory . $filename . '.' . $ext;
$newsize = getimagesize($imgPath);
$imgWidth = ($newsize[0]+30);
$imgHeight = ($newsize[1]+50);
}
}
return array('success'=>true,
'thumbnailPath'=>$thumbnailPath,
'imgPath'=>$imgPath,
'imgWidth'=>$imgWidth,
'imgHeight'=>$imgHeight
);
} else {
return array('error'=> 'Could not save uploaded file.' .
'The upload was cancelled, or server error encountered');
}
}
}
// list of valid extensions, ex. array("jpeg", "xml", "bmp")
$allowedExtensions = array();
// max file size in bytes
$sizeLimit = 2097152;
$uploader = new qqFileUploader($allowedExtensions, $sizeLimit);
$result = $uploader->handleUpload('uploads/');
// to pass data through iframe you will need to encode all html tags
echo htmlspecialchars(json_encode($result), ENT_NOQUOTES);
If someone can point me in the right direction about what I'm doing wrong, it would be most appreciated.
Edit:
Thanks Mark B for the help and clarification. So the new code (which I pasted in the same location as the old, the handleUpload function) is still throwing an error no matter what I upload, so I wonder if it needs to be in a different place -- I'm just not sure where to put it.
$newIm = getimagesize($uploadDirectory . $filename . '.' . $ext);
if ($newIm === FALSE) {
return array('error' => 'File is not an image. Please try again');
}
Second Edit:
I believe the answer is here, still trying to implement it.
Just use getimagesize():
$newIm = getimagesize$uploadDirectory . $filename . '.' . $ext');
if ($newIm === FALSE) {
die("Hey! what are you trying to pull?");
}
The problem with your code is the 3 imagecreate calls and subsequent if() statement. It should have been written as an OR clause. "if any of the image load attempts fail, then complain". Yours is written as "if all image attempts fail", which is not possible if a gif/jpg/png actually was uploaded.
The answer detailed here works like a charm, I wish I had seen it before posting. I hope I implemented it correctly...as I have it, it works!
class qqUploadedFileXhr {
/**
* Save the file to the specified path
* #return boolean TRUE on success
*/
function save($path) {
// 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(), 'upload'); // upl is 3-letter prefix for upload
$tmpStream = fopen($tmpPath, 'w'); // For writing it to tmp dir
$realSize = stream_copy_to_stream($input, $tmpStream);
fclose($input);
fclose($tmpStream);
if ($realSize != $this->getSize()){
return false;
}
$newIm = getimagesize($tmpPath);
if ($newIm === FALSE) {
return false;
}else{
// 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);
return true;
}
}
function getName() {
return $_GET['qqfile'];
}
function getSize() {
if (isset($_SERVER["CONTENT_LENGTH"])){
return (int)$_SERVER["CONTENT_LENGTH"];
} else {
throw new Exception('Getting content length is not supported.');
}
}
}