Issues (61)

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 (1 issue)

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
 * ownCloud - galleryplus
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\GalleryPlus\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\GalleryPlus\Config
25
 */
26
class ConfigParser {
27
	/** @var ConfigValidator */
28
	private $configValidator;
29
30
	/**
31
	 * Constructor
32
	 */
33 49
	public function __construct() {
34 49
		$this->configValidator = new ConfigValidator();
35 49
	}
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 12
	public function getFeaturesList($folder, $configName) {
46 12
		$featuresList = [];
47 12
		$parsedConfig = $this->parseConfig($folder, $configName);
48 10
		$key = 'features';
49 10
		if (array_key_exists($key, $parsedConfig)) {
50 7
			$featuresList = $this->parseFeatures($parsedConfig[$key]);
51
		}
52
53 10
		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 12
	public function getFolderConfig($folder, $configName, $currentConfig, $completionStatus, $level
70
	) {
71 12
		$parsedConfig = $this->parseConfig($folder, $configName);
72
		list($config, $completionStatus) =
73 12
			$this->buildAlbumConfig($currentConfig, $parsedConfig, $completionStatus, $level);
74
75 12
		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 array|string|\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 24
	private function parseConfig($folder, $configName) {
89
		try {
90
			/** @var File $configFile */
91 24
			$configFile = $folder->get($configName);
92 23
			$rawConfig = $configFile->getContent();
93 23
			$saneConfig = $this->bomFixer($rawConfig);
94 23
			$yaml = new Parser();
95 23
			$parsedConfig = $yaml->parse($saneConfig);
96
97
			//\OC::$server->getLogger()->debug("rawConfig : {path}", ['path' => $rawConfig]);
98
99 22
			return $parsedConfig;
100 2
		} catch (\Exception  $exception) {
101 2
			$errorMessage = "Problem while reading or parsing the configuration file";
102 2
			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 7
	private function parseFeatures($featuresList) {
115 7
		$parsedFeatures = $featuresList;
116 7
		if (!empty($parsedFeatures)) {
117 5
			$parsedFeatures = array_keys($featuresList, 'yes');
118
		}
119
120 7
		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 23
	private function bomFixer($file) {
133 23
		$bom = pack("CCC", 0xef, 0xbb, 0xbf);
134 23
		if (strncmp($file, $bom, 3) === 0) {
135 3
			$file = substr($file, 3);
136
		}
137
138 23
		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 12
	private function buildAlbumConfig($currentConfig, $parsedConfig, $completionStatus, $level) {
153 12
		foreach ($completionStatus as $key => $complete) {
154 12
			if (!$this->isConfigItemComplete($key, $parsedConfig, $complete)) {
155 12
				$parsedConfigItem = $parsedConfig[$key];
156 12
				if ($this->isConfigUsable($key, $parsedConfigItem, $level)) {
157
					list($configItem, $itemComplete) =
158 9
						$this->addConfigItem($key, $parsedConfigItem, $level);
159 9
					$currentConfig = array_merge($currentConfig, $configItem);
160 12
					$completionStatus[$key] = $itemComplete;
161
				}
162
			}
163
		}
164
165 12
		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 12
	private function isConfigItemComplete($key, $parsedConfig, $complete) {
178 12
		return !(!$complete
179 12
				 && array_key_exists($key, $parsedConfig)
180 12
				 && !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 12
	private function isConfigUsable($key, $parsedConfigItem, $level) {
199 12
		$inherit = $this->isConfigInheritable($parsedConfigItem);
200
201 12
		$usable = $level === 0 || $inherit;
202
203 12
		$safe = $this->configValidator->isConfigSafe($key, $parsedConfigItem);
204
205 12
		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>
216
	 */
217 9
	private function addConfigItem($key, $parsedConfigItem, $level) {
218 9
		if ($key === 'sorting' && !array_key_exists('type', $parsedConfigItem)) {
219
220 1
			return [[], false];
221
		} else {
222 8
			$parsedConfigItem['level'] = $level;
223 8
			$configItem = [$key => $parsedConfigItem];
224 8
			$itemComplete = true;
225
226 8
			return [$configItem, $itemComplete];
227
		}
228
	}
229
230
	/**
231
	 * Determines if we can use a configuration sub-section found in parent folders
232
	 *
233
	 * @param array $parsedConfigItem the configuration for a sub-section
234
	 *
235
	 * @return bool
236
	 */
237 12
	private function isConfigInheritable($parsedConfigItem) {
238 12
		$inherit = false;
239 12
		if (array_key_exists('inherit', $parsedConfigItem)) {
240 8
			$inherit = $parsedConfigItem['inherit'];
241
		}
242
243 12
		if ($inherit === 'yes') {
244 7
			$inherit = true;
245
		}
246
247 12
		return $inherit;
248
	}
249
250
}
251