mirror of
https://github.com/processwire/processwire.git
synced 2025-08-09 08:17:12 +02:00
Minor optimizations and improvements to WireUpload class
This commit is contained in:
@@ -6,7 +6,7 @@
|
||||
* Saves uploads of single or multiple files, saving them to the destination path.
|
||||
* If the destination path does not exist, it will be created.
|
||||
*
|
||||
* ProcessWire 3.x, Copyright 2016 by Ryan Cramer
|
||||
* ProcessWire 3.x, Copyright 2023 by Ryan Cramer
|
||||
* https://processwire.com
|
||||
*
|
||||
*/
|
||||
@@ -141,6 +141,12 @@ class WireUpload extends Wire {
|
||||
*/
|
||||
protected $errorInfo = array();
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
*
|
||||
*/
|
||||
protected $initialized = false;
|
||||
|
||||
/**
|
||||
* Construct with the given input name
|
||||
*
|
||||
@@ -148,6 +154,29 @@ class WireUpload extends Wire {
|
||||
*
|
||||
*/
|
||||
public function __construct($name) {
|
||||
parent::__construct();
|
||||
|
||||
$this->setName($name);
|
||||
$this->maxFiles = 0; // no limit
|
||||
$this->overwrite = false;
|
||||
$this->destinationPath = '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Wired to API
|
||||
*
|
||||
*/
|
||||
public function wired() {
|
||||
parent::wired();
|
||||
$this->init();
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize
|
||||
*
|
||||
*/
|
||||
protected function init() {
|
||||
$this->initialized = true;
|
||||
|
||||
$this->errorInfo = array(
|
||||
UPLOAD_ERR_OK => $this->_('Successful Upload'),
|
||||
@@ -158,16 +187,13 @@ class WireUpload extends Wire {
|
||||
UPLOAD_ERR_NO_TMP_DIR => $this->_('Missing a temporary folder.'),
|
||||
UPLOAD_ERR_CANT_WRITE => $this->_('Failed to write file to disk.'),
|
||||
UPLOAD_ERR_EXTENSION => $this->_('File upload stopped by extension.')
|
||||
);
|
||||
);
|
||||
|
||||
$this->setName($name);
|
||||
$this->maxFiles = 0; // no limit
|
||||
$this->overwrite = false;
|
||||
$this->destinationPath = '';
|
||||
$config = $this->wire()->config;
|
||||
|
||||
if($this->config->uploadBadExtensions) {
|
||||
$badExtensions = $this->config->uploadBadExtensions;
|
||||
if(is_string($badExtensions) && $badExtensions) $badExtensions = explode(' ', $badExtensions);
|
||||
if($config->uploadBadExtensions) {
|
||||
$badExtensions = $config->uploadBadExtensions;
|
||||
if(is_string($badExtensions) && strlen($badExtensions)) $badExtensions = explode(' ', $badExtensions);
|
||||
if(is_array($badExtensions)) $this->badExtensions = $badExtensions;
|
||||
}
|
||||
}
|
||||
@@ -179,7 +205,7 @@ class WireUpload extends Wire {
|
||||
public function __destruct() {
|
||||
// cleanup files that were backed up when overwritten
|
||||
foreach($this->overwrittenFiles as $bakDestination => $destination) {
|
||||
if(is_file($bakDestination)) $this->wire('files')->unlink($bakDestination);
|
||||
if(is_file($bakDestination)) $this->wire()->files->unlink($bakDestination);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -192,13 +218,14 @@ class WireUpload extends Wire {
|
||||
*/
|
||||
public function execute() {
|
||||
|
||||
if(!$this->initialized) $this->init();
|
||||
if(!$this->name) throw new WireException("You must set the name for WireUpload before executing it");
|
||||
if(!$this->destinationPath) throw new WireException("You must set the destination path for WireUpload before executing it");
|
||||
|
||||
$files = array();
|
||||
$uploadFiles = array();
|
||||
|
||||
$f = $this->getPhpFiles();
|
||||
if(!$f) return $files;
|
||||
if(!$f) return $uploadFiles;
|
||||
|
||||
if(is_array($f['name'])) {
|
||||
// multi file upload
|
||||
@@ -213,17 +240,17 @@ class WireUpload extends Wire {
|
||||
$cnt++;
|
||||
}
|
||||
|
||||
$files = $this->completedFilenames;
|
||||
$uploadFiles = $this->completedFilenames;
|
||||
|
||||
} else {
|
||||
// single file upload, including ajax
|
||||
if($this->isValidUpload($f['name'], $f['size'], $f['error'])) {
|
||||
$this->saveUpload($f['tmp_name'], $f['name'], !empty($f['ajax'])); // returns filename or false
|
||||
$files = $this->completedFilenames;
|
||||
$uploadFiles = $this->completedFilenames;
|
||||
}
|
||||
}
|
||||
|
||||
return $files;
|
||||
return $uploadFiles;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -249,7 +276,7 @@ class WireUpload extends Wire {
|
||||
*/
|
||||
protected function getUploadDir() {
|
||||
|
||||
$config = $this->wire('config');
|
||||
$config = $this->wire()->config;
|
||||
$dir = $config->uploadTmpDir;
|
||||
|
||||
if(!$dir && stripos(PHP_OS, 'WIN') === 0) {
|
||||
@@ -283,8 +310,9 @@ class WireUpload extends Wire {
|
||||
*/
|
||||
protected function getPhpFilesAjax() {
|
||||
|
||||
if(!$filename = $_SERVER['HTTP_X_FILENAME']) return false;
|
||||
$filename = rawurldecode($filename); // per #1487
|
||||
if(empty($_SERVER['HTTP_X_FILENAME'])) return false;
|
||||
|
||||
$filename = rawurldecode($_SERVER['HTTP_X_FILENAME']); // per #1487
|
||||
$dir = $this->getUploadDir();
|
||||
$tmpName = tempnam($dir, wireClassName($this, false));
|
||||
|
||||
@@ -311,7 +339,7 @@ class WireUpload extends Wire {
|
||||
'size' => $filesize,
|
||||
'error' => $error,
|
||||
'ajax' => true,
|
||||
);
|
||||
);
|
||||
|
||||
return $file;
|
||||
}
|
||||
@@ -348,11 +376,12 @@ class WireUpload extends Wire {
|
||||
*
|
||||
*/
|
||||
protected function isValidUpload($name, $size, $error) {
|
||||
$valid = false;
|
||||
$fname = $this->wire('sanitizer')->name($name);
|
||||
|
||||
$fname = $this->wire()->sanitizer->name($name);
|
||||
|
||||
if($error && $error != UPLOAD_ERR_NO_FILE) {
|
||||
$this->error($this->errorInfo[$error]);
|
||||
$valid = false;
|
||||
} else if(!$size) {
|
||||
$valid = false; // no data
|
||||
} else if($name[0] == '.') {
|
||||
@@ -362,8 +391,10 @@ class WireUpload extends Wire {
|
||||
"$fname - " . $this->_('Invalid file extension, please use one of:') . ' ' .
|
||||
implode(', ', $this->validExtensions)
|
||||
);
|
||||
$valid = false;
|
||||
} else if($this->maxFileSize > 0 && $size > $this->maxFileSize) {
|
||||
$this->error("$fname - " . $this->_('Exceeds max allowed file size'));
|
||||
$valid = false;
|
||||
} else {
|
||||
$valid = true;
|
||||
}
|
||||
@@ -379,7 +410,7 @@ class WireUpload extends Wire {
|
||||
*/
|
||||
protected function checkDestinationPath() {
|
||||
if(!is_dir($this->destinationPath)) {
|
||||
$this->error("Destination path does not exist {$this->destinationPath}");
|
||||
$this->error("Destination path does not exist: $this->destinationPath");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
@@ -416,9 +447,11 @@ class WireUpload extends Wire {
|
||||
*
|
||||
*/
|
||||
public function validateFilename($value, $extensions = array()) {
|
||||
|
||||
$value = basename($value);
|
||||
if($value[0] == '.') return false; // no hidden files
|
||||
$value = $this->wire('sanitizer')->filename($value, Sanitizer::translate);
|
||||
|
||||
$value = $this->wire()->sanitizer->filename($value, Sanitizer::translate);
|
||||
if($this->lowercase) $value = strtolower($value);
|
||||
$value = trim($value, "_");
|
||||
if(!strlen($value)) return false;
|
||||
@@ -506,11 +539,11 @@ class WireUpload extends Wire {
|
||||
if(!$destination || !$filename) $destination = $this->destinationPath . 'invalid-filename';
|
||||
if(!$error) $error = "Unable to move uploaded file to: $destination";
|
||||
$this->error($error);
|
||||
if(is_file($tmp_name)) $this->wire('files')->unlink($tmp_name);
|
||||
if(is_file($tmp_name)) $this->wire()->files->unlink($tmp_name);
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->wire('files')->chmod($destination);
|
||||
$this->wire()->files->chmod($destination);
|
||||
|
||||
if($p['extension'] == 'zip' && ($this->maxFiles == 0) && $this->extractArchives) {
|
||||
if($this->saveUploadZip($destination)) {
|
||||
@@ -536,30 +569,35 @@ class WireUpload extends Wire {
|
||||
|
||||
// unzip with command line utility
|
||||
|
||||
$fileTools = $this->wire()->files;
|
||||
$files = array();
|
||||
$dir = dirname($zipFile) . '/';
|
||||
$tmpDir = $dir . '.zip_tmp/';
|
||||
|
||||
try {
|
||||
$files = $this->wire('files')->unzip($zipFile, $tmpDir);
|
||||
$files = $fileTools->unzip($zipFile, $tmpDir);
|
||||
if(!count($files)) {
|
||||
throw new WireException($this->_('No files found in ZIP file'));
|
||||
}
|
||||
} catch(\Exception $e) {
|
||||
$this->error($e->getMessage());
|
||||
$this->wire('files')->rmdir($tmpDir, true);
|
||||
$this->wire('files')->unlink($zipFile);
|
||||
$fileTools->rmdir($tmpDir, true);
|
||||
$fileTools->unlink($zipFile);
|
||||
return $files;
|
||||
}
|
||||
|
||||
$cnt = 0;
|
||||
|
||||
// allow files within ZIP to be up to 10x the size of max upload size
|
||||
$maxFileSize = $this->maxFileSize;
|
||||
$this->setMaxFileSize($maxFileSize * 10);
|
||||
|
||||
foreach($files as $file) {
|
||||
|
||||
$pathname = $tmpDir . $file;
|
||||
|
||||
if(!$this->isValidUpload($file, filesize($pathname), UPLOAD_ERR_OK)) {
|
||||
$this->wire('files')->unlink($pathname, $tmpDir);
|
||||
$fileTools->unlink($pathname, $tmpDir);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -575,7 +613,7 @@ class WireUpload extends Wire {
|
||||
$bakDestination = $dir . $bakName;
|
||||
} while(file_exists($bakDestination));
|
||||
rename($destination, $bakDestination);
|
||||
$this->wire('log')->message("Renamed $destination => $bakDestination");
|
||||
$this->wire()->log->message("Renamed $destination => $bakDestination");
|
||||
$this->overwrittenFiles[$bakDestination] = $destination;
|
||||
|
||||
} else {
|
||||
@@ -589,15 +627,16 @@ class WireUpload extends Wire {
|
||||
$this->completedFilenames[] = basename($destination);
|
||||
$cnt++;
|
||||
} else {
|
||||
$this->wire('files')->unlink($pathname, $tmpDir);
|
||||
$fileTools->unlink($pathname, $tmpDir);
|
||||
}
|
||||
}
|
||||
|
||||
$this->wire('files')->rmdir($tmpDir, true);
|
||||
$this->wire('files')->unlink($zipFile);
|
||||
$this->setMaxFileSize($maxFileSize); // restore original
|
||||
|
||||
if(!$cnt) return false;
|
||||
return true;
|
||||
$fileTools->rmdir($tmpDir, true);
|
||||
$fileTools->unlink($zipFile);
|
||||
|
||||
return $cnt > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -732,7 +771,7 @@ class WireUpload extends Wire {
|
||||
*
|
||||
*/
|
||||
public function setName($name) {
|
||||
$this->name = $this->wire('sanitizer')->fieldName($name);
|
||||
$this->name = $this->wire()->sanitizer->fieldName($name);
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user