format: Sanitize format name in the format factory

RSS-Bridge currently sanitizes the format name only for the display
action, which can cause problems if other actions depend on formats
as well.

It is therefore better to do sanitization in the factory class for
formats. Additionally, formats should not require a perfect match,
so 'Atom' and 'aToM' make no difference. This will also allow users
to define formats in their own style (i.e. only lowercase via CLI).

References #1001
This commit is contained in:
logmanoriginal 2019-06-18 18:32:56 +02:00
parent 55e1703741
commit 1ada9c26f8
2 changed files with 52 additions and 7 deletions

View file

@ -18,12 +18,6 @@ class DisplayAction extends ActionAbstract {
$format = $this->userData['format'] $format = $this->userData['format']
or returnClientError('You must specify a format!'); or returnClientError('You must specify a format!');
// DEPRECATED: 'nameFormat' scheme is replaced by 'name' in format parameter values
// this is to keep compatibility until futher complete removal
if(($pos = strpos($format, 'Format')) === (strlen($format) - strlen('Format'))) {
$format = substr($format, 0, $pos);
}
// whitelist control // whitelist control
if(!Bridge::isWhitelisted($bridge)) { if(!Bridge::isWhitelisted($bridge)) {
throw new \Exception('This bridge is not whitelisted', 401); throw new \Exception('This bridge is not whitelisted', 401);

View file

@ -68,7 +68,7 @@ class Format {
throw new \InvalidArgumentException('Format name invalid!'); throw new \InvalidArgumentException('Format name invalid!');
} }
$name = $name . 'Format'; $name = self::sanitizeFormatName($name) . 'Format';
$pathFormat = self::getWorkingDir() . $name . '.php'; $pathFormat = self::getWorkingDir() . $name . '.php';
if(!file_exists($pathFormat)) { if(!file_exists($pathFormat)) {
@ -163,4 +163,55 @@ class Format {
return $formatNames; return $formatNames;
} }
/**
* Returns the sanitized format name.
*
* The format name can be specified in various ways:
* * The PHP file name (i.e. `AtomFormat.php`)
* * The PHP file name without file extension (i.e. `AtomFormat`)
* * The format name (i.e. `Atom`)
*
* Casing is ignored (i.e. `ATOM` and `atom` are the same).
*
* A format file matching the given format name must exist in the working
* directory!
*
* @param string $name The format name
* @return string|null The sanitized format name if the provided name is
* valid, null otherwise.
*/
protected static function sanitizeFormatName($name) {
if(is_string($name)) {
// Trim trailing '.php' if exists
if(preg_match('/(.+)(?:\.php)/', $name, $matches)) {
$name = $matches[1];
}
// Trim trailing 'Format' if exists
if(preg_match('/(.+)(?:Format)/i', $name, $matches)) {
$name = $matches[1];
}
// Improve performance for correctly written format names
if(in_array($name, self::getFormatNames())) {
$index = array_search($name, self::getFormatNames());
return self::getFormatNames()[$index];
}
// The name is valid if a corresponding format file is found on disk
if(in_array(strtolower($name), array_map('strtolower', self::getFormatNames()))) {
$index = array_search(strtolower($name), array_map('strtolower', self::getFormatNames()));
return self::getFormatNames()[$index];
}
Debug::log('Invalid format name: "' . $name . '"!');
}
return null; // Bad parameter
}
} }