diff options
| author | 2025-04-07 08:47:42 +0200 | |
|---|---|---|
| committer | 2025-04-07 08:47:42 +0200 | |
| commit | 0c33d2713957eaf6cc0222150df7ebbcb53beaed (patch) | |
| tree | a9a011c370e2d8ecf3c3290dfb1afd86c9cea0bc /lib | |
| parent | d3d9acca9f905fc03d6151f6ad75567256310831 (diff) | |
Secure serving of user files from extensions (#7495)
* Secure serving of user files from extensions
fix https://github.com/FreshRSS/FreshRSS/issues/4930
* More fixes
* Typo
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/Minz/Extension.php | 35 | ||||
| -rw-r--r-- | lib/core-extensions/UserCSS/extension.php | 2 | ||||
| -rw-r--r-- | lib/core-extensions/UserCSS/metadata.json | 2 | ||||
| -rw-r--r-- | lib/core-extensions/UserJS/extension.php | 2 | ||||
| -rw-r--r-- | lib/core-extensions/UserJS/metadata.json | 2 |
5 files changed, 29 insertions, 14 deletions
diff --git a/lib/Minz/Extension.php b/lib/Minz/Extension.php index d03db8bde..3129c2e1e 100644 --- a/lib/Minz/Extension.php +++ b/lib/Minz/Extension.php @@ -178,12 +178,26 @@ abstract class Minz_Extension { } /** Return whether a user-specific, extension-specific, file exists */ - final protected function hasFile(string $filename): bool { + final public function hasFile(string $filename): bool { + if ($filename === '' || str_contains($filename, '..')) { + return false; + } return file_exists($this->getExtensionUserPath() . '/' . $filename); } - /** Return the user-specific, extension-specific, file content, or null if it does not exist */ - final protected function getFile(string $filename): ?string { + /** Return the motification time of the user-specific, extension-specific, file or null if it does not exist */ + final public function mtimeFile(string $filename): ?int { + if (!$this->hasFile($filename)) { + return null; + } + return @filemtime($this->getExtensionUserPath() . '/' . $filename) ?: null; + } + + /** Return the user-specific, extension-specific, file content or null if it does not exist */ + final public function getFile(string $filename): ?string { + if (!$this->hasFile($filename)) { + return null; + } $content = @file_get_contents($this->getExtensionUserPath() . '/' . $filename); return is_string($content) ? $content : null; } @@ -192,26 +206,27 @@ abstract class Minz_Extension { * Return the url for a given file. * * @param string $filename name of the file to serve. - * @param 'css'|'js'|'svg' $type the type (js or css or svg) of the file to serve. + * @param '' $type MIME type of the file to serve. Deprecated: always use the file extension. * @param bool $isStatic indicates if the file is a static file or a user file. Default is static. * @return string url corresponding to the file. */ - final public function getFileUrl(string $filename, string $type, bool $isStatic = true): string { + final public function getFileUrl(string $filename, string $type = '', bool $isStatic = true): string { if ($isStatic) { $dir = basename($this->path); $file_name_url = urlencode("{$dir}/static/{$filename}"); $mtime = @filemtime("{$this->path}/static/{$filename}"); + return Minz_Url::display("/ext.php?f={$file_name_url}&{$mtime}", 'php'); } else { $username = Minz_User::name(); if ($username == null) { return ''; } - $path = $this->getExtensionUserPath() . "/{$filename}"; - $file_name_url = urlencode("{$username}/extensions/{$this->getEntrypoint()}/{$filename}"); - $mtime = @filemtime($path); + return Minz_Url::display(['c' => 'extension', 'a' => 'serve', 'params' => [ + 'x' => $this->getName(), + 'f' => $filename, + 'm' => $this->mtimeFile($filename), // cache-busting + ]]); } - - return Minz_Url::display("/ext.php?f={$file_name_url}&t={$type}&{$mtime}", 'php'); } /** diff --git a/lib/core-extensions/UserCSS/extension.php b/lib/core-extensions/UserCSS/extension.php index c0622b145..2a1fa2a6e 100644 --- a/lib/core-extensions/UserCSS/extension.php +++ b/lib/core-extensions/UserCSS/extension.php @@ -11,7 +11,7 @@ final class UserCSSExtension extends Minz_Extension { $this->registerTranslates(); if ($this->hasFile(self::FILENAME)) { - Minz_View::appendStyle($this->getFileUrl(self::FILENAME, 'css', false)); + Minz_View::appendStyle($this->getFileUrl(self::FILENAME, isStatic: false)); } } diff --git a/lib/core-extensions/UserCSS/metadata.json b/lib/core-extensions/UserCSS/metadata.json index 2de79af8c..d8a4225e2 100644 --- a/lib/core-extensions/UserCSS/metadata.json +++ b/lib/core-extensions/UserCSS/metadata.json @@ -2,7 +2,7 @@ "name": "User CSS", "author": "hkcomori, Marien Fressinaud", "description": "Give possibility to overwrite the CSS with a user-specific rules.", - "version": "1.0.0", + "version": "1.1.0", "entrypoint": "UserCSS", "type": "user" } diff --git a/lib/core-extensions/UserJS/extension.php b/lib/core-extensions/UserJS/extension.php index 3b860029a..db27b9ebd 100644 --- a/lib/core-extensions/UserJS/extension.php +++ b/lib/core-extensions/UserJS/extension.php @@ -11,7 +11,7 @@ final class UserJSExtension extends Minz_Extension { $this->registerTranslates(); if ($this->hasFile(self::FILENAME)) { - Minz_View::appendScript($this->getFileUrl(self::FILENAME, 'js', false)); + Minz_View::appendScript($this->getFileUrl(self::FILENAME, isStatic: false)); } } diff --git a/lib/core-extensions/UserJS/metadata.json b/lib/core-extensions/UserJS/metadata.json index d38958801..9096d753d 100644 --- a/lib/core-extensions/UserJS/metadata.json +++ b/lib/core-extensions/UserJS/metadata.json @@ -2,7 +2,7 @@ "name": "User JS", "author": "hkcomori, Frans de Jonge", "description": "Apply user JS.", - "version": "1.0.0", + "version": "1.1.0", "entrypoint": "UserJS", "type": "user" } |
