File indexing completed on 2024-11-24 05:19:04
0001 <?php 0002 /** 0003 * Image media server - part of Opendesktop.org platform project <https://www.opendesktop.org>. 0004 * 0005 * Copyright (c) 2016 pling GmbH. 0006 * 0007 * This program is free software: you can redistribute it and/or modify 0008 * it under the terms of the GNU Affero General Public License as 0009 * published by the Free Software Foundation, either version 3 of the 0010 * License, or (at your option) any later version. 0011 * 0012 * This program is distributed in the hope that it will be useful, 0013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 0014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 0015 * GNU Affero General Public License for more details. 0016 * 0017 * You should have received a copy of the GNU Affero General Public License 0018 * along with this program. If not, see <https://www.gnu.org/licenses/>. 0019 */ 0020 0021 namespace Ocs\Filter\File; 0022 0023 use Laminas\Filter\AbstractFilter; 0024 0025 class Filename extends AbstractFilter 0026 { 0027 protected $beautify; 0028 0029 public function __construct($options = []) 0030 { 0031 $this->beautify = true; 0032 if (isset($options['beautify'])) { 0033 $this->beautify = $options['beautify']; 0034 } 0035 0036 } 0037 0038 /** 0039 * @inheritDoc 0040 */ 0041 public function filter($value) 0042 { 0043 if (is_string($value)) { 0044 return $this->filter_filename($value); 0045 } 0046 0047 if (false == isset($value['name'])) { 0048 return $value; 0049 } 0050 0051 $value['name'] = $this->filter_filename($value['name']); 0052 0053 return $value; 0054 } 0055 0056 /** 0057 * @param string $filename 0058 * 0059 * @return string 0060 */ 0061 private function filter_filename(string $filename): string 0062 { 0063 // try to prevent filesystem traversal attacks 0064 $filename = basename($filename); 0065 // sanitize filename 0066 $filename = preg_replace('~ 0067 [<>:"/\\|?*]| # file system reserved https://en.wikipedia.org/wiki/Filename#Reserved_characters_and_words 0068 [\x00-\x1F]| # control characters http://msdn.microsoft.com/en-us/library/windows/desktop/aa365247%28v=vs.85%29.aspx 0069 [\x7F\xA0\xAD]| # non-printing characters DEL, NO-BREAK SPACE, SOFT HYPHEN 0070 [#\[\]@!$&\'()+,;=]| # URI reserved https://tools.ietf.org/html/rfc3986#section-2.2 0071 [{}^\~`] # URL unsafe characters https://www.ietf.org/rfc/rfc1738.txt 0072 ~x', '-', $filename); 0073 // avoids ".", ".." or ".hiddenFiles" 0074 $filename = ltrim($filename, '.-'); 0075 // optional beautification 0076 if ($this->beautify) { 0077 $filename = $this->beautify_filename($filename); 0078 } 0079 // maximize filename length to 255 bytes http://serverfault.com/a/9548/44086 0080 $ext = pathinfo($filename, PATHINFO_EXTENSION); 0081 $filename = mb_strcut(pathinfo($filename, PATHINFO_FILENAME), 0, 255 - ($ext ? strlen($ext) + 1 : 0), mb_detect_encoding($filename)) . ($ext ? '.' . $ext : ''); 0082 0083 return $filename; 0084 } 0085 0086 /** 0087 * @param string $filename 0088 * 0089 * @return string 0090 */ 0091 private function beautify_filename($filename): string 0092 { 0093 // reduce consecutive characters 0094 $filename = preg_replace(array(// "file name.zip" becomes "file-name.zip" 0095 '/ +/', 0096 // "file___name.zip" becomes "file-name.zip" 0097 '/_+/', 0098 // "file---name.zip" becomes "file-name.zip" 0099 '/-+/'), '-', $filename); 0100 $filename = preg_replace(array(// "file--.--.-.--name.zip" becomes "file.name.zip" 0101 '/-*\.-*/', 0102 // "file...name..zip" becomes "file.name.zip" 0103 '/\.{2,}/'), '.', $filename); 0104 // lowercase for windows/unix interoperability http://support.microsoft.com/kb/100625 0105 //$filename = mb_strtolower($filename, mb_detect_encoding($filename)); 0106 // ".file-name.-" becomes "file-name" 0107 $filename = trim($filename, '.-'); 0108 0109 return $filename; 0110 } 0111 0112 /** 0113 * @return mixed 0114 */ 0115 public function getBeautify() 0116 { 0117 return $this->beautify; 0118 } 0119 0120 /** 0121 * @param mixed $beautify 0122 */ 0123 public function setBeautify($beautify): void 0124 { 0125 $this->beautify = $beautify; 0126 } 0127 0128 }