1
0
mirror of https://github.com/processwire/processwire.git synced 2025-08-12 09:44:38 +02:00

Add new methods to $files API var: fileInPath($file, $path); unixDirName($dir); unixFileName($file); filePutContents($file, $contents);

This commit is contained in:
Ryan Cramer
2018-09-26 09:40:16 -04:00
parent e5900e7567
commit bf8baf36dd

View File

@@ -5,7 +5,7 @@
*
* #pw-summary Helpers for working with files and directories.
*
* ProcessWire 3.x, Copyright 2016 by Ryan Cramer
* ProcessWire 3.x, Copyright 2018 by Ryan Cramer
* https://processwire.com
*
* @method bool include($filename, array $vars = array(), array $options = array())
@@ -298,7 +298,7 @@ class WireFileTools extends Wire {
'returnRelative' => false,
);
if(DIRECTORY_SEPARATOR != '/') $path = str_replace(DIRECTORY_SEPARATOR, '/', $path);
$path = $this->unixDirName($path);
if(!is_dir($path) || !is_readable($path)) return array();
$options = array_merge($defaults, $options);
@@ -325,8 +325,7 @@ class WireFileTools extends Wire {
$ext = strtolower($file->getExtension());
if(!empty($options['extensions']) && !in_array($ext, $options['extensions'])) continue;
if(!empty($options['excludeExtensions']) && in_array($ext, $options['excludeExtensions'])) continue;
$filename = $file->getPathname();
if(DIRECTORY_SEPARATOR != '/') $filename = str_replace(DIRECTORY_SEPARATOR, '/', $filename);
$filename = $this->unixFileName($file->getPathname());
// make relative to provided path
if($options['returnRelative']) {
$filename = str_replace($options['_startPath'], '', $filename);
@@ -371,7 +370,7 @@ class WireFileTools extends Wire {
*/
public function unzip($file, $dst) {
$dst = rtrim($dst, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR;
$dst = rtrim($dst, '/' . DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR;
if(!class_exists('\ZipArchive')) throw new WireException("PHP's ZipArchive class does not exist");
if(!is_file($file)) throw new WireException("ZIP file does not exist");
@@ -551,6 +550,25 @@ class WireFileTools extends Wire {
$http->sendFile($filename, $options, $headers);
}
/**
* Create (overwrite or append) a file, put the $contents in it, and adjust permissions
*
* This is the same as PHPs `file_put_contents()` except that its preferable to use this in
* ProcessWire because it adjusts the file permissions configured with `$config->chmodFile`.
*
* @param string $filename Filename to write to
* @param string|mixed $contents Contents to write to file
* @param int $flags Flags to modify behavior:
* - `FILE_APPEND` (constant): Append to file if it already exists .
* - `LOCK_EX` (constant): Acquire exclusive lock to file while writing.
* @return int|bool Number of bytes written or boolean false on fail
*
*/
public function filePutContents($filename, $contents, $flags = 0) {
$result = file_put_contents($filename, $contents, $flags);
if($result !== false) $this->chmod($filename);
return $result;
}
/**
* Given a filename, render it as a ProcessWire template file
@@ -600,7 +618,7 @@ class WireFileTools extends Wire {
);
$options = array_merge($defaults, $options);
if(DIRECTORY_SEPARATOR != '/') $filename = str_replace(DIRECTORY_SEPARATOR, '/', $filename);
$filename = $this->unixFileName($filename);
// add .php extension if filename doesn't already have an extension
if($options['autoExtension'] && !strrpos(basename($filename), '.')) {
@@ -706,7 +724,7 @@ class WireFileTools extends Wire {
if($filename === false) throw new WireException("File does not exist: $_filename");
}
if(DIRECTORY_SEPARATOR != '/') $filename = str_replace(DIRECTORY_SEPARATOR, '/', $filename);
$filename = $this->unixFileName($filename);
if(strpos($filename, '//') !== false) {
throw new WireException("File is not allowed (double-slash): $filename");
@@ -723,8 +741,7 @@ class WireFileTools extends Wire {
// absolute path, make sure it's part of PW's installation
$allowed = false;
foreach($options['allowedPaths'] as $path) {
if(DIRECTORY_SEPARATOR != '/') $path = str_replace(DIRECTORY_SEPARATOR, '/', $path);
if(strpos($filename, $path) === 0) $allowed = true;
if($this->fileInPath($filename, $path)) $allowed = true;
}
if(!$allowed) throw new WireException("File is not in an allowed path: $filename");
}
@@ -780,7 +797,6 @@ class WireFileTools extends Wire {
if($fileIsContents) {
$data = $file;
$file = '';
} else {
$data = file_get_contents($file);
if($data === false) return $namespace;
@@ -980,4 +996,50 @@ class WireFileTools extends Wire {
TemplateFile::popRenderStack();
}
/**
* Convert given directory name to use unix slashes and enforce trailing or no-trailing slash
*
* @param string $dir Directory name to adust (if it needs it)
* @param bool $trailingSlash True to force trailing slash, false to force no trailing slash (default=true)
* @return string Adjusted directory name
*
*/
public function unixDirName($dir, $trailingSlash = true) {
if(DIRECTORY_SEPARATOR != '/' && strpos($dir, DIRECTORY_SEPARATOR) !== false) {
$dir = str_replace(DIRECTORY_SEPARATOR, '/', $dir);
}
$dir = rtrim($dir, '/');
if($trailingSlash) $dir .= '/';
return $dir;
}
/**
* Convert given file name to use unix slashes (if it isnt already)
*
* @param string $file File name to adjust (if it needs it)
* @return string Adjusted file name
*
*/
public function unixFileName($file) {
return $this->unixDirName($file, false);
}
/**
* Is given $file name in given $path name? (aka: is $file a subdirectory somewhere within $path)
*
* This is purely for string comparison purposes, it does not check if file/path actually exists.
* Note that if $file and $path are identical, this method returns false.
*
* @param string $file May be a file or a directory
* @param string $path
* @return bool
*
*/
public function fileInPath($file, $path) {
$file = $this->unixDirName($file); // use of unixDirName rather than unixFileName intentional
$path = $this->unixDirName($path);
if($file === $path || strlen($file) <= strlen($path)) return false;
return strpos($file, $path) === 0;
}
}