Passed
Push — master ( 671ad7...f13b60 )
by Blizzz
15:36 queued 12s
created
lib/private/Config.php 1 patch
Indentation   +267 added lines, -267 removed lines patch added patch discarded remove patch
@@ -45,271 +45,271 @@
 block discarded – undo
45 45
  * configuration file of Nextcloud.
46 46
  */
47 47
 class Config {
48
-	public const ENV_PREFIX = 'NC_';
49
-
50
-	/** @var array Associative array ($key => $value) */
51
-	protected $cache = [];
52
-	/** @var array */
53
-	protected $envCache = [];
54
-	/** @var string */
55
-	protected $configDir;
56
-	/** @var string */
57
-	protected $configFilePath;
58
-	/** @var string */
59
-	protected $configFileName;
60
-	/** @var bool */
61
-	protected $isReadOnly;
62
-
63
-	/**
64
-	 * @param string $configDir Path to the config dir, needs to end with '/'
65
-	 * @param string $fileName (Optional) Name of the config file. Defaults to config.php
66
-	 */
67
-	public function __construct($configDir, $fileName = 'config.php') {
68
-		$this->configDir = $configDir;
69
-		$this->configFilePath = $this->configDir.$fileName;
70
-		$this->configFileName = $fileName;
71
-		$this->readData();
72
-		$this->isReadOnly = $this->getValue('config_is_read_only', false);
73
-	}
74
-
75
-	/**
76
-	 * Lists all available config keys
77
-	 *
78
-	 * Please note that it does not return the values.
79
-	 *
80
-	 * @return array an array of key names
81
-	 */
82
-	public function getKeys() {
83
-		return array_keys($this->cache);
84
-	}
85
-
86
-	/**
87
-	 * Returns a config value
88
-	 *
89
-	 * gets its value from an `NC_` prefixed environment variable
90
-	 * if it doesn't exist from config.php
91
-	 * if this doesn't exist either, it will return the given `$default`
92
-	 *
93
-	 * @param string $key key
94
-	 * @param mixed $default = null default value
95
-	 * @return mixed the value or $default
96
-	 */
97
-	public function getValue($key, $default = null) {
98
-		$envKey = self::ENV_PREFIX . $key;
99
-		if (isset($this->envCache[$envKey])) {
100
-			return $this->envCache[$envKey];
101
-		}
102
-
103
-		if (isset($this->cache[$key])) {
104
-			return $this->cache[$key];
105
-		}
106
-
107
-		return $default;
108
-	}
109
-
110
-	/**
111
-	 * Sets and deletes values and writes the config.php
112
-	 *
113
-	 * @param array $configs Associative array with `key => value` pairs
114
-	 *                       If value is null, the config key will be deleted
115
-	 * @throws HintException
116
-	 */
117
-	public function setValues(array $configs) {
118
-		$needsUpdate = false;
119
-		foreach ($configs as $key => $value) {
120
-			if ($value !== null) {
121
-				$needsUpdate |= $this->set($key, $value);
122
-			} else {
123
-				$needsUpdate |= $this->delete($key);
124
-			}
125
-		}
126
-
127
-		if ($needsUpdate) {
128
-			// Write changes
129
-			$this->writeData();
130
-		}
131
-	}
132
-
133
-	/**
134
-	 * Sets the value and writes it to config.php if required
135
-	 *
136
-	 * @param string $key key
137
-	 * @param mixed $value value
138
-	 * @throws HintException
139
-	 */
140
-	public function setValue($key, $value) {
141
-		if ($this->set($key, $value)) {
142
-			// Write changes
143
-			$this->writeData();
144
-		}
145
-	}
146
-
147
-	/**
148
-	 * This function sets the value
149
-	 *
150
-	 * @param string $key key
151
-	 * @param mixed $value value
152
-	 * @return bool True if the file needs to be updated, false otherwise
153
-	 * @throws HintException
154
-	 */
155
-	protected function set($key, $value) {
156
-		$this->checkReadOnly();
157
-
158
-		if (!isset($this->cache[$key]) || $this->cache[$key] !== $value) {
159
-			// Add change
160
-			$this->cache[$key] = $value;
161
-			return true;
162
-		}
163
-
164
-		return false;
165
-	}
166
-
167
-	/**
168
-	 * Removes a key from the config and removes it from config.php if required
169
-	 *
170
-	 * @param string $key
171
-	 * @throws HintException
172
-	 */
173
-	public function deleteKey($key) {
174
-		if ($this->delete($key)) {
175
-			// Write changes
176
-			$this->writeData();
177
-		}
178
-	}
179
-
180
-	/**
181
-	 * This function removes a key from the config
182
-	 *
183
-	 * @param string $key
184
-	 * @return bool True if the file needs to be updated, false otherwise
185
-	 * @throws HintException
186
-	 */
187
-	protected function delete($key) {
188
-		$this->checkReadOnly();
189
-
190
-		if (isset($this->cache[$key])) {
191
-			// Delete key from cache
192
-			unset($this->cache[$key]);
193
-			return true;
194
-		}
195
-		return false;
196
-	}
197
-
198
-	/**
199
-	 * Loads the config file
200
-	 *
201
-	 * Reads the config file and saves it to the cache
202
-	 *
203
-	 * @throws \Exception If no lock could be acquired or the config file has not been found
204
-	 */
205
-	private function readData() {
206
-		// Default config should always get loaded
207
-		$configFiles = [$this->configFilePath];
208
-
209
-		// Add all files in the config dir ending with the same file name
210
-		$extra = glob($this->configDir.'*.'.$this->configFileName);
211
-		if (is_array($extra)) {
212
-			natsort($extra);
213
-			$configFiles = array_merge($configFiles, $extra);
214
-		}
215
-
216
-		// Include file and merge config
217
-		foreach ($configFiles as $file) {
218
-			$fileExistsAndIsReadable = file_exists($file) && is_readable($file);
219
-			$filePointer = $fileExistsAndIsReadable ? fopen($file, 'r') : false;
220
-			if ($file === $this->configFilePath &&
221
-				$filePointer === false) {
222
-				// Opening the main config might not be possible, e.g. if the wrong
223
-				// permissions are set (likely on a new installation)
224
-				continue;
225
-			}
226
-
227
-			// Try to acquire a file lock
228
-			if (!flock($filePointer, LOCK_SH)) {
229
-				throw new \Exception(sprintf('Could not acquire a shared lock on the config file %s', $file));
230
-			}
231
-
232
-			unset($CONFIG);
233
-			include $file;
234
-			if (!defined('PHPUNIT_RUN') && headers_sent()) {
235
-				// syntax issues in the config file like leading spaces causing PHP to send output
236
-				$errorMessage = sprintf('Config file has leading content, please remove everything before "<?php" in %s', basename($file));
237
-				if (!defined('OC_CONSOLE')) {
238
-					print(\OCP\Util::sanitizeHTML($errorMessage));
239
-				}
240
-				throw new \Exception($errorMessage);
241
-			}
242
-			if (isset($CONFIG) && is_array($CONFIG)) {
243
-				$this->cache = array_merge($this->cache, $CONFIG);
244
-			}
245
-
246
-			// Close the file pointer and release the lock
247
-			flock($filePointer, LOCK_UN);
248
-			fclose($filePointer);
249
-		}
250
-
251
-		$this->envCache = getenv();
252
-	}
253
-
254
-	/**
255
-	 * Writes the config file
256
-	 *
257
-	 * Saves the config to the config file.
258
-	 *
259
-	 * @throws HintException If the config file cannot be written to
260
-	 * @throws \Exception If no file lock can be acquired
261
-	 */
262
-	private function writeData() {
263
-		$this->checkReadOnly();
264
-
265
-		if (!is_file(\OC::$configDir.'/CAN_INSTALL') && !isset($this->cache['version'])) {
266
-			throw new HintException(sprintf('Configuration was not read or initialized correctly, not overwriting %s', $this->configFilePath));
267
-		}
268
-
269
-		// Create a php file ...
270
-		$content = "<?php\n";
271
-		$content .= '$CONFIG = ';
272
-		$content .= var_export($this->cache, true);
273
-		$content .= ";\n";
274
-
275
-		touch($this->configFilePath);
276
-		$filePointer = fopen($this->configFilePath, 'r+');
277
-
278
-		// Prevent others not to read the config
279
-		chmod($this->configFilePath, 0640);
280
-
281
-		// File does not exist, this can happen when doing a fresh install
282
-		if (!is_resource($filePointer)) {
283
-			throw new HintException(
284
-				"Can't write into config directory!",
285
-				'This can usually be fixed by giving the webserver write access to the config directory.');
286
-		}
287
-
288
-		// Try to acquire a file lock
289
-		if (!flock($filePointer, LOCK_EX)) {
290
-			throw new \Exception(sprintf('Could not acquire an exclusive lock on the config file %s', $this->configFilePath));
291
-		}
292
-
293
-		// Write the config and release the lock
294
-		ftruncate($filePointer, 0);
295
-		fwrite($filePointer, $content);
296
-		fflush($filePointer);
297
-		flock($filePointer, LOCK_UN);
298
-		fclose($filePointer);
299
-
300
-		if (function_exists('opcache_invalidate')) {
301
-			@opcache_invalidate($this->configFilePath, true);
302
-		}
303
-	}
304
-
305
-	/**
306
-	 * @throws HintException
307
-	 */
308
-	private function checkReadOnly(): void {
309
-		if ($this->isReadOnly) {
310
-			throw new HintException(
311
-				'Config is set to be read-only via option "config_is_read_only".',
312
-				'Unset "config_is_read_only" to allow changes to the config file.');
313
-		}
314
-	}
48
+    public const ENV_PREFIX = 'NC_';
49
+
50
+    /** @var array Associative array ($key => $value) */
51
+    protected $cache = [];
52
+    /** @var array */
53
+    protected $envCache = [];
54
+    /** @var string */
55
+    protected $configDir;
56
+    /** @var string */
57
+    protected $configFilePath;
58
+    /** @var string */
59
+    protected $configFileName;
60
+    /** @var bool */
61
+    protected $isReadOnly;
62
+
63
+    /**
64
+     * @param string $configDir Path to the config dir, needs to end with '/'
65
+     * @param string $fileName (Optional) Name of the config file. Defaults to config.php
66
+     */
67
+    public function __construct($configDir, $fileName = 'config.php') {
68
+        $this->configDir = $configDir;
69
+        $this->configFilePath = $this->configDir.$fileName;
70
+        $this->configFileName = $fileName;
71
+        $this->readData();
72
+        $this->isReadOnly = $this->getValue('config_is_read_only', false);
73
+    }
74
+
75
+    /**
76
+     * Lists all available config keys
77
+     *
78
+     * Please note that it does not return the values.
79
+     *
80
+     * @return array an array of key names
81
+     */
82
+    public function getKeys() {
83
+        return array_keys($this->cache);
84
+    }
85
+
86
+    /**
87
+     * Returns a config value
88
+     *
89
+     * gets its value from an `NC_` prefixed environment variable
90
+     * if it doesn't exist from config.php
91
+     * if this doesn't exist either, it will return the given `$default`
92
+     *
93
+     * @param string $key key
94
+     * @param mixed $default = null default value
95
+     * @return mixed the value or $default
96
+     */
97
+    public function getValue($key, $default = null) {
98
+        $envKey = self::ENV_PREFIX . $key;
99
+        if (isset($this->envCache[$envKey])) {
100
+            return $this->envCache[$envKey];
101
+        }
102
+
103
+        if (isset($this->cache[$key])) {
104
+            return $this->cache[$key];
105
+        }
106
+
107
+        return $default;
108
+    }
109
+
110
+    /**
111
+     * Sets and deletes values and writes the config.php
112
+     *
113
+     * @param array $configs Associative array with `key => value` pairs
114
+     *                       If value is null, the config key will be deleted
115
+     * @throws HintException
116
+     */
117
+    public function setValues(array $configs) {
118
+        $needsUpdate = false;
119
+        foreach ($configs as $key => $value) {
120
+            if ($value !== null) {
121
+                $needsUpdate |= $this->set($key, $value);
122
+            } else {
123
+                $needsUpdate |= $this->delete($key);
124
+            }
125
+        }
126
+
127
+        if ($needsUpdate) {
128
+            // Write changes
129
+            $this->writeData();
130
+        }
131
+    }
132
+
133
+    /**
134
+     * Sets the value and writes it to config.php if required
135
+     *
136
+     * @param string $key key
137
+     * @param mixed $value value
138
+     * @throws HintException
139
+     */
140
+    public function setValue($key, $value) {
141
+        if ($this->set($key, $value)) {
142
+            // Write changes
143
+            $this->writeData();
144
+        }
145
+    }
146
+
147
+    /**
148
+     * This function sets the value
149
+     *
150
+     * @param string $key key
151
+     * @param mixed $value value
152
+     * @return bool True if the file needs to be updated, false otherwise
153
+     * @throws HintException
154
+     */
155
+    protected function set($key, $value) {
156
+        $this->checkReadOnly();
157
+
158
+        if (!isset($this->cache[$key]) || $this->cache[$key] !== $value) {
159
+            // Add change
160
+            $this->cache[$key] = $value;
161
+            return true;
162
+        }
163
+
164
+        return false;
165
+    }
166
+
167
+    /**
168
+     * Removes a key from the config and removes it from config.php if required
169
+     *
170
+     * @param string $key
171
+     * @throws HintException
172
+     */
173
+    public function deleteKey($key) {
174
+        if ($this->delete($key)) {
175
+            // Write changes
176
+            $this->writeData();
177
+        }
178
+    }
179
+
180
+    /**
181
+     * This function removes a key from the config
182
+     *
183
+     * @param string $key
184
+     * @return bool True if the file needs to be updated, false otherwise
185
+     * @throws HintException
186
+     */
187
+    protected function delete($key) {
188
+        $this->checkReadOnly();
189
+
190
+        if (isset($this->cache[$key])) {
191
+            // Delete key from cache
192
+            unset($this->cache[$key]);
193
+            return true;
194
+        }
195
+        return false;
196
+    }
197
+
198
+    /**
199
+     * Loads the config file
200
+     *
201
+     * Reads the config file and saves it to the cache
202
+     *
203
+     * @throws \Exception If no lock could be acquired or the config file has not been found
204
+     */
205
+    private function readData() {
206
+        // Default config should always get loaded
207
+        $configFiles = [$this->configFilePath];
208
+
209
+        // Add all files in the config dir ending with the same file name
210
+        $extra = glob($this->configDir.'*.'.$this->configFileName);
211
+        if (is_array($extra)) {
212
+            natsort($extra);
213
+            $configFiles = array_merge($configFiles, $extra);
214
+        }
215
+
216
+        // Include file and merge config
217
+        foreach ($configFiles as $file) {
218
+            $fileExistsAndIsReadable = file_exists($file) && is_readable($file);
219
+            $filePointer = $fileExistsAndIsReadable ? fopen($file, 'r') : false;
220
+            if ($file === $this->configFilePath &&
221
+                $filePointer === false) {
222
+                // Opening the main config might not be possible, e.g. if the wrong
223
+                // permissions are set (likely on a new installation)
224
+                continue;
225
+            }
226
+
227
+            // Try to acquire a file lock
228
+            if (!flock($filePointer, LOCK_SH)) {
229
+                throw new \Exception(sprintf('Could not acquire a shared lock on the config file %s', $file));
230
+            }
231
+
232
+            unset($CONFIG);
233
+            include $file;
234
+            if (!defined('PHPUNIT_RUN') && headers_sent()) {
235
+                // syntax issues in the config file like leading spaces causing PHP to send output
236
+                $errorMessage = sprintf('Config file has leading content, please remove everything before "<?php" in %s', basename($file));
237
+                if (!defined('OC_CONSOLE')) {
238
+                    print(\OCP\Util::sanitizeHTML($errorMessage));
239
+                }
240
+                throw new \Exception($errorMessage);
241
+            }
242
+            if (isset($CONFIG) && is_array($CONFIG)) {
243
+                $this->cache = array_merge($this->cache, $CONFIG);
244
+            }
245
+
246
+            // Close the file pointer and release the lock
247
+            flock($filePointer, LOCK_UN);
248
+            fclose($filePointer);
249
+        }
250
+
251
+        $this->envCache = getenv();
252
+    }
253
+
254
+    /**
255
+     * Writes the config file
256
+     *
257
+     * Saves the config to the config file.
258
+     *
259
+     * @throws HintException If the config file cannot be written to
260
+     * @throws \Exception If no file lock can be acquired
261
+     */
262
+    private function writeData() {
263
+        $this->checkReadOnly();
264
+
265
+        if (!is_file(\OC::$configDir.'/CAN_INSTALL') && !isset($this->cache['version'])) {
266
+            throw new HintException(sprintf('Configuration was not read or initialized correctly, not overwriting %s', $this->configFilePath));
267
+        }
268
+
269
+        // Create a php file ...
270
+        $content = "<?php\n";
271
+        $content .= '$CONFIG = ';
272
+        $content .= var_export($this->cache, true);
273
+        $content .= ";\n";
274
+
275
+        touch($this->configFilePath);
276
+        $filePointer = fopen($this->configFilePath, 'r+');
277
+
278
+        // Prevent others not to read the config
279
+        chmod($this->configFilePath, 0640);
280
+
281
+        // File does not exist, this can happen when doing a fresh install
282
+        if (!is_resource($filePointer)) {
283
+            throw new HintException(
284
+                "Can't write into config directory!",
285
+                'This can usually be fixed by giving the webserver write access to the config directory.');
286
+        }
287
+
288
+        // Try to acquire a file lock
289
+        if (!flock($filePointer, LOCK_EX)) {
290
+            throw new \Exception(sprintf('Could not acquire an exclusive lock on the config file %s', $this->configFilePath));
291
+        }
292
+
293
+        // Write the config and release the lock
294
+        ftruncate($filePointer, 0);
295
+        fwrite($filePointer, $content);
296
+        fflush($filePointer);
297
+        flock($filePointer, LOCK_UN);
298
+        fclose($filePointer);
299
+
300
+        if (function_exists('opcache_invalidate')) {
301
+            @opcache_invalidate($this->configFilePath, true);
302
+        }
303
+    }
304
+
305
+    /**
306
+     * @throws HintException
307
+     */
308
+    private function checkReadOnly(): void {
309
+        if ($this->isReadOnly) {
310
+            throw new HintException(
311
+                'Config is set to be read-only via option "config_is_read_only".',
312
+                'Unset "config_is_read_only" to allow changes to the config file.');
313
+        }
314
+    }
315 315
 }
Please login to merge, or discard this patch.