This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | /** |
||
3 | * Gallery |
||
4 | * |
||
5 | * This file is licensed under the Affero General Public License version 3 or |
||
6 | * later. See the COPYING file. |
||
7 | * |
||
8 | * @author Olivier Paroz <[email protected]> |
||
9 | * |
||
10 | * @copyright Olivier Paroz 2016 |
||
11 | */ |
||
12 | |||
13 | namespace OCA\Gallery\Config; |
||
14 | |||
15 | use Symfony\Component\Yaml\Parser; |
||
16 | use Symfony\Component\Yaml\Exception\ParseException; |
||
17 | |||
18 | use OCP\Files\Folder; |
||
19 | use OCP\Files\File; |
||
20 | |||
21 | /** |
||
22 | * Parses configuration files |
||
23 | * |
||
24 | * @package OCA\Gallery\Config |
||
25 | */ |
||
26 | class ConfigParser { |
||
27 | /** @var ConfigValidator */ |
||
28 | private $configValidator; |
||
29 | |||
30 | /** |
||
31 | * Constructor |
||
32 | */ |
||
33 | public function __construct() { |
||
34 | $this->configValidator = new ConfigValidator(); |
||
35 | } |
||
36 | |||
37 | /** |
||
38 | * Returns a parsed global configuration if one was found in the root folder |
||
39 | * |
||
40 | * @param Folder $folder the current folder |
||
41 | * @param string $configName name of the configuration file |
||
42 | * |
||
43 | * @return null|array |
||
44 | */ |
||
45 | public function getFeaturesList($folder, $configName) { |
||
46 | $featuresList = []; |
||
47 | $parsedConfig = $this->parseConfig($folder, $configName); |
||
48 | $key = 'features'; |
||
49 | if (\array_key_exists($key, $parsedConfig)) { |
||
50 | $featuresList = $this->parseFeatures($parsedConfig[$key]); |
||
51 | } |
||
52 | |||
53 | return $featuresList; |
||
54 | } |
||
55 | |||
56 | /** |
||
57 | * Returns a parsed configuration if one was found in the current folder |
||
58 | * |
||
59 | * @param Folder $folder the current folder |
||
60 | * @param string $configName name of the configuration file |
||
61 | * @param array $currentConfig the configuration collected so far |
||
62 | * @param array <string,bool> $completionStatus determines if we already have all we need for a |
||
63 | * config sub-section |
||
64 | * @param int $level the starting level is 0 and we add 1 each time we visit a parent folder |
||
65 | * |
||
66 | * @return array <null|array,array<string,bool>> |
||
67 | * @throws ConfigException |
||
68 | */ |
||
69 | public function getFolderConfig($folder, $configName, $currentConfig, $completionStatus, $level |
||
70 | ) { |
||
71 | $parsedConfig = $this->parseConfig($folder, $configName); |
||
72 | list($config, $completionStatus) = |
||
73 | $this->buildAlbumConfig($currentConfig, $parsedConfig, $completionStatus, $level); |
||
74 | |||
75 | return [$config, $completionStatus]; |
||
76 | } |
||
77 | |||
78 | /** |
||
79 | * Returns a parsed configuration |
||
80 | * |
||
81 | * @param Folder $folder the current folder |
||
82 | * @param string $configName |
||
83 | * |
||
84 | * @return array |
||
0 ignored issues
–
show
|
|||
85 | * |
||
86 | * @throws ConfigException |
||
87 | */ |
||
88 | private function parseConfig($folder, $configName) { |
||
89 | try { |
||
90 | /** @var File $configFile */ |
||
91 | $configFile = $folder->get($configName); |
||
92 | $rawConfig = $configFile->getContent(); |
||
93 | $saneConfig = $this->bomFixer($rawConfig); |
||
94 | $yaml = new Parser(); |
||
95 | $parsedConfig = $yaml->parse($saneConfig); |
||
96 | |||
97 | //\OC::$server->getLogger()->debug("rawConfig : {path}", ['path' => $rawConfig]); |
||
98 | |||
99 | return $parsedConfig; |
||
100 | } catch (\Exception $exception) { |
||
101 | $errorMessage = "Problem while reading or parsing the configuration file"; |
||
102 | throw new ConfigException($errorMessage); |
||
103 | } |
||
104 | } |
||
105 | |||
106 | /** |
||
107 | * Returns only the features which have been enabled |
||
108 | * |
||
109 | * @param array <string,string> $featuresList the list of features collected from the |
||
110 | * configuration file |
||
111 | * |
||
112 | * @return array |
||
113 | */ |
||
114 | private function parseFeatures($featuresList) { |
||
115 | $parsedFeatures = $featuresList; |
||
116 | if (!empty($parsedFeatures)) { |
||
117 | $parsedFeatures = \array_keys($featuresList, 'yes'); |
||
118 | } |
||
119 | |||
120 | return $parsedFeatures; |
||
121 | } |
||
122 | |||
123 | /** |
||
124 | * Removes the BOM from a file |
||
125 | * |
||
126 | * http://us.php.net/manual/en/function.pack.php#104151 |
||
127 | * |
||
128 | * @param string $file |
||
129 | * |
||
130 | * @return string |
||
131 | */ |
||
132 | private function bomFixer($file) { |
||
133 | $bom = \pack("CCC", 0xef, 0xbb, 0xbf); |
||
134 | if (\strncmp($file, $bom, 3) === 0) { |
||
135 | $file = \substr($file, 3); |
||
136 | } |
||
137 | |||
138 | return $file; |
||
139 | } |
||
140 | |||
141 | /** |
||
142 | * Returns either the local config or one merged with a config containing sorting information |
||
143 | * |
||
144 | * @param array $currentConfig the configuration collected so far |
||
145 | * @param array $parsedConfig the configuration collected in the current folder |
||
146 | * @param array <string,bool> $completionStatus determines if we already have all we need for a |
||
147 | * config sub-section |
||
148 | * @param int $level the starting level is 0 and we add 1 each time we visit a parent folder |
||
149 | * |
||
150 | * @return array <null|array,array<string,bool>> |
||
151 | */ |
||
152 | private function buildAlbumConfig($currentConfig, $parsedConfig, $completionStatus, $level) { |
||
153 | foreach ($completionStatus as $key => $complete) { |
||
154 | if (!$this->isConfigItemComplete($key, $parsedConfig, $complete)) { |
||
155 | $parsedConfigItem = $parsedConfig[$key]; |
||
156 | if ($this->isConfigUsable($key, $parsedConfigItem, $level)) { |
||
157 | list($configItem, $itemComplete) = |
||
158 | $this->addConfigItem($key, $parsedConfigItem, $level); |
||
159 | $currentConfig = \array_merge($currentConfig, $configItem); |
||
160 | $completionStatus[$key] = $itemComplete; |
||
161 | } |
||
162 | } |
||
163 | } |
||
164 | |||
165 | return [$currentConfig, $completionStatus]; |
||
166 | } |
||
167 | |||
168 | /** |
||
169 | * Determines if we already have everything we need for this configuration sub-section |
||
170 | * |
||
171 | * @param string $key the configuration sub-section identifier |
||
172 | * @param array $parsedConfig the configuration for that sub-section |
||
173 | * @param bool $complete |
||
174 | * |
||
175 | * @return bool |
||
176 | */ |
||
177 | private function isConfigItemComplete($key, $parsedConfig, $complete) { |
||
178 | return !(!$complete |
||
179 | && \array_key_exists($key, $parsedConfig) |
||
180 | && !empty($parsedConfig[$key])); |
||
181 | } |
||
182 | |||
183 | /** |
||
184 | * Determines if we can use this configuration sub-section |
||
185 | * |
||
186 | * It's possible in two cases: |
||
187 | * * the configuration was collected from the currently opened folder |
||
188 | * * the configuration was collected in a parent folder and is inheritable |
||
189 | * |
||
190 | * We also need to make sure that the values contained in the configuration are safe for web use |
||
191 | * |
||
192 | * @param string $key the configuration sub-section identifier |
||
193 | * @param array $parsedConfigItem the configuration for a sub-section |
||
194 | * @param int $level the starting level is 0 and we add 1 each time we visit a parent folder |
||
195 | * |
||
196 | * @return bool |
||
197 | */ |
||
198 | private function isConfigUsable($key, $parsedConfigItem, $level) { |
||
199 | $inherit = $this->isConfigInheritable($parsedConfigItem); |
||
200 | |||
201 | $usable = $level === 0 || $inherit; |
||
202 | |||
203 | $safe = $this->configValidator->isConfigSafe($key, $parsedConfigItem); |
||
204 | |||
205 | return $usable && $safe; |
||
206 | } |
||
207 | |||
208 | /** |
||
209 | * Adds a config sub-section to the global config |
||
210 | * |
||
211 | * @param string $key the configuration sub-section identifier |
||
212 | * @param array $parsedConfigItem the configuration for a sub-section |
||
213 | * @param int $level the starting level is 0 and we add 1 each time we visit a parent folder |
||
214 | * |
||
215 | * @return array<null|array<string,string>,bool> |
||
0 ignored issues
–
show
|
|||
216 | */ |
||
217 | private function addConfigItem($key, $parsedConfigItem, $level) { |
||
218 | if ($key === 'sorting' && !\array_key_exists('type', $parsedConfigItem)) { |
||
219 | return [[], false]; |
||
220 | } else { |
||
221 | $parsedConfigItem['level'] = $level; |
||
222 | $configItem = [$key => $parsedConfigItem]; |
||
223 | $itemComplete = true; |
||
224 | |||
225 | return [$configItem, $itemComplete]; |
||
226 | } |
||
227 | } |
||
228 | |||
229 | /** |
||
230 | * Determines if we can use a configuration sub-section found in parent folders |
||
231 | * |
||
232 | * @param array $parsedConfigItem the configuration for a sub-section |
||
233 | * |
||
234 | * @return bool |
||
235 | */ |
||
236 | private function isConfigInheritable($parsedConfigItem) { |
||
237 | $inherit = false; |
||
238 | if (\array_key_exists('inherit', $parsedConfigItem)) { |
||
239 | $inherit = $parsedConfigItem['inherit']; |
||
240 | } |
||
241 | |||
242 | if ($inherit === 'yes') { |
||
243 | $inherit = true; |
||
244 | } |
||
245 | |||
246 | return $inherit; |
||
247 | } |
||
248 | } |
||
249 |
This check compares the return type specified in the
@return
annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.If the return type contains the type array, this check recommends the use of a more specific type like
String[]
orarray<String>
.