mirror of
https://github.com/silverstripe/silverstripe-framework
synced 2024-10-22 14:05:37 +02:00
126 lines
3.5 KiB
PHP
126 lines
3.5 KiB
PHP
<?php
|
|
|
|
namespace SilverStripe\Assets;
|
|
|
|
use SilverStripe\Core\Object;
|
|
use SilverStripe\View\Parsers\Transliterator;
|
|
|
|
/**
|
|
* Filter certain characters from file name, for nicer (more SEO-friendly) URLs
|
|
* as well as better filesystem compatibility. Can be used for files and folders.
|
|
*
|
|
* Caution: Does not take care of full filename sanitization in regards to directory traversal etc.,
|
|
* please use PHP's built-in basename() for this purpose.
|
|
*
|
|
* The default sanitizer is quite conservative regarding non-ASCII characters,
|
|
* in order to achieve maximum filesystem compatibility.
|
|
* In case your filesystem supports a wider character set,
|
|
* or is case sensitive, you might want to relax these rules
|
|
* via overriding {@link FileNameFilter_DefaultFilter::$default_replacements}.
|
|
*
|
|
* To leave uploaded filenames as they are (being aware of filesystem restrictions),
|
|
* add the following code to your YAML config:
|
|
* <code>
|
|
* FileNameFilter:
|
|
* default_use_transliterator: false
|
|
* default_replacements:
|
|
* </code>
|
|
*
|
|
* See {@link URLSegmentFilter} for a more generic implementation.
|
|
*/
|
|
class FileNameFilter extends Object {
|
|
|
|
/**
|
|
* @config
|
|
* @var Boolean
|
|
*/
|
|
private static $default_use_transliterator = true;
|
|
|
|
/**
|
|
* @config
|
|
* @var array See {@link setReplacements()}.
|
|
*/
|
|
private static $default_replacements = array(
|
|
'/\s/' => '-', // remove whitespace
|
|
'/_/' => '-', // underscores to dashes
|
|
'/[^A-Za-z0-9+.\-]+/' => '', // remove non-ASCII chars, only allow alphanumeric plus dash and dot
|
|
'/[\-]{2,}/' => '-', // remove duplicate dashes
|
|
'/^[\.\-_]+/' => '', // Remove all leading dots, dashes or underscores
|
|
);
|
|
|
|
/**
|
|
* @var array See {@link setReplacements()}
|
|
*/
|
|
public $replacements = array();
|
|
|
|
/**
|
|
* Depending on the applied replacement rules, this method
|
|
* might result in an empty string. In this case, {@link getDefaultName()}
|
|
* will be used to return a randomly generated file name, while retaining its extension.
|
|
*
|
|
* @param string $name including extension (not path).
|
|
* @return string A filtered filename
|
|
*/
|
|
public function filter($name) {
|
|
$ext = pathinfo($name, PATHINFO_EXTENSION);
|
|
|
|
$transliterator = $this->getTransliterator();
|
|
if($transliterator) $name = $transliterator->toASCII($name);
|
|
foreach($this->getReplacements() as $regex => $replace) {
|
|
$name = preg_replace($regex, $replace, $name);
|
|
}
|
|
|
|
// Safeguard against empty file names
|
|
$nameWithoutExt = pathinfo($name, PATHINFO_FILENAME);
|
|
if(empty($nameWithoutExt)) $name = $this->getDefaultName() . '.' . $ext;
|
|
|
|
return $name;
|
|
}
|
|
|
|
/**
|
|
* Take care not to add replacements which might invalidate the file structure,
|
|
* e.g. removing dots will remove file extension information.
|
|
*
|
|
* @param array $r Map of find/replace used for preg_replace().
|
|
*/
|
|
public function setReplacements($r) {
|
|
$this->replacements = $r;
|
|
}
|
|
|
|
/**
|
|
* @return array
|
|
*/
|
|
public function getReplacements() {
|
|
return ($this->replacements) ? $this->replacements : (array)$this->config()->default_replacements;
|
|
}
|
|
|
|
/**
|
|
* @var Transliterator
|
|
*/
|
|
protected $transliterator;
|
|
|
|
/**
|
|
* @return Transliterator
|
|
*/
|
|
public function getTransliterator() {
|
|
if($this->transliterator === null && $this->config()->default_use_transliterator) {
|
|
$this->transliterator = Transliterator::create();
|
|
}
|
|
return $this->transliterator;
|
|
}
|
|
|
|
/**
|
|
* @param Transliterator $t
|
|
*/
|
|
public function setTransliterator($t) {
|
|
$this->transliterator = $t;
|
|
}
|
|
|
|
/**
|
|
* @return String File name without extension
|
|
*/
|
|
public function getDefaultName() {
|
|
return (string)uniqid();
|
|
}
|
|
}
|