1
0
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:
Ryan Cramer
2023-01-20 09:21:29 -05:00
parent a435e9291c
commit df81fdfd0b

View File

@@ -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;
}