Issues (108)

Security Analysis    not enabled

This project does not seem to handle request data directly as such no vulnerable execution paths were found.

  Cross-Site Scripting
Cross-Site Scripting enables an attacker to inject code into the response of a web-request that is viewed by other users. It can for example be used to bypass access controls, or even to take over other users' accounts.
  File Exposure
File Exposure allows an attacker to gain access to local files that he should not be able to access. These files can for example include database credentials, or other configuration files.
  File Manipulation
File Manipulation enables an attacker to write custom data to files. This potentially leads to injection of arbitrary code on the server.
  Object Injection
Object Injection enables an attacker to inject an object into PHP code, and can lead to arbitrary code execution, file exposure, or file manipulation attacks.
  Code Injection
Code Injection enables an attacker to execute arbitrary code on the server.
  Response Splitting
Response Splitting can be used to send arbitrary responses.
  File Inclusion
File Inclusion enables an attacker to inject custom files into PHP's file loading mechanism, either explicitly passed to include, or for example via PHP's auto-loading mechanism.
  Command Injection
Command Injection enables an attacker to inject a shell command that is execute with the privileges of the web-server. This can be used to expose sensitive data, or gain access of your server.
  SQL Injection
SQL Injection enables an attacker to execute arbitrary SQL code on your database server gaining access to user data, or manipulating user data.
  XPath Injection
XPath Injection enables an attacker to modify the parts of XML document that are read. If that XML document is for example used for authentication, this can lead to further vulnerabilities similar to SQL Injection.
  LDAP Injection
LDAP Injection enables an attacker to inject LDAP statements potentially granting permission to run unauthorized queries, or modify content inside the LDAP tree.
  Header Injection
  Other Vulnerability
This category comprises other attack vectors such as manipulating the PHP runtime, loading custom extensions, freezing the runtime, or similar.
  Regex Injection
Regex Injection enables an attacker to execute arbitrary code in your PHP process.
  XML Injection
XML Injection enables an attacker to read files on your local filesystem including configuration files, or can be abused to freeze your web-server process.
  Variable Injection
Variable Injection enables an attacker to overwrite program variables with custom data, and can lead to further vulnerabilities.
Unfortunately, the security analysis is currently not available for your project. If you are a non-commercial open-source project, please contact support to gain access.

config/configparser.php (2 issues)

Upgrade to new PHP Analysis Engine

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
Should the return type not be null|\Symfony\Component\...|string|array|\stdClass? Also, consider making the array more specific, something like array<String>, or String[].

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[] or array<String>.

Loading history...
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
Should the return type not be array<array|boolean>?

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.

Loading history...
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