Completed
Pull Request — master (#6788)
by Markus
14:10
created
apps/theming/lib/ThemingDefaults.php 1 patch
Indentation   +334 added lines, -334 removed lines patch added patch discarded remove patch
@@ -33,338 +33,338 @@
 block discarded – undo
33 33
 
34 34
 class ThemingDefaults extends \OC_Defaults {
35 35
 
36
-	/** @var IConfig */
37
-	private $config;
38
-	/** @var IL10N */
39
-	private $l;
40
-	/** @var IURLGenerator */
41
-	private $urlGenerator;
42
-	/** @var IAppData */
43
-	private $appData;
44
-	/** @var ICacheFactory */
45
-	private $cacheFactory;
46
-	/** @var Util */
47
-	private $util;
48
-	/** @var IAppManager */
49
-	private $appManager;
50
-	/** @var string */
51
-	private $name;
52
-	/** @var string */
53
-	private $title;
54
-	/** @var string */
55
-	private $entity;
56
-	/** @var string */
57
-	private $url;
58
-	/** @var string */
59
-	private $slogan;
60
-	/** @var string */
61
-	private $color;
62
-
63
-	/** @var string */
64
-	private $iTunesAppId;
65
-	/** @var string */
66
-	private $iOSClientUrl;
67
-	/** @var string */
68
-	private $AndroidClientUrl;
69
-
70
-	/**
71
-	 * ThemingDefaults constructor.
72
-	 *
73
-	 * @param IConfig $config
74
-	 * @param IL10N $l
75
-	 * @param IURLGenerator $urlGenerator
76
-	 * @param \OC_Defaults $defaults
77
-	 * @param IAppData $appData
78
-	 * @param ICacheFactory $cacheFactory
79
-	 * @param Util $util
80
-	 * @param IAppManager $appManager
81
-	 */
82
-	public function __construct(IConfig $config,
83
-								IL10N $l,
84
-								IURLGenerator $urlGenerator,
85
-								IAppData $appData,
86
-								ICacheFactory $cacheFactory,
87
-								Util $util,
88
-								IAppManager $appManager
89
-	) {
90
-		parent::__construct();
91
-		$this->config = $config;
92
-		$this->l = $l;
93
-		$this->urlGenerator = $urlGenerator;
94
-		$this->appData = $appData;
95
-		$this->cacheFactory = $cacheFactory;
96
-		$this->util = $util;
97
-		$this->appManager = $appManager;
98
-
99
-		$this->name = parent::getName();
100
-		$this->title = parent::getTitle();
101
-		$this->entity = parent::getEntity();
102
-		$this->url = parent::getBaseUrl();
103
-		$this->slogan = parent::getSlogan();
104
-		$this->color = parent::getColorPrimary();
105
-		$this->iTunesAppId = parent::getiTunesAppId();
106
-		$this->iOSClientUrl = parent::getiOSClientUrl();
107
-		$this->AndroidClientUrl = parent::getAndroidClientUrl();
108
-	}
109
-
110
-	public function getName() {
111
-		return strip_tags($this->config->getAppValue('theming', 'name', $this->name));
112
-	}
113
-
114
-	public function getHTMLName() {
115
-		return $this->config->getAppValue('theming', 'name', $this->name);
116
-	}
117
-
118
-	public function getTitle() {
119
-		return strip_tags($this->config->getAppValue('theming', 'name', $this->title));
120
-	}
121
-
122
-	public function getEntity() {
123
-		return strip_tags($this->config->getAppValue('theming', 'name', $this->entity));
124
-	}
125
-
126
-	public function getBaseUrl() {
127
-		return $this->config->getAppValue('theming', 'url', $this->url);
128
-	}
129
-
130
-	public function getSlogan() {
131
-		return \OCP\Util::sanitizeHTML($this->config->getAppValue('theming', 'slogan', $this->slogan));
132
-	}
133
-
134
-	public function getShortFooter() {
135
-		$slogan = $this->getSlogan();
136
-		$footer = '<a href="'. $this->getBaseUrl() . '" target="_blank"' .
137
-			' rel="noreferrer noopener">' .$this->getEntity() . '</a>'.
138
-			($slogan !== '' ? ' – ' . $slogan : '');
139
-
140
-		return $footer;
141
-	}
142
-
143
-	/**
144
-	 * Color that is used for the header as well as for mail headers
145
-	 *
146
-	 * @return string
147
-	 */
148
-	public function getColorPrimary() {
149
-		return $this->config->getAppValue('theming', 'color', $this->color);
150
-	}
151
-
152
-	/**
153
-	 * Themed logo url
154
-	 *
155
-	 * @param bool $useSvg Whether to point to the SVG image or a fallback
156
-	 * @return string
157
-	 */
158
-	public function getLogo($useSvg = true) {
159
-		$logo = $this->config->getAppValue('theming', 'logoMime', false);
160
-
161
-		$logoExists = true;
162
-		try {
163
-			$this->appData->getFolder('images')->getFile('logo');
164
-		} catch (\Exception $e) {
165
-			$logoExists = false;
166
-		}
167
-
168
-		$cacheBusterCounter = $this->config->getAppValue('theming', 'cachebuster', '0');
169
-
170
-		if(!$logo || !$logoExists) {
171
-			if($useSvg) {
172
-				$logo = $this->urlGenerator->imagePath('core', 'logo.svg');
173
-			} else {
174
-				$logo = $this->urlGenerator->imagePath('core', 'logo.png');
175
-			}
176
-			return $logo . '?v=' . $cacheBusterCounter;
177
-		}
178
-
179
-		return $this->urlGenerator->linkToRoute('theming.Theming.getLogo') . '?v=' . $cacheBusterCounter;
180
-	}
181
-
182
-	/**
183
-	 * Themed background image url
184
-	 *
185
-	 * @return string
186
-	 */
187
-	public function getBackground() {
188
-		$backgroundLogo = $this->config->getAppValue('theming', 'backgroundMime',false);
189
-
190
-		$backgroundExists = true;
191
-		try {
192
-			$this->appData->getFolder('images')->getFile('background');
193
-		} catch (\Exception $e) {
194
-			$backgroundExists = false;
195
-		}
196
-
197
-		$cacheBusterCounter = $this->config->getAppValue('theming', 'cachebuster', '0');
198
-
199
-		if(!$backgroundLogo || !$backgroundExists) {
200
-			return $this->urlGenerator->imagePath('core','background.png') . '?v=' . $cacheBusterCounter;
201
-		}
202
-
203
-		return $this->urlGenerator->linkToRoute('theming.Theming.getLoginBackground') . '?v=' . $cacheBusterCounter;
204
-	}
205
-
206
-	/**
207
-	 * @return string
208
-	 */
209
-	public function getiTunesAppId() {
210
-		return $this->config->getAppValue('theming', 'iTunesAppId', $this->iTunesAppId);
211
-	}
212
-
213
-	/**
214
-	 * @return string
215
-	 */
216
-	public function getiOSClientUrl() {
217
-		return $this->config->getAppValue('theming', 'iOSClientUrl', $this->iOSClientUrl);
218
-	}
219
-
220
-	/**
221
-	 * @return string
222
-	 */
223
-	public function getAndroidClientUrl() {
224
-		return $this->config->getAppValue('theming', 'AndroidClientUrl', $this->AndroidClientUrl);
225
-	}
226
-
227
-
228
-	/**
229
-	 * @return array scss variables to overwrite
230
-	 */
231
-	public function getScssVariables() {
232
-		$cache = $this->cacheFactory->create('theming');
233
-		if ($value = $cache->get('getScssVariables')) {
234
-			return $value;
235
-		}
236
-
237
-		$variables = [
238
-			'theming-cachebuster' => "'" . $this->config->getAppValue('theming', 'cachebuster', '0') . "'",
239
-			'theming-logo-mime' => "'" . $this->config->getAppValue('theming', 'logoMime', '') . "'",
240
-			'theming-background-mime' => "'" . $this->config->getAppValue('theming', 'backgroundMime', '') . "'"
241
-		];
242
-
243
-		$variables['image-logo'] = "'".$this->urlGenerator->getAbsoluteURL($this->getLogo())."'";
244
-		$variables['image-login-background'] = "'".$this->urlGenerator->getAbsoluteURL($this->getBackground())."'";
245
-		$variables['image-login-plain'] = 'false';
246
-
247
-		if ($this->config->getAppValue('theming', 'color', null) !== null) {
248
-			if ($this->util->invertTextColor($this->getColorPrimary())) {
249
-				$colorPrimaryText = '#000000';
250
-			} else {
251
-				$colorPrimaryText = '#ffffff';
252
-			}
253
-			$variables['color-primary'] = $this->getColorPrimary();
254
-			$variables['color-primary-text'] = $colorPrimaryText;
255
-			$variables['color-primary-element'] = $this->util->elementColor($this->getColorPrimary());
256
-		}
257
-
258
-		if ($this->config->getAppValue('theming', 'backgroundMime', null) === 'backgroundColor') {
259
-			$variables['image-login-plain'] = 'true';
260
-		}
261
-		$cache->set('getScssVariables', $variables);
262
-		return $variables;
263
-	}
264
-
265
-	/**
266
-	 * Check if the image should be replaced by the theming app
267
-	 * and return the new image location then
268
-	 *
269
-	 * @param string $app name of the app
270
-	 * @param string $image filename of the image
271
-	 * @return bool|string false if image should not replaced, otherwise the location of the image
272
-	 */
273
-	public function replaceImagePath($app, $image) {
274
-		if($app==='') {
275
-			$app = 'core';
276
-		}
277
-		$cacheBusterValue = $this->config->getAppValue('theming', 'cachebuster', '0');
278
-
279
-		if ($image === 'favicon.ico' && $this->shouldReplaceIcons()) {
280
-			return $this->urlGenerator->linkToRoute('theming.Icon.getFavicon', ['app' => $app]) . '?v=' . $cacheBusterValue;
281
-		}
282
-		if ($image === 'favicon-touch.png' && $this->shouldReplaceIcons()) {
283
-			return $this->urlGenerator->linkToRoute('theming.Icon.getTouchIcon', ['app' => $app]) . '?v=' . $cacheBusterValue;
284
-		}
285
-		if ($image === 'manifest.json') {
286
-			try {
287
-				$appPath = $this->appManager->getAppPath($app);
288
-				if (file_exists($appPath . '/img/manifest.json')) {
289
-					return false;
290
-				}
291
-			} catch (AppPathNotFoundException $e) {}
292
-			return $this->urlGenerator->linkToRoute('theming.Theming.getManifest') . '?v=' . $cacheBusterValue;
293
-		}
294
-		return false;
295
-	}
296
-
297
-	/**
298
-	 * Check if Imagemagick is enabled and if SVG is supported
299
-	 * otherwise we can't render custom icons
300
-	 *
301
-	 * @return bool
302
-	 */
303
-	public function shouldReplaceIcons() {
304
-		$cache = $this->cacheFactory->create('theming');
305
-		if($value = $cache->get('shouldReplaceIcons')) {
306
-			return (bool)$value;
307
-		}
308
-		$value = false;
309
-		if(extension_loaded('imagick')) {
310
-			$checkImagick = new \Imagick();
311
-			if (count($checkImagick->queryFormats('SVG')) >= 1) {
312
-				$value = true;
313
-			}
314
-			$checkImagick->clear();
315
-		}
316
-		$cache->set('shouldReplaceIcons', $value);
317
-		return $value;
318
-	}
319
-
320
-	/**
321
-	 * Increases the cache buster key
322
-	 */
323
-	private function increaseCacheBuster() {
324
-		$cacheBusterKey = $this->config->getAppValue('theming', 'cachebuster', '0');
325
-		$this->config->setAppValue('theming', 'cachebuster', (int)$cacheBusterKey+1);
326
-		$this->cacheFactory->create('theming')->clear('getScssVariables');
327
-	}
328
-
329
-	/**
330
-	 * Update setting in the database
331
-	 *
332
-	 * @param string $setting
333
-	 * @param string $value
334
-	 */
335
-	public function set($setting, $value) {
336
-		$this->config->setAppValue('theming', $setting, $value);
337
-		$this->increaseCacheBuster();
338
-	}
339
-
340
-	/**
341
-	 * Revert settings to the default value
342
-	 *
343
-	 * @param string $setting setting which should be reverted
344
-	 * @return string default value
345
-	 */
346
-	public function undo($setting) {
347
-		$this->config->deleteAppValue('theming', $setting);
348
-		$this->increaseCacheBuster();
349
-
350
-		switch ($setting) {
351
-			case 'name':
352
-				$returnValue = $this->getEntity();
353
-				break;
354
-			case 'url':
355
-				$returnValue = $this->getBaseUrl();
356
-				break;
357
-			case 'slogan':
358
-				$returnValue = $this->getSlogan();
359
-				break;
360
-			case 'color':
361
-				$returnValue = $this->getColorPrimary();
362
-				break;
363
-			default:
364
-				$returnValue = '';
365
-				break;
366
-		}
367
-
368
-		return $returnValue;
369
-	}
36
+    /** @var IConfig */
37
+    private $config;
38
+    /** @var IL10N */
39
+    private $l;
40
+    /** @var IURLGenerator */
41
+    private $urlGenerator;
42
+    /** @var IAppData */
43
+    private $appData;
44
+    /** @var ICacheFactory */
45
+    private $cacheFactory;
46
+    /** @var Util */
47
+    private $util;
48
+    /** @var IAppManager */
49
+    private $appManager;
50
+    /** @var string */
51
+    private $name;
52
+    /** @var string */
53
+    private $title;
54
+    /** @var string */
55
+    private $entity;
56
+    /** @var string */
57
+    private $url;
58
+    /** @var string */
59
+    private $slogan;
60
+    /** @var string */
61
+    private $color;
62
+
63
+    /** @var string */
64
+    private $iTunesAppId;
65
+    /** @var string */
66
+    private $iOSClientUrl;
67
+    /** @var string */
68
+    private $AndroidClientUrl;
69
+
70
+    /**
71
+     * ThemingDefaults constructor.
72
+     *
73
+     * @param IConfig $config
74
+     * @param IL10N $l
75
+     * @param IURLGenerator $urlGenerator
76
+     * @param \OC_Defaults $defaults
77
+     * @param IAppData $appData
78
+     * @param ICacheFactory $cacheFactory
79
+     * @param Util $util
80
+     * @param IAppManager $appManager
81
+     */
82
+    public function __construct(IConfig $config,
83
+                                IL10N $l,
84
+                                IURLGenerator $urlGenerator,
85
+                                IAppData $appData,
86
+                                ICacheFactory $cacheFactory,
87
+                                Util $util,
88
+                                IAppManager $appManager
89
+    ) {
90
+        parent::__construct();
91
+        $this->config = $config;
92
+        $this->l = $l;
93
+        $this->urlGenerator = $urlGenerator;
94
+        $this->appData = $appData;
95
+        $this->cacheFactory = $cacheFactory;
96
+        $this->util = $util;
97
+        $this->appManager = $appManager;
98
+
99
+        $this->name = parent::getName();
100
+        $this->title = parent::getTitle();
101
+        $this->entity = parent::getEntity();
102
+        $this->url = parent::getBaseUrl();
103
+        $this->slogan = parent::getSlogan();
104
+        $this->color = parent::getColorPrimary();
105
+        $this->iTunesAppId = parent::getiTunesAppId();
106
+        $this->iOSClientUrl = parent::getiOSClientUrl();
107
+        $this->AndroidClientUrl = parent::getAndroidClientUrl();
108
+    }
109
+
110
+    public function getName() {
111
+        return strip_tags($this->config->getAppValue('theming', 'name', $this->name));
112
+    }
113
+
114
+    public function getHTMLName() {
115
+        return $this->config->getAppValue('theming', 'name', $this->name);
116
+    }
117
+
118
+    public function getTitle() {
119
+        return strip_tags($this->config->getAppValue('theming', 'name', $this->title));
120
+    }
121
+
122
+    public function getEntity() {
123
+        return strip_tags($this->config->getAppValue('theming', 'name', $this->entity));
124
+    }
125
+
126
+    public function getBaseUrl() {
127
+        return $this->config->getAppValue('theming', 'url', $this->url);
128
+    }
129
+
130
+    public function getSlogan() {
131
+        return \OCP\Util::sanitizeHTML($this->config->getAppValue('theming', 'slogan', $this->slogan));
132
+    }
133
+
134
+    public function getShortFooter() {
135
+        $slogan = $this->getSlogan();
136
+        $footer = '<a href="'. $this->getBaseUrl() . '" target="_blank"' .
137
+            ' rel="noreferrer noopener">' .$this->getEntity() . '</a>'.
138
+            ($slogan !== '' ? ' – ' . $slogan : '');
139
+
140
+        return $footer;
141
+    }
142
+
143
+    /**
144
+     * Color that is used for the header as well as for mail headers
145
+     *
146
+     * @return string
147
+     */
148
+    public function getColorPrimary() {
149
+        return $this->config->getAppValue('theming', 'color', $this->color);
150
+    }
151
+
152
+    /**
153
+     * Themed logo url
154
+     *
155
+     * @param bool $useSvg Whether to point to the SVG image or a fallback
156
+     * @return string
157
+     */
158
+    public function getLogo($useSvg = true) {
159
+        $logo = $this->config->getAppValue('theming', 'logoMime', false);
160
+
161
+        $logoExists = true;
162
+        try {
163
+            $this->appData->getFolder('images')->getFile('logo');
164
+        } catch (\Exception $e) {
165
+            $logoExists = false;
166
+        }
167
+
168
+        $cacheBusterCounter = $this->config->getAppValue('theming', 'cachebuster', '0');
169
+
170
+        if(!$logo || !$logoExists) {
171
+            if($useSvg) {
172
+                $logo = $this->urlGenerator->imagePath('core', 'logo.svg');
173
+            } else {
174
+                $logo = $this->urlGenerator->imagePath('core', 'logo.png');
175
+            }
176
+            return $logo . '?v=' . $cacheBusterCounter;
177
+        }
178
+
179
+        return $this->urlGenerator->linkToRoute('theming.Theming.getLogo') . '?v=' . $cacheBusterCounter;
180
+    }
181
+
182
+    /**
183
+     * Themed background image url
184
+     *
185
+     * @return string
186
+     */
187
+    public function getBackground() {
188
+        $backgroundLogo = $this->config->getAppValue('theming', 'backgroundMime',false);
189
+
190
+        $backgroundExists = true;
191
+        try {
192
+            $this->appData->getFolder('images')->getFile('background');
193
+        } catch (\Exception $e) {
194
+            $backgroundExists = false;
195
+        }
196
+
197
+        $cacheBusterCounter = $this->config->getAppValue('theming', 'cachebuster', '0');
198
+
199
+        if(!$backgroundLogo || !$backgroundExists) {
200
+            return $this->urlGenerator->imagePath('core','background.png') . '?v=' . $cacheBusterCounter;
201
+        }
202
+
203
+        return $this->urlGenerator->linkToRoute('theming.Theming.getLoginBackground') . '?v=' . $cacheBusterCounter;
204
+    }
205
+
206
+    /**
207
+     * @return string
208
+     */
209
+    public function getiTunesAppId() {
210
+        return $this->config->getAppValue('theming', 'iTunesAppId', $this->iTunesAppId);
211
+    }
212
+
213
+    /**
214
+     * @return string
215
+     */
216
+    public function getiOSClientUrl() {
217
+        return $this->config->getAppValue('theming', 'iOSClientUrl', $this->iOSClientUrl);
218
+    }
219
+
220
+    /**
221
+     * @return string
222
+     */
223
+    public function getAndroidClientUrl() {
224
+        return $this->config->getAppValue('theming', 'AndroidClientUrl', $this->AndroidClientUrl);
225
+    }
226
+
227
+
228
+    /**
229
+     * @return array scss variables to overwrite
230
+     */
231
+    public function getScssVariables() {
232
+        $cache = $this->cacheFactory->create('theming');
233
+        if ($value = $cache->get('getScssVariables')) {
234
+            return $value;
235
+        }
236
+
237
+        $variables = [
238
+            'theming-cachebuster' => "'" . $this->config->getAppValue('theming', 'cachebuster', '0') . "'",
239
+            'theming-logo-mime' => "'" . $this->config->getAppValue('theming', 'logoMime', '') . "'",
240
+            'theming-background-mime' => "'" . $this->config->getAppValue('theming', 'backgroundMime', '') . "'"
241
+        ];
242
+
243
+        $variables['image-logo'] = "'".$this->urlGenerator->getAbsoluteURL($this->getLogo())."'";
244
+        $variables['image-login-background'] = "'".$this->urlGenerator->getAbsoluteURL($this->getBackground())."'";
245
+        $variables['image-login-plain'] = 'false';
246
+
247
+        if ($this->config->getAppValue('theming', 'color', null) !== null) {
248
+            if ($this->util->invertTextColor($this->getColorPrimary())) {
249
+                $colorPrimaryText = '#000000';
250
+            } else {
251
+                $colorPrimaryText = '#ffffff';
252
+            }
253
+            $variables['color-primary'] = $this->getColorPrimary();
254
+            $variables['color-primary-text'] = $colorPrimaryText;
255
+            $variables['color-primary-element'] = $this->util->elementColor($this->getColorPrimary());
256
+        }
257
+
258
+        if ($this->config->getAppValue('theming', 'backgroundMime', null) === 'backgroundColor') {
259
+            $variables['image-login-plain'] = 'true';
260
+        }
261
+        $cache->set('getScssVariables', $variables);
262
+        return $variables;
263
+    }
264
+
265
+    /**
266
+     * Check if the image should be replaced by the theming app
267
+     * and return the new image location then
268
+     *
269
+     * @param string $app name of the app
270
+     * @param string $image filename of the image
271
+     * @return bool|string false if image should not replaced, otherwise the location of the image
272
+     */
273
+    public function replaceImagePath($app, $image) {
274
+        if($app==='') {
275
+            $app = 'core';
276
+        }
277
+        $cacheBusterValue = $this->config->getAppValue('theming', 'cachebuster', '0');
278
+
279
+        if ($image === 'favicon.ico' && $this->shouldReplaceIcons()) {
280
+            return $this->urlGenerator->linkToRoute('theming.Icon.getFavicon', ['app' => $app]) . '?v=' . $cacheBusterValue;
281
+        }
282
+        if ($image === 'favicon-touch.png' && $this->shouldReplaceIcons()) {
283
+            return $this->urlGenerator->linkToRoute('theming.Icon.getTouchIcon', ['app' => $app]) . '?v=' . $cacheBusterValue;
284
+        }
285
+        if ($image === 'manifest.json') {
286
+            try {
287
+                $appPath = $this->appManager->getAppPath($app);
288
+                if (file_exists($appPath . '/img/manifest.json')) {
289
+                    return false;
290
+                }
291
+            } catch (AppPathNotFoundException $e) {}
292
+            return $this->urlGenerator->linkToRoute('theming.Theming.getManifest') . '?v=' . $cacheBusterValue;
293
+        }
294
+        return false;
295
+    }
296
+
297
+    /**
298
+     * Check if Imagemagick is enabled and if SVG is supported
299
+     * otherwise we can't render custom icons
300
+     *
301
+     * @return bool
302
+     */
303
+    public function shouldReplaceIcons() {
304
+        $cache = $this->cacheFactory->create('theming');
305
+        if($value = $cache->get('shouldReplaceIcons')) {
306
+            return (bool)$value;
307
+        }
308
+        $value = false;
309
+        if(extension_loaded('imagick')) {
310
+            $checkImagick = new \Imagick();
311
+            if (count($checkImagick->queryFormats('SVG')) >= 1) {
312
+                $value = true;
313
+            }
314
+            $checkImagick->clear();
315
+        }
316
+        $cache->set('shouldReplaceIcons', $value);
317
+        return $value;
318
+    }
319
+
320
+    /**
321
+     * Increases the cache buster key
322
+     */
323
+    private function increaseCacheBuster() {
324
+        $cacheBusterKey = $this->config->getAppValue('theming', 'cachebuster', '0');
325
+        $this->config->setAppValue('theming', 'cachebuster', (int)$cacheBusterKey+1);
326
+        $this->cacheFactory->create('theming')->clear('getScssVariables');
327
+    }
328
+
329
+    /**
330
+     * Update setting in the database
331
+     *
332
+     * @param string $setting
333
+     * @param string $value
334
+     */
335
+    public function set($setting, $value) {
336
+        $this->config->setAppValue('theming', $setting, $value);
337
+        $this->increaseCacheBuster();
338
+    }
339
+
340
+    /**
341
+     * Revert settings to the default value
342
+     *
343
+     * @param string $setting setting which should be reverted
344
+     * @return string default value
345
+     */
346
+    public function undo($setting) {
347
+        $this->config->deleteAppValue('theming', $setting);
348
+        $this->increaseCacheBuster();
349
+
350
+        switch ($setting) {
351
+            case 'name':
352
+                $returnValue = $this->getEntity();
353
+                break;
354
+            case 'url':
355
+                $returnValue = $this->getBaseUrl();
356
+                break;
357
+            case 'slogan':
358
+                $returnValue = $this->getSlogan();
359
+                break;
360
+            case 'color':
361
+                $returnValue = $this->getColorPrimary();
362
+                break;
363
+            default:
364
+                $returnValue = '';
365
+                break;
366
+        }
367
+
368
+        return $returnValue;
369
+    }
370 370
 }
Please login to merge, or discard this patch.
core/templates/update.use-cli.php 1 patch
Indentation   +5 added lines, -5 removed lines patch added patch discarded remove patch
@@ -3,12 +3,12 @@
 block discarded – undo
3 3
 		<h2 class="title"><?php p($l->t('Update needed')) ?></h2>
4 4
 		<div class="infogroup">
5 5
 			<?php if ($_['tooBig']) {
6
-				p($l->t('Please use the command line updater because you have a big instance with more than 50 users.'));
7
-			} else {
8
-				p($l->t('Please use the command line updater because automatic updating is disabled in the config.php.'));
9
-			} ?><br><br>
6
+                p($l->t('Please use the command line updater because you have a big instance with more than 50 users.'));
7
+            } else {
8
+                p($l->t('Please use the command line updater because automatic updating is disabled in the config.php.'));
9
+            } ?><br><br>
10 10
 			<?php
11
-			print_unescaped($l->t('For help, see the  <a target="_blank" rel="noreferrer noopener" href="%s">documentation</a>.', [link_to_docs('admin-cli-upgrade')])); ?><br><br>
11
+            print_unescaped($l->t('For help, see the  <a target="_blank" rel="noreferrer noopener" href="%s">documentation</a>.', [link_to_docs('admin-cli-upgrade')])); ?><br><br>
12 12
 		</div>
13 13
 	</div>
14 14
 
Please login to merge, or discard this patch.
core/templates/installation.php 1 patch
Indentation   +6 added lines, -6 removed lines patch added patch discarded remove patch
@@ -1,7 +1,7 @@  discard block
 block discarded – undo
1 1
 <?php
2 2
 script('core', [
3
-	'jquery-showpassword',
4
-	'installation'
3
+    'jquery-showpassword',
4
+    'installation'
5 5
 ]);
6 6
 ?>
7 7
 <input type='hidden' id='hasMySQL' value='<?php p($_['hasMySQL']) ?>'>
@@ -30,9 +30,9 @@  discard block
 block discarded – undo
30 30
 		<legend><strong><?php p($l->t('Security warning'));?></strong></legend>
31 31
 		<p><?php p($l->t('Your data directory and files are probably accessible from the internet because the .htaccess file does not work.'));?><br>
32 32
 		<?php print_unescaped($l->t(
33
-			'For information how to properly configure your server, please see the <a href="%s" target="_blank" rel="noreferrer noopener">documentation</a>.',
34
-			link_to_docs('admin-install')
35
-		)); ?></p>
33
+            'For information how to properly configure your server, please see the <a href="%s" target="_blank" rel="noreferrer noopener">documentation</a>.',
34
+            link_to_docs('admin-install')
35
+        )); ?></p>
36 36
 	</fieldset>
37 37
 	<?php endif; ?>
38 38
 	<fieldset id="adminaccount">
@@ -76,7 +76,7 @@  discard block
 block discarded – undo
76 76
 	<?php if(!$_['dbIsSet'] OR count($_['errors']) > 0): ?>
77 77
 	<fieldset id='databaseBackend'>
78 78
 		<?php if($_['hasMySQL'] or $_['hasPostgreSQL'] or $_['hasOracle'])
79
-			$hasOtherDB = true; else $hasOtherDB =false; //other than SQLite ?>
79
+            $hasOtherDB = true; else $hasOtherDB =false; //other than SQLite ?>
80 80
 		<legend><?php p($l->t( 'Configure the database' )); ?></legend>
81 81
 		<div id="selectDbType">
82 82
 		<?php foreach($_['databases'] as $type => $label): ?>
Please login to merge, or discard this patch.
core/templates/layout.noscript.warning.php 1 patch
Indentation   +4 added lines, -4 removed lines patch added patch discarded remove patch
@@ -2,10 +2,10 @@
 block discarded – undo
2 2
 	<div id="nojavascript">
3 3
 		<div>
4 4
 			<?php print_unescaped(str_replace(
5
-					['{linkstart}', '{linkend}'],
6
-					['<a href="https://www.enable-javascript.com/" target="_blank" rel="noreferrer noopener">', '</a>'],
7
-					$l->t('This application requires JavaScript for correct operation. Please {linkstart}enable JavaScript{linkend} and reload the page.')
8
-				)); ?>
5
+                    ['{linkstart}', '{linkend}'],
6
+                    ['<a href="https://www.enable-javascript.com/" target="_blank" rel="noreferrer noopener">', '</a>'],
7
+                    $l->t('This application requires JavaScript for correct operation. Please {linkstart}enable JavaScript{linkend} and reload the page.')
8
+                )); ?>
9 9
 		</div>
10 10
 	</div>
11 11
 </noscript>
Please login to merge, or discard this patch.
settings/templates/settings.development.notice.php 1 patch
Indentation   +51 added lines, -51 removed lines patch added patch discarded remove patch
@@ -1,64 +1,64 @@
 block discarded – undo
1 1
 	<p>
2 2
 		<?php print_unescaped(str_replace(
3
-			[
4
-				'{communityopen}',
5
-				'{githubopen}',
6
-				'{licenseopen}',
7
-				'{linkclose}',
8
-			],
9
-			[
10
-				'<a href="https://nextcloud.com/contribute" target="_blank" rel="noreferrer noopener">',
11
-				'<a href="https://github.com/nextcloud" target="_blank" rel="noreferrer noopener">',
12
-				'<a href="https://www.gnu.org/licenses/agpl-3.0.html" target="_blank" rel="noreferrer noopener">',
13
-				'</a>',
14
-			],
15
-			$l->t('Developed by the {communityopen}Nextcloud community{linkclose}, the {githubopen}source code{linkclose} is licensed under the {licenseopen}AGPL{linkclose}.')
16
-		)); ?>
3
+            [
4
+                '{communityopen}',
5
+                '{githubopen}',
6
+                '{licenseopen}',
7
+                '{linkclose}',
8
+            ],
9
+            [
10
+                '<a href="https://nextcloud.com/contribute" target="_blank" rel="noreferrer noopener">',
11
+                '<a href="https://github.com/nextcloud" target="_blank" rel="noreferrer noopener">',
12
+                '<a href="https://www.gnu.org/licenses/agpl-3.0.html" target="_blank" rel="noreferrer noopener">',
13
+                '</a>',
14
+            ],
15
+            $l->t('Developed by the {communityopen}Nextcloud community{linkclose}, the {githubopen}source code{linkclose} is licensed under the {licenseopen}AGPL{linkclose}.')
16
+        )); ?>
17 17
 	</p>
18 18
 
19 19
 	<p class="social-button">
20 20
 		<?php print_unescaped(str_replace(
21
-			[
22
-				'{googleimage}',
23
-				'{facebookimage}',
24
-				'{twitterimage}',
25
-				'{rssimage}',
26
-				'{mailimage}',
27
-				'{googleopen}',
28
-				'{facebookopen}',
29
-				'{twitteropen}',
30
-				'{rssopen}',
31
-				'{newsletteropen}',
32
-				'{linkclose}',
33
-				'{googletext}',
34
-				'{facebooktext}',
35
-				'{twittertext}',
36
-				'{rsstext}',
37
-				'{mailtext}',
38
-			],
39
-			[
40
-				image_path('core', 'googleplus.svg'),
41
-				image_path('core', 'facebook.svg'),
42
-				image_path('core', 'twitter.svg'),
43
-				image_path('core', 'rss.svg'),
44
-				image_path('core', 'mail.svg'),
45
-				'<a target="_blank" rel="noreferrer noopener noopener" href="https://plus.google.com/+Nextcloud">',
46
-				'<a target="_blank" rel="noreferrer noopener noopener" href="https://www.facebook.com/Nextclouders/">',
47
-				'<a target="_blank" rel="noreferrer noopener noopener" href="https://twitter.com/nextclouders">',
48
-				'<a target="_blank" rel="noreferrer noopener noopener" href="https://nextcloud.com/news/">',
49
-				'<a target="_blank" rel="noreferrer noopener noopener" href="https://newsletter.nextcloud.com/?p=subscribe&amp;id=1">',
50
-				'</a>',
51
-				$l->t('Follow us on Google+'),
52
-				$l->t('Like our Facebook page'),
53
-				$l->t('Follow us on Twitter'),
54
-				$l->t('Check out our blog'),
55
-				$l->t('Subscribe to our newsletter'),
21
+            [
22
+                '{googleimage}',
23
+                '{facebookimage}',
24
+                '{twitterimage}',
25
+                '{rssimage}',
26
+                '{mailimage}',
27
+                '{googleopen}',
28
+                '{facebookopen}',
29
+                '{twitteropen}',
30
+                '{rssopen}',
31
+                '{newsletteropen}',
32
+                '{linkclose}',
33
+                '{googletext}',
34
+                '{facebooktext}',
35
+                '{twittertext}',
36
+                '{rsstext}',
37
+                '{mailtext}',
38
+            ],
39
+            [
40
+                image_path('core', 'googleplus.svg'),
41
+                image_path('core', 'facebook.svg'),
42
+                image_path('core', 'twitter.svg'),
43
+                image_path('core', 'rss.svg'),
44
+                image_path('core', 'mail.svg'),
45
+                '<a target="_blank" rel="noreferrer noopener noopener" href="https://plus.google.com/+Nextcloud">',
46
+                '<a target="_blank" rel="noreferrer noopener noopener" href="https://www.facebook.com/Nextclouders/">',
47
+                '<a target="_blank" rel="noreferrer noopener noopener" href="https://twitter.com/nextclouders">',
48
+                '<a target="_blank" rel="noreferrer noopener noopener" href="https://nextcloud.com/news/">',
49
+                '<a target="_blank" rel="noreferrer noopener noopener" href="https://newsletter.nextcloud.com/?p=subscribe&amp;id=1">',
50
+                '</a>',
51
+                $l->t('Follow us on Google+'),
52
+                $l->t('Like our Facebook page'),
53
+                $l->t('Follow us on Twitter'),
54
+                $l->t('Check out our blog'),
55
+                $l->t('Subscribe to our newsletter'),
56 56
 
57
-			],
57
+            ],
58 58
 '{googleopen}<img width="50" src="{googleimage}" title="{googletext}" alt="{googletext}">{linkclose}
59 59
 {facebookopen}<img width="50" src="{facebookimage}" title="{facebooktext}" alt="{facebooktext}">{linkclose}
60 60
 {twitteropen}<img width="50" src="{twitterimage}" title="{twittertext}" alt="{twittertext}">{linkclose}
61 61
 {rssopen}<img class="img-circle" width="50" src="{rssimage}" title="{rsstext}" alt="{rsstext}">{linkclose}
62 62
 {newsletteropen}<img width="50" src="{mailimage}" title="{mailtext}" alt="{mailtext}">{linkclose}'
63
-		)); ?>
63
+        )); ?>
64 64
 	</p>
Please login to merge, or discard this patch.
settings/templates/settings/admin/server.php 1 patch
Indentation   +68 added lines, -68 removed lines patch added patch discarded remove patch
@@ -31,101 +31,101 @@  discard block
 block discarded – undo
31 31
 	<p class="settings-hint"><?php p($l->t('It\'s important for the security and performance of your instance that everything is configured correctly. To help you with that we are doing some automatic checks. Please see the Tips & Tricks section and the documentation for more information.'));?></p>
32 32
 	<ul>
33 33
 		<?php
34
-		// is php setup properly to query system environment variables like getenv('PATH')
35
-		if ($_['getenvServerNotWorking']) {
36
-			?>
34
+        // is php setup properly to query system environment variables like getenv('PATH')
35
+        if ($_['getenvServerNotWorking']) {
36
+            ?>
37 37
 			<li>
38 38
 				<?php p($l->t('PHP does not seem to be setup properly to query system environment variables. The test with getenv("PATH") only returns an empty response.')); ?><br>
39 39
 				<?php print_unescaped($l->t('Please check the <a target="_blank" rel="noreferrer noopener" href="%s">installation documentation ↗</a> for PHP configuration notes and the PHP configuration of your server, especially when using php-fpm.', link_to_docs('admin-php-fpm'))); ?>
40 40
 			</li>
41 41
 			<?php
42
-		}
42
+        }
43 43
 
44
-		// is read only config enabled
45
-		if ($_['readOnlyConfigEnabled']) {
46
-			?>
44
+        // is read only config enabled
45
+        if ($_['readOnlyConfigEnabled']) {
46
+            ?>
47 47
 			<li>
48 48
 				<?php p($l->t('The Read-Only config has been enabled. This prevents setting some configurations via the web-interface. Furthermore, the file needs to be made writable manually for every update.')); ?>
49 49
 			</li>
50 50
 			<?php
51
-		}
51
+        }
52 52
 
53
-		// Are doc blocks accessible?
54
-		if (!$_['isAnnotationsWorking']) {
55
-			?>
53
+        // Are doc blocks accessible?
54
+        if (!$_['isAnnotationsWorking']) {
55
+            ?>
56 56
 			<li>
57 57
 				<?php p($l->t('PHP is apparently set up to strip inline doc blocks. This will make several core apps inaccessible.')); ?><br>
58 58
 				<?php p($l->t('This is probably caused by a cache/accelerator such as Zend OPcache or eAccelerator.')); ?>
59 59
 			</li>
60 60
 			<?php
61
-		}
61
+        }
62 62
 
63
-		// Is the Transaction isolation level READ_COMMITTED?
64
-		if ($_['invalidTransactionIsolationLevel']) {
65
-			?>
63
+        // Is the Transaction isolation level READ_COMMITTED?
64
+        if ($_['invalidTransactionIsolationLevel']) {
65
+            ?>
66 66
 			<li>
67 67
 				<?php p($l->t('Your database does not run with "READ COMMITTED" transaction isolation level. This can cause problems when multiple actions are executed in parallel.')); ?>
68 68
 			</li>
69 69
 			<?php
70
-		}
70
+        }
71 71
 
72
-		// Warning if memcache is outdated
73
-		foreach ($_['OutdatedCacheWarning'] as $php_module => $data) {
74
-			?>
72
+        // Warning if memcache is outdated
73
+        foreach ($_['OutdatedCacheWarning'] as $php_module => $data) {
74
+            ?>
75 75
 			<li>
76 76
 				<?php p($l->t('%1$s below version %2$s is installed, for stability and performance reasons it is recommended to update to a newer %1$s version.', $data)); ?>
77 77
 			</li>
78 78
 			<?php
79
-		}
79
+        }
80 80
 
81
-		// if module fileinfo available?
82
-		if (!$_['has_fileinfo']) {
83
-			?>
81
+        // if module fileinfo available?
82
+        if (!$_['has_fileinfo']) {
83
+            ?>
84 84
 			<li>
85 85
 				<?php p($l->t('The PHP module \'fileinfo\' is missing. It is strongly recommended to enable this module to get the best results with MIME type detection.')); ?>
86 86
 			</li>
87 87
 			<?php
88
-		}
88
+        }
89 89
 
90
-		// locking configured optimally?
91
-		if ($_['fileLockingType'] === 'none') {
92
-			?>
90
+        // locking configured optimally?
91
+        if ($_['fileLockingType'] === 'none') {
92
+            ?>
93 93
 			<li>
94 94
 				<?php print_unescaped($l->t('Transactional file locking is disabled, this might lead to issues with race conditions. Enable \'filelocking.enabled\' in config.php to avoid these problems. See the <a target="_blank" rel="noreferrer noopener" href="%s">documentation ↗</a> for more information.', link_to_docs('admin-transactional-locking'))); ?>
95 95
 			</li>
96 96
 			<?php
97
-		}
97
+        }
98 98
 
99
-		// is locale working ?
100
-		if (!$_['isLocaleWorking']) {
101
-			?>
99
+        // is locale working ?
100
+        if (!$_['isLocaleWorking']) {
101
+            ?>
102 102
 			<li>
103 103
 				<?php
104
-				$locales = 'en_US.UTF-8/fr_FR.UTF-8/es_ES.UTF-8/de_DE.UTF-8/ru_RU.UTF-8/pt_BR.UTF-8/it_IT.UTF-8/ja_JP.UTF-8/zh_CN.UTF-8';
105
-				p($l->t('System locale can not be set to a one which supports UTF-8.'));
106
-				?>
104
+                $locales = 'en_US.UTF-8/fr_FR.UTF-8/es_ES.UTF-8/de_DE.UTF-8/ru_RU.UTF-8/pt_BR.UTF-8/it_IT.UTF-8/ja_JP.UTF-8/zh_CN.UTF-8';
105
+                p($l->t('System locale can not be set to a one which supports UTF-8.'));
106
+                ?>
107 107
 				<br>
108 108
 				<?php
109
-				p($l->t('This means that there might be problems with certain characters in filenames.'));
110
-				?>
109
+                p($l->t('This means that there might be problems with certain characters in filenames.'));
110
+                ?>
111 111
 				<br>
112 112
 				<?php
113
-				p($l->t('It is strongly proposed to install the required packages on your system to support one of the following locales: %s.', [$locales]));
114
-				?>
113
+                p($l->t('It is strongly proposed to install the required packages on your system to support one of the following locales: %s.', [$locales]));
114
+                ?>
115 115
 			</li>
116 116
 			<?php
117
-		}
117
+        }
118 118
 
119
-		if ($_['suggestedOverwriteCliUrl']) {
120
-			?>
119
+        if ($_['suggestedOverwriteCliUrl']) {
120
+            ?>
121 121
 			<li>
122 122
 				<?php p($l->t('If your installation is not installed at the root of the domain and uses system Cron, there can be issues with the URL generation. To avoid these problems, please set the "overwrite.cli.url" option in your config.php file to the webroot path of your installation (Suggested: "%s")', $_['suggestedOverwriteCliUrl'])); ?>
123 123
 			</li>
124 124
 			<?php
125
-		}
125
+        }
126 126
 
127
-		if ($_['cronErrors']) {
128
-			?>
127
+        if ($_['cronErrors']) {
128
+            ?>
129 129
 			<li>
130 130
 				<?php p($l->t('It was not possible to execute the cron job via CLI. The following technical errors have appeared:')); ?>
131 131
 				<br>
@@ -136,8 +136,8 @@  discard block
 block discarded – undo
136 136
 				</ol>
137 137
 			</li>
138 138
 			<?php
139
-		}
140
-		?>
139
+        }
140
+        ?>
141 141
 	</ul>
142 142
 
143 143
 	<div id="postsetupchecks" data-check-wellknown="<?php if($_['checkForWorkingWellKnownSetup']) { p('true'); } else { p('false'); } ?>">
@@ -158,9 +158,9 @@  discard block
 block discarded – undo
158 158
 	<h2 class="inlineblock"><?php p($l->t('Background jobs'));?></h2>
159 159
 	<p class="cronlog inlineblock">
160 160
 		<?php if ($_['lastcron'] !== false):
161
-			$relative_time = relative_modified_date($_['lastcron']);
162
-			$absolute_time = OC_Util::formatDate($_['lastcron']);
163
-			if (time() - $_['lastcron'] <= 3600): ?>
161
+            $relative_time = relative_modified_date($_['lastcron']);
162
+            $absolute_time = OC_Util::formatDate($_['lastcron']);
163
+            if (time() - $_['lastcron'] <= 3600): ?>
164 164
 				<span class="status success"></span>
165 165
 				<span class="crondate" title="<?php p($absolute_time);?>">
166 166
 				<?php p($l->t("Last job ran %s.", [$relative_time]));?>
@@ -171,10 +171,10 @@  discard block
 block discarded – undo
171 171
 				<?php p($l->t("Last job execution ran %s. Something seems wrong.", [$relative_time]));?>
172 172
 			</span>
173 173
 			<?php endif;
174
-		else: ?>
174
+        else: ?>
175 175
 			<span class="status error"></span>
176 176
 			<?php p($l->t("Background job didn’t run yet!"));
177
-		endif; ?>
177
+        endif; ?>
178 178
 	</p>
179 179
 	<a target="_blank" rel="noreferrer noopener" class="icon-info"
180 180
 	   title="<?php p($l->t('Open documentation'));?>"
@@ -184,38 +184,38 @@  discard block
 block discarded – undo
184 184
 	<p>
185 185
 		<input type="radio" name="mode" value="ajax" class="radio"
186 186
 			   id="backgroundjobs_ajax" <?php if ($_['backgroundjobs_mode'] === "ajax") {
187
-			print_unescaped('checked="checked"');
188
-		} ?>>
187
+            print_unescaped('checked="checked"');
188
+        } ?>>
189 189
 		<label for="backgroundjobs_ajax">AJAX</label><br/>
190 190
 		<em><?php p($l->t("Execute one task with each page loaded")); ?></em>
191 191
 	</p>
192 192
 	<p>
193 193
 		<input type="radio" name="mode" value="webcron" class="radio"
194 194
 			   id="backgroundjobs_webcron" <?php if ($_['backgroundjobs_mode'] === "webcron") {
195
-			print_unescaped('checked="checked"');
196
-		} ?>>
195
+            print_unescaped('checked="checked"');
196
+        } ?>>
197 197
 		<label for="backgroundjobs_webcron">Webcron</label><br/>
198 198
 		<em><?php p($l->t("cron.php is registered at a webcron service to call cron.php every 15 minutes over HTTP.")); ?></em>
199 199
 	</p>
200 200
 	<p>
201 201
 		<input type="radio" name="mode" value="cron" class="radio"
202 202
 			   id="backgroundjobs_cron" <?php if ($_['backgroundjobs_mode'] === "cron") {
203
-			print_unescaped('checked="checked"');
204
-		}
205
-		if (!$_['cli_based_cron_possible']) {
206
-			print_unescaped('disabled');
207
-		}?>>
203
+            print_unescaped('checked="checked"');
204
+        }
205
+        if (!$_['cli_based_cron_possible']) {
206
+            print_unescaped('disabled');
207
+        }?>>
208 208
 		<label for="backgroundjobs_cron">Cron</label><br/>
209 209
 		<em><?php p($l->t("Use system cron service to call the cron.php file every 15 minutes.")); ?>
210 210
 			<?php if($_['cli_based_cron_possible']) {
211
-				p($l->t('The cron.php needs to be executed by the system user "%s".', [$_['cli_based_cron_user']]));
212
-			} else {
213
-				print_unescaped(str_replace(
214
-					['{linkstart}', '{linkend}'],
215
-					['<a href="http://php.net/manual/en/book.posix.php">', ' ↗</a>'],
216
-					$l->t('To run this you need the PHP POSIX extension. See {linkstart}PHP documentation{linkend} for more details.')
217
-				));
218
-		} ?></em>
211
+                p($l->t('The cron.php needs to be executed by the system user "%s".', [$_['cli_based_cron_user']]));
212
+            } else {
213
+                print_unescaped(str_replace(
214
+                    ['{linkstart}', '{linkend}'],
215
+                    ['<a href="http://php.net/manual/en/book.posix.php">', ' ↗</a>'],
216
+                    $l->t('To run this you need the PHP POSIX extension. See {linkstart}PHP documentation{linkend} for more details.')
217
+                ));
218
+        } ?></em>
219 219
 
220 220
 	</p>
221 221
 </div>
Please login to merge, or discard this patch.
lib/private/legacy/defaults.php 1 patch
Indentation   +255 added lines, -255 removed lines patch added patch discarded remove patch
@@ -31,287 +31,287 @@
 block discarded – undo
31 31
  */
32 32
 class OC_Defaults {
33 33
 
34
-	private $theme;
35
-	private $l;
34
+    private $theme;
35
+    private $l;
36 36
 
37
-	private $defaultEntity;
38
-	private $defaultName;
39
-	private $defaultTitle;
40
-	private $defaultBaseUrl;
41
-	private $defaultSyncClientUrl;
42
-	private $defaultiOSClientUrl;
43
-	private $defaultiTunesAppId;
44
-	private $defaultAndroidClientUrl;
45
-	private $defaultDocBaseUrl;
46
-	private $defaultDocVersion;
47
-	private $defaultSlogan;
48
-	private $defaultColorPrimary;
37
+    private $defaultEntity;
38
+    private $defaultName;
39
+    private $defaultTitle;
40
+    private $defaultBaseUrl;
41
+    private $defaultSyncClientUrl;
42
+    private $defaultiOSClientUrl;
43
+    private $defaultiTunesAppId;
44
+    private $defaultAndroidClientUrl;
45
+    private $defaultDocBaseUrl;
46
+    private $defaultDocVersion;
47
+    private $defaultSlogan;
48
+    private $defaultColorPrimary;
49 49
 
50
-	public function __construct() {
51
-		$this->l = \OC::$server->getL10N('lib');
50
+    public function __construct() {
51
+        $this->l = \OC::$server->getL10N('lib');
52 52
 
53
-		$this->defaultEntity = 'Nextcloud'; /* e.g. company name, used for footers and copyright notices */
54
-		$this->defaultName = 'Nextcloud'; /* short name, used when referring to the software */
55
-		$this->defaultTitle = 'Nextcloud'; /* can be a longer name, for titles */
56
-		$this->defaultBaseUrl = 'https://nextcloud.com';
57
-		$this->defaultSyncClientUrl = 'https://nextcloud.com/install/#install-clients';
58
-		$this->defaultiOSClientUrl = 'https://itunes.apple.com/us/app/nextcloud/id1125420102?mt=8';
59
-		$this->defaultiTunesAppId = '1125420102';
60
-		$this->defaultAndroidClientUrl = 'https://play.google.com/store/apps/details?id=com.nextcloud.client';
61
-		$this->defaultDocBaseUrl = 'https://docs.nextcloud.com';
62
-		$this->defaultDocVersion = '12'; // used to generate doc links
63
-		$this->defaultSlogan = $this->l->t('a safe home for all your data');
64
-		$this->defaultColorPrimary = '#0082c9';
53
+        $this->defaultEntity = 'Nextcloud'; /* e.g. company name, used for footers and copyright notices */
54
+        $this->defaultName = 'Nextcloud'; /* short name, used when referring to the software */
55
+        $this->defaultTitle = 'Nextcloud'; /* can be a longer name, for titles */
56
+        $this->defaultBaseUrl = 'https://nextcloud.com';
57
+        $this->defaultSyncClientUrl = 'https://nextcloud.com/install/#install-clients';
58
+        $this->defaultiOSClientUrl = 'https://itunes.apple.com/us/app/nextcloud/id1125420102?mt=8';
59
+        $this->defaultiTunesAppId = '1125420102';
60
+        $this->defaultAndroidClientUrl = 'https://play.google.com/store/apps/details?id=com.nextcloud.client';
61
+        $this->defaultDocBaseUrl = 'https://docs.nextcloud.com';
62
+        $this->defaultDocVersion = '12'; // used to generate doc links
63
+        $this->defaultSlogan = $this->l->t('a safe home for all your data');
64
+        $this->defaultColorPrimary = '#0082c9';
65 65
 
66
-		$themePath = OC::$SERVERROOT . '/themes/' . OC_Util::getTheme() . '/defaults.php';
67
-		if (file_exists($themePath)) {
68
-			// prevent defaults.php from printing output
69
-			ob_start();
70
-			require_once $themePath;
71
-			ob_end_clean();
72
-			if (class_exists('OC_Theme')) {
73
-				$this->theme = new OC_Theme();
74
-			}
75
-		}
76
-	}
66
+        $themePath = OC::$SERVERROOT . '/themes/' . OC_Util::getTheme() . '/defaults.php';
67
+        if (file_exists($themePath)) {
68
+            // prevent defaults.php from printing output
69
+            ob_start();
70
+            require_once $themePath;
71
+            ob_end_clean();
72
+            if (class_exists('OC_Theme')) {
73
+                $this->theme = new OC_Theme();
74
+            }
75
+        }
76
+    }
77 77
 
78
-	/**
79
-	 * @param string $method
80
-	 */
81
-	private function themeExist($method) {
82
-		if (isset($this->theme) && method_exists($this->theme, $method)) {
83
-			return true;
84
-		}
85
-		return false;
86
-	}
78
+    /**
79
+     * @param string $method
80
+     */
81
+    private function themeExist($method) {
82
+        if (isset($this->theme) && method_exists($this->theme, $method)) {
83
+            return true;
84
+        }
85
+        return false;
86
+    }
87 87
 
88
-	/**
89
-	 * Returns the base URL
90
-	 * @return string URL
91
-	 */
92
-	public function getBaseUrl() {
93
-		if ($this->themeExist('getBaseUrl')) {
94
-			return $this->theme->getBaseUrl();
95
-		} else {
96
-			return $this->defaultBaseUrl;
97
-		}
98
-	}
88
+    /**
89
+     * Returns the base URL
90
+     * @return string URL
91
+     */
92
+    public function getBaseUrl() {
93
+        if ($this->themeExist('getBaseUrl')) {
94
+            return $this->theme->getBaseUrl();
95
+        } else {
96
+            return $this->defaultBaseUrl;
97
+        }
98
+    }
99 99
 
100
-	/**
101
-	 * Returns the URL where the sync clients are listed
102
-	 * @return string URL
103
-	 */
104
-	public function getSyncClientUrl() {
105
-		if ($this->themeExist('getSyncClientUrl')) {
106
-			return $this->theme->getSyncClientUrl();
107
-		} else {
108
-			return $this->defaultSyncClientUrl;
109
-		}
110
-	}
100
+    /**
101
+     * Returns the URL where the sync clients are listed
102
+     * @return string URL
103
+     */
104
+    public function getSyncClientUrl() {
105
+        if ($this->themeExist('getSyncClientUrl')) {
106
+            return $this->theme->getSyncClientUrl();
107
+        } else {
108
+            return $this->defaultSyncClientUrl;
109
+        }
110
+    }
111 111
 
112
-	/**
113
-	 * Returns the URL to the App Store for the iOS Client
114
-	 * @return string URL
115
-	 */
116
-	public function getiOSClientUrl() {
117
-		if ($this->themeExist('getiOSClientUrl')) {
118
-			return $this->theme->getiOSClientUrl();
119
-		} else {
120
-			return $this->defaultiOSClientUrl;
121
-		}
122
-	}
112
+    /**
113
+     * Returns the URL to the App Store for the iOS Client
114
+     * @return string URL
115
+     */
116
+    public function getiOSClientUrl() {
117
+        if ($this->themeExist('getiOSClientUrl')) {
118
+            return $this->theme->getiOSClientUrl();
119
+        } else {
120
+            return $this->defaultiOSClientUrl;
121
+        }
122
+    }
123 123
 
124
-	/**
125
-	 * Returns the AppId for the App Store for the iOS Client
126
-	 * @return string AppId
127
-	 */
128
-	public function getiTunesAppId() {
129
-		if ($this->themeExist('getiTunesAppId')) {
130
-			return $this->theme->getiTunesAppId();
131
-		} else {
132
-			return $this->defaultiTunesAppId;
133
-		}
134
-	}
124
+    /**
125
+     * Returns the AppId for the App Store for the iOS Client
126
+     * @return string AppId
127
+     */
128
+    public function getiTunesAppId() {
129
+        if ($this->themeExist('getiTunesAppId')) {
130
+            return $this->theme->getiTunesAppId();
131
+        } else {
132
+            return $this->defaultiTunesAppId;
133
+        }
134
+    }
135 135
 
136
-	/**
137
-	 * Returns the URL to Google Play for the Android Client
138
-	 * @return string URL
139
-	 */
140
-	public function getAndroidClientUrl() {
141
-		if ($this->themeExist('getAndroidClientUrl')) {
142
-			return $this->theme->getAndroidClientUrl();
143
-		} else {
144
-			return $this->defaultAndroidClientUrl;
145
-		}
146
-	}
136
+    /**
137
+     * Returns the URL to Google Play for the Android Client
138
+     * @return string URL
139
+     */
140
+    public function getAndroidClientUrl() {
141
+        if ($this->themeExist('getAndroidClientUrl')) {
142
+            return $this->theme->getAndroidClientUrl();
143
+        } else {
144
+            return $this->defaultAndroidClientUrl;
145
+        }
146
+    }
147 147
 
148
-	/**
149
-	 * Returns the documentation URL
150
-	 * @return string URL
151
-	 */
152
-	public function getDocBaseUrl() {
153
-		if ($this->themeExist('getDocBaseUrl')) {
154
-			return $this->theme->getDocBaseUrl();
155
-		} else {
156
-			return $this->defaultDocBaseUrl;
157
-		}
158
-	}
148
+    /**
149
+     * Returns the documentation URL
150
+     * @return string URL
151
+     */
152
+    public function getDocBaseUrl() {
153
+        if ($this->themeExist('getDocBaseUrl')) {
154
+            return $this->theme->getDocBaseUrl();
155
+        } else {
156
+            return $this->defaultDocBaseUrl;
157
+        }
158
+    }
159 159
 
160
-	/**
161
-	 * Returns the title
162
-	 * @return string title
163
-	 */
164
-	public function getTitle() {
165
-		if ($this->themeExist('getTitle')) {
166
-			return $this->theme->getTitle();
167
-		} else {
168
-			return $this->defaultTitle;
169
-		}
170
-	}
160
+    /**
161
+     * Returns the title
162
+     * @return string title
163
+     */
164
+    public function getTitle() {
165
+        if ($this->themeExist('getTitle')) {
166
+            return $this->theme->getTitle();
167
+        } else {
168
+            return $this->defaultTitle;
169
+        }
170
+    }
171 171
 
172
-	/**
173
-	 * Returns the short name of the software
174
-	 * @return string title
175
-	 */
176
-	public function getName() {
177
-		if ($this->themeExist('getName')) {
178
-			return $this->theme->getName();
179
-		} else {
180
-			return $this->defaultName;
181
-		}
182
-	}
172
+    /**
173
+     * Returns the short name of the software
174
+     * @return string title
175
+     */
176
+    public function getName() {
177
+        if ($this->themeExist('getName')) {
178
+            return $this->theme->getName();
179
+        } else {
180
+            return $this->defaultName;
181
+        }
182
+    }
183 183
 
184
-	/**
185
-	 * Returns the short name of the software containing HTML strings
186
-	 * @return string title
187
-	 */
188
-	public function getHTMLName() {
189
-		if ($this->themeExist('getHTMLName')) {
190
-			return $this->theme->getHTMLName();
191
-		} else {
192
-			return $this->defaultName;
193
-		}
194
-	}
184
+    /**
185
+     * Returns the short name of the software containing HTML strings
186
+     * @return string title
187
+     */
188
+    public function getHTMLName() {
189
+        if ($this->themeExist('getHTMLName')) {
190
+            return $this->theme->getHTMLName();
191
+        } else {
192
+            return $this->defaultName;
193
+        }
194
+    }
195 195
 
196
-	/**
197
-	 * Returns entity (e.g. company name) - used for footer, copyright
198
-	 * @return string entity name
199
-	 */
200
-	public function getEntity() {
201
-		if ($this->themeExist('getEntity')) {
202
-			return $this->theme->getEntity();
203
-		} else {
204
-			return $this->defaultEntity;
205
-		}
206
-	}
196
+    /**
197
+     * Returns entity (e.g. company name) - used for footer, copyright
198
+     * @return string entity name
199
+     */
200
+    public function getEntity() {
201
+        if ($this->themeExist('getEntity')) {
202
+            return $this->theme->getEntity();
203
+        } else {
204
+            return $this->defaultEntity;
205
+        }
206
+    }
207 207
 
208
-	/**
209
-	 * Returns slogan
210
-	 * @return string slogan
211
-	 */
212
-	public function getSlogan() {
213
-		if ($this->themeExist('getSlogan')) {
214
-			return $this->theme->getSlogan();
215
-		} else {
216
-			return $this->defaultSlogan;
217
-		}
218
-	}
208
+    /**
209
+     * Returns slogan
210
+     * @return string slogan
211
+     */
212
+    public function getSlogan() {
213
+        if ($this->themeExist('getSlogan')) {
214
+            return $this->theme->getSlogan();
215
+        } else {
216
+            return $this->defaultSlogan;
217
+        }
218
+    }
219 219
 
220
-	/**
221
-	 * Returns logo claim
222
-	 * @return string logo claim
223
-	 * @deprecated 13.0.0
224
-	 */
225
-	public function getLogoClaim() {
226
-		return '';
227
-	}
220
+    /**
221
+     * Returns logo claim
222
+     * @return string logo claim
223
+     * @deprecated 13.0.0
224
+     */
225
+    public function getLogoClaim() {
226
+        return '';
227
+    }
228 228
 
229
-	/**
230
-	 * Returns short version of the footer
231
-	 * @return string short footer
232
-	 */
233
-	public function getShortFooter() {
234
-		if ($this->themeExist('getShortFooter')) {
235
-			$footer = $this->theme->getShortFooter();
236
-		} else {
237
-			$footer = '<a href="'. $this->getBaseUrl() . '" target="_blank"' .
238
-				' rel="noreferrer noopener">' .$this->getEntity() . '</a>'.
239
-				' – ' . $this->getSlogan();
240
-		}
229
+    /**
230
+     * Returns short version of the footer
231
+     * @return string short footer
232
+     */
233
+    public function getShortFooter() {
234
+        if ($this->themeExist('getShortFooter')) {
235
+            $footer = $this->theme->getShortFooter();
236
+        } else {
237
+            $footer = '<a href="'. $this->getBaseUrl() . '" target="_blank"' .
238
+                ' rel="noreferrer noopener">' .$this->getEntity() . '</a>'.
239
+                ' – ' . $this->getSlogan();
240
+        }
241 241
 
242
-		return $footer;
243
-	}
242
+        return $footer;
243
+    }
244 244
 
245
-	/**
246
-	 * Returns long version of the footer
247
-	 * @return string long footer
248
-	 */
249
-	public function getLongFooter() {
250
-		if ($this->themeExist('getLongFooter')) {
251
-			$footer = $this->theme->getLongFooter();
252
-		} else {
253
-			$footer = $this->getShortFooter();
254
-		}
245
+    /**
246
+     * Returns long version of the footer
247
+     * @return string long footer
248
+     */
249
+    public function getLongFooter() {
250
+        if ($this->themeExist('getLongFooter')) {
251
+            $footer = $this->theme->getLongFooter();
252
+        } else {
253
+            $footer = $this->getShortFooter();
254
+        }
255 255
 
256
-		return $footer;
257
-	}
256
+        return $footer;
257
+    }
258 258
 
259
-	/**
260
-	 * @param string $key
261
-	 * @return string URL to doc with key
262
-	 */
263
-	public function buildDocLinkToKey($key) {
264
-		if ($this->themeExist('buildDocLinkToKey')) {
265
-			return $this->theme->buildDocLinkToKey($key);
266
-		}
267
-		return $this->getDocBaseUrl() . '/server/' . $this->defaultDocVersion . '/go.php?to=' . $key;
268
-	}
259
+    /**
260
+     * @param string $key
261
+     * @return string URL to doc with key
262
+     */
263
+    public function buildDocLinkToKey($key) {
264
+        if ($this->themeExist('buildDocLinkToKey')) {
265
+            return $this->theme->buildDocLinkToKey($key);
266
+        }
267
+        return $this->getDocBaseUrl() . '/server/' . $this->defaultDocVersion . '/go.php?to=' . $key;
268
+    }
269 269
 
270
-	/**
271
-	 * Returns primary color
272
-	 * @return string
273
-	 */
274
-	public function getColorPrimary() {
270
+    /**
271
+     * Returns primary color
272
+     * @return string
273
+     */
274
+    public function getColorPrimary() {
275 275
 
276
-		if ($this->themeExist('getColorPrimary')) {
277
-			return $this->theme->getColorPrimary();
278
-		}
279
-		if ($this->themeExist('getMailHeaderColor')) {
280
-			return $this->theme->getMailHeaderColor();
281
-		}
282
-		return $this->defaultColorPrimary;
283
-	}
276
+        if ($this->themeExist('getColorPrimary')) {
277
+            return $this->theme->getColorPrimary();
278
+        }
279
+        if ($this->themeExist('getMailHeaderColor')) {
280
+            return $this->theme->getMailHeaderColor();
281
+        }
282
+        return $this->defaultColorPrimary;
283
+    }
284 284
 
285
-	/**
286
-	 * @return array scss variables to overwrite
287
-	 */
288
-	public function getScssVariables() {
289
-		if($this->themeExist('getScssVariables')) {
290
-			return $this->theme->getScssVariables();
291
-		}
292
-		return [];
293
-	}
285
+    /**
286
+     * @return array scss variables to overwrite
287
+     */
288
+    public function getScssVariables() {
289
+        if($this->themeExist('getScssVariables')) {
290
+            return $this->theme->getScssVariables();
291
+        }
292
+        return [];
293
+    }
294 294
 
295
-	public function shouldReplaceIcons() {
296
-		return false;
297
-	}
295
+    public function shouldReplaceIcons() {
296
+        return false;
297
+    }
298 298
 
299
-	/**
300
-	 * Themed logo url
301
-	 *
302
-	 * @param bool $useSvg Whether to point to the SVG image or a fallback
303
-	 * @return string
304
-	 */
305
-	public function getLogo($useSvg = true) {
306
-		if ($this->themeExist('getLogo')) {
307
-			return $this->theme->getLogo($useSvg);
308
-		}
299
+    /**
300
+     * Themed logo url
301
+     *
302
+     * @param bool $useSvg Whether to point to the SVG image or a fallback
303
+     * @return string
304
+     */
305
+    public function getLogo($useSvg = true) {
306
+        if ($this->themeExist('getLogo')) {
307
+            return $this->theme->getLogo($useSvg);
308
+        }
309 309
 
310
-		if($useSvg) {
311
-			$logo = \OC::$server->getURLGenerator()->imagePath('core', 'logo.svg');
312
-		} else {
313
-			$logo = \OC::$server->getURLGenerator()->imagePath('core', 'logo.png');
314
-		}
315
-	    return $logo . '?v=' . hash('sha1', implode('.', \OCP\Util::getVersion()));
316
-	}
310
+        if($useSvg) {
311
+            $logo = \OC::$server->getURLGenerator()->imagePath('core', 'logo.svg');
312
+        } else {
313
+            $logo = \OC::$server->getURLGenerator()->imagePath('core', 'logo.png');
314
+        }
315
+        return $logo . '?v=' . hash('sha1', implode('.', \OCP\Util::getVersion()));
316
+    }
317 317
 }
Please login to merge, or discard this patch.
lib/private/Installer.php 1 patch
Indentation   +556 added lines, -556 removed lines patch added patch discarded remove patch
@@ -63,560 +63,560 @@
 block discarded – undo
63 63
  * This class provides the functionality needed to install, update and remove apps
64 64
  */
65 65
 class Installer {
66
-	/** @var AppFetcher */
67
-	private $appFetcher;
68
-	/** @var IClientService */
69
-	private $clientService;
70
-	/** @var ITempManager */
71
-	private $tempManager;
72
-	/** @var ILogger */
73
-	private $logger;
74
-	/** @var IConfig */
75
-	private $config;
76
-
77
-	/**
78
-	 * @param AppFetcher $appFetcher
79
-	 * @param IClientService $clientService
80
-	 * @param ITempManager $tempManager
81
-	 * @param ILogger $logger
82
-	 * @param IConfig $config
83
-	 */
84
-	public function __construct(AppFetcher $appFetcher,
85
-								IClientService $clientService,
86
-								ITempManager $tempManager,
87
-								ILogger $logger,
88
-								IConfig $config) {
89
-		$this->appFetcher = $appFetcher;
90
-		$this->clientService = $clientService;
91
-		$this->tempManager = $tempManager;
92
-		$this->logger = $logger;
93
-		$this->config = $config;
94
-	}
95
-
96
-	/**
97
-	 * Installs an app that is located in one of the app folders already
98
-	 *
99
-	 * @param string $appId App to install
100
-	 * @throws \Exception
101
-	 * @return string app ID
102
-	 */
103
-	public function installApp($appId) {
104
-		$app = \OC_App::findAppInDirectories($appId);
105
-		if($app === false) {
106
-			throw new \Exception('App not found in any app directory');
107
-		}
108
-
109
-		$basedir = $app['path'].'/'.$appId;
110
-		$info = OC_App::getAppInfo($basedir.'/appinfo/info.xml', true);
111
-
112
-		$l = \OC::$server->getL10N('core');
113
-
114
-		if(!is_array($info)) {
115
-			throw new \Exception(
116
-				$l->t('App "%s" cannot be installed because appinfo file cannot be read.',
117
-					[$info['name']]
118
-				)
119
-			);
120
-		}
121
-
122
-		$version = \OCP\Util::getVersion();
123
-		if (!\OC_App::isAppCompatible($version, $info)) {
124
-			throw new \Exception(
125
-				// TODO $l
126
-				$l->t('App "%s" cannot be installed because it is not compatible with this version of the server.',
127
-					[$info['name']]
128
-				)
129
-			);
130
-		}
131
-
132
-		// check for required dependencies
133
-		\OC_App::checkAppDependencies($this->config, $l, $info);
134
-		\OC_App::registerAutoloading($appId, $basedir);
135
-
136
-		//install the database
137
-		if(is_file($basedir.'/appinfo/database.xml')) {
138
-			if (\OC::$server->getAppConfig()->getValue($info['id'], 'installed_version') === null) {
139
-				OC_DB::createDbFromStructure($basedir.'/appinfo/database.xml');
140
-			} else {
141
-				OC_DB::updateDbFromStructure($basedir.'/appinfo/database.xml');
142
-			}
143
-		} else {
144
-			$ms = new \OC\DB\MigrationService($info['id'], \OC::$server->getDatabaseConnection());
145
-			$ms->migrate();
146
-		}
147
-
148
-		\OC_App::setupBackgroundJobs($info['background-jobs']);
149
-		if(isset($info['settings']) && is_array($info['settings'])) {
150
-			\OC::$server->getSettingsManager()->setupSettings($info['settings']);
151
-		}
152
-
153
-		//run appinfo/install.php
154
-		if((!isset($data['noinstall']) or $data['noinstall']==false)) {
155
-			self::includeAppScript($basedir . '/appinfo/install.php');
156
-		}
157
-
158
-		$appData = OC_App::getAppInfo($appId);
159
-		OC_App::executeRepairSteps($appId, $appData['repair-steps']['install']);
160
-
161
-		//set the installed version
162
-		\OC::$server->getConfig()->setAppValue($info['id'], 'installed_version', OC_App::getAppVersion($info['id'], false));
163
-		\OC::$server->getConfig()->setAppValue($info['id'], 'enabled', 'no');
164
-
165
-		//set remote/public handlers
166
-		foreach($info['remote'] as $name=>$path) {
167
-			\OC::$server->getConfig()->setAppValue('core', 'remote_'.$name, $info['id'].'/'.$path);
168
-		}
169
-		foreach($info['public'] as $name=>$path) {
170
-			\OC::$server->getConfig()->setAppValue('core', 'public_'.$name, $info['id'].'/'.$path);
171
-		}
172
-
173
-		OC_App::setAppTypes($info['id']);
174
-
175
-		return $info['id'];
176
-	}
177
-
178
-	/**
179
-	 * @brief checks whether or not an app is installed
180
-	 * @param string $app app
181
-	 * @returns bool
182
-	 *
183
-	 * Checks whether or not an app is installed, i.e. registered in apps table.
184
-	 */
185
-	public static function isInstalled( $app ) {
186
-		return (\OC::$server->getConfig()->getAppValue($app, "installed_version", null) !== null);
187
-	}
188
-
189
-	/**
190
-	 * Updates the specified app from the appstore
191
-	 *
192
-	 * @param string $appId
193
-	 * @return bool
194
-	 */
195
-	public function updateAppstoreApp($appId) {
196
-		if(self::isUpdateAvailable($appId, $this->appFetcher)) {
197
-			try {
198
-				$this->downloadApp($appId);
199
-			} catch (\Exception $e) {
200
-				$this->logger->error($e->getMessage(), ['app' => 'core']);
201
-				return false;
202
-			}
203
-			return OC_App::updateApp($appId);
204
-		}
205
-
206
-		return false;
207
-	}
208
-
209
-	/**
210
-	 * Downloads an app and puts it into the app directory
211
-	 *
212
-	 * @param string $appId
213
-	 *
214
-	 * @throws \Exception If the installation was not successful
215
-	 */
216
-	public function downloadApp($appId) {
217
-		$appId = strtolower($appId);
218
-
219
-		$apps = $this->appFetcher->get();
220
-		foreach($apps as $app) {
221
-			if($app['id'] === $appId) {
222
-				// Load the certificate
223
-				$certificate = new X509();
224
-				$certificate->loadCA(file_get_contents(__DIR__ . '/../../resources/codesigning/root.crt'));
225
-				$loadedCertificate = $certificate->loadX509($app['certificate']);
226
-
227
-				// Verify if the certificate has been revoked
228
-				$crl = new X509();
229
-				$crl->loadCA(file_get_contents(__DIR__ . '/../../resources/codesigning/root.crt'));
230
-				$crl->loadCRL(file_get_contents(__DIR__ . '/../../resources/codesigning/root.crl'));
231
-				if($crl->validateSignature() !== true) {
232
-					throw new \Exception('Could not validate CRL signature');
233
-				}
234
-				$csn = $loadedCertificate['tbsCertificate']['serialNumber']->toString();
235
-				$revoked = $crl->getRevoked($csn);
236
-				if ($revoked !== false) {
237
-					throw new \Exception(
238
-						sprintf(
239
-							'Certificate "%s" has been revoked',
240
-							$csn
241
-						)
242
-					);
243
-				}
244
-
245
-				// Verify if the certificate has been issued by the Nextcloud Code Authority CA
246
-				if($certificate->validateSignature() !== true) {
247
-					throw new \Exception(
248
-						sprintf(
249
-							'App with id %s has a certificate not issued by a trusted Code Signing Authority',
250
-							$appId
251
-						)
252
-					);
253
-				}
254
-
255
-				// Verify if the certificate is issued for the requested app id
256
-				$certInfo = openssl_x509_parse($app['certificate']);
257
-				if(!isset($certInfo['subject']['CN'])) {
258
-					throw new \Exception(
259
-						sprintf(
260
-							'App with id %s has a cert with no CN',
261
-							$appId
262
-						)
263
-					);
264
-				}
265
-				if($certInfo['subject']['CN'] !== $appId) {
266
-					throw new \Exception(
267
-						sprintf(
268
-							'App with id %s has a cert issued to %s',
269
-							$appId,
270
-							$certInfo['subject']['CN']
271
-						)
272
-					);
273
-				}
274
-
275
-				// Download the release
276
-				$tempFile = $this->tempManager->getTemporaryFile('.tar.gz');
277
-				$client = $this->clientService->newClient();
278
-				$client->get($app['releases'][0]['download'], ['save_to' => $tempFile]);
279
-
280
-				// Check if the signature actually matches the downloaded content
281
-				$certificate = openssl_get_publickey($app['certificate']);
282
-				$verified = (bool)openssl_verify(file_get_contents($tempFile), base64_decode($app['releases'][0]['signature']), $certificate, OPENSSL_ALGO_SHA512);
283
-				openssl_free_key($certificate);
284
-
285
-				if($verified === true) {
286
-					// Seems to match, let's proceed
287
-					$extractDir = $this->tempManager->getTemporaryFolder();
288
-					$archive = new TAR($tempFile);
289
-
290
-					if($archive) {
291
-						if (!$archive->extract($extractDir)) {
292
-							throw new \Exception(
293
-								sprintf(
294
-									'Could not extract app %s',
295
-									$appId
296
-								)
297
-							);
298
-						}
299
-						$allFiles = scandir($extractDir);
300
-						$folders = array_diff($allFiles, ['.', '..']);
301
-						$folders = array_values($folders);
302
-
303
-						if(count($folders) > 1) {
304
-							throw new \Exception(
305
-								sprintf(
306
-									'Extracted app %s has more than 1 folder',
307
-									$appId
308
-								)
309
-							);
310
-						}
311
-
312
-						// Check if appinfo/info.xml has the same app ID as well
313
-						$loadEntities = libxml_disable_entity_loader(false);
314
-						$xml = simplexml_load_file($extractDir . '/' . $folders[0] . '/appinfo/info.xml');
315
-						libxml_disable_entity_loader($loadEntities);
316
-						if((string)$xml->id !== $appId) {
317
-							throw new \Exception(
318
-								sprintf(
319
-									'App for id %s has a wrong app ID in info.xml: %s',
320
-									$appId,
321
-									(string)$xml->id
322
-								)
323
-							);
324
-						}
325
-
326
-						// Check if the version is lower than before
327
-						$currentVersion = OC_App::getAppVersion($appId);
328
-						$newVersion = (string)$xml->version;
329
-						if(version_compare($currentVersion, $newVersion) === 1) {
330
-							throw new \Exception(
331
-								sprintf(
332
-									'App for id %s has version %s and tried to update to lower version %s',
333
-									$appId,
334
-									$currentVersion,
335
-									$newVersion
336
-								)
337
-							);
338
-						}
339
-
340
-						$baseDir = OC_App::getInstallPath() . '/' . $appId;
341
-						// Remove old app with the ID if existent
342
-						OC_Helper::rmdirr($baseDir);
343
-						// Move to app folder
344
-						if(@mkdir($baseDir)) {
345
-							$extractDir .= '/' . $folders[0];
346
-							OC_Helper::copyr($extractDir, $baseDir);
347
-						}
348
-						OC_Helper::copyr($extractDir, $baseDir);
349
-						OC_Helper::rmdirr($extractDir);
350
-						return;
351
-					} else {
352
-						throw new \Exception(
353
-							sprintf(
354
-								'Could not extract app with ID %s to %s',
355
-								$appId,
356
-								$extractDir
357
-							)
358
-						);
359
-					}
360
-				} else {
361
-					// Signature does not match
362
-					throw new \Exception(
363
-						sprintf(
364
-							'App with id %s has invalid signature',
365
-							$appId
366
-						)
367
-					);
368
-				}
369
-			}
370
-		}
371
-
372
-		throw new \Exception(
373
-			sprintf(
374
-				'Could not download app %s',
375
-				$appId
376
-			)
377
-		);
378
-	}
379
-
380
-	/**
381
-	 * Check if an update for the app is available
382
-	 *
383
-	 * @param string $appId
384
-	 * @param AppFetcher $appFetcher
385
-	 * @return string|false false or the version number of the update
386
-	 */
387
-	public static function isUpdateAvailable($appId,
388
-									  AppFetcher $appFetcher) {
389
-		static $isInstanceReadyForUpdates = null;
390
-
391
-		if ($isInstanceReadyForUpdates === null) {
392
-			$installPath = OC_App::getInstallPath();
393
-			if ($installPath === false || $installPath === null) {
394
-				$isInstanceReadyForUpdates = false;
395
-			} else {
396
-				$isInstanceReadyForUpdates = true;
397
-			}
398
-		}
399
-
400
-		if ($isInstanceReadyForUpdates === false) {
401
-			return false;
402
-		}
403
-
404
-		$apps = $appFetcher->get();
405
-		foreach($apps as $app) {
406
-			if($app['id'] === $appId) {
407
-				$currentVersion = OC_App::getAppVersion($appId);
408
-				$newestVersion = $app['releases'][0]['version'];
409
-				if (version_compare($newestVersion, $currentVersion, '>')) {
410
-					return $newestVersion;
411
-				} else {
412
-					return false;
413
-				}
414
-			}
415
-		}
416
-
417
-		return false;
418
-	}
419
-
420
-	/**
421
-	 * Check if app is already downloaded
422
-	 * @param string $name name of the application to remove
423
-	 * @return boolean
424
-	 *
425
-	 * The function will check if the app is already downloaded in the apps repository
426
-	 */
427
-	public function isDownloaded($name) {
428
-		foreach(\OC::$APPSROOTS as $dir) {
429
-			$dirToTest  = $dir['path'];
430
-			$dirToTest .= '/';
431
-			$dirToTest .= $name;
432
-			$dirToTest .= '/';
433
-
434
-			if (is_dir($dirToTest)) {
435
-				return true;
436
-			}
437
-		}
438
-
439
-		return false;
440
-	}
441
-
442
-	/**
443
-	 * Removes an app
444
-	 * @param string $appId ID of the application to remove
445
-	 * @return boolean
446
-	 *
447
-	 *
448
-	 * This function works as follows
449
-	 *   -# call uninstall repair steps
450
-	 *   -# removing the files
451
-	 *
452
-	 * The function will not delete preferences, tables and the configuration,
453
-	 * this has to be done by the function oc_app_uninstall().
454
-	 */
455
-	public function removeApp($appId) {
456
-		if($this->isDownloaded( $appId )) {
457
-			$appDir = OC_App::getInstallPath() . '/' . $appId;
458
-			OC_Helper::rmdirr($appDir);
459
-			return true;
460
-		}else{
461
-			\OCP\Util::writeLog('core', 'can\'t remove app '.$appId.'. It is not installed.', \OCP\Util::ERROR);
462
-
463
-			return false;
464
-		}
465
-
466
-	}
467
-
468
-	/**
469
-	 * Installs the app within the bundle and marks the bundle as installed
470
-	 *
471
-	 * @param Bundle $bundle
472
-	 * @throws \Exception If app could not get installed
473
-	 */
474
-	public function installAppBundle(Bundle $bundle) {
475
-		$appIds = $bundle->getAppIdentifiers();
476
-		foreach($appIds as $appId) {
477
-			if(!$this->isDownloaded($appId)) {
478
-				$this->downloadApp($appId);
479
-			}
480
-			$this->installApp($appId);
481
-			$app = new OC_App();
482
-			$app->enable($appId);
483
-		}
484
-		$bundles = json_decode($this->config->getAppValue('core', 'installed.bundles', json_encode([])), true);
485
-		$bundles[] = $bundle->getIdentifier();
486
-		$this->config->setAppValue('core', 'installed.bundles', json_encode($bundles));
487
-	}
488
-
489
-	/**
490
-	 * Installs shipped apps
491
-	 *
492
-	 * This function installs all apps found in the 'apps' directory that should be enabled by default;
493
-	 * @param bool $softErrors When updating we ignore errors and simply log them, better to have a
494
-	 *                         working ownCloud at the end instead of an aborted update.
495
-	 * @return array Array of error messages (appid => Exception)
496
-	 */
497
-	public static function installShippedApps($softErrors = false) {
498
-		$errors = [];
499
-		foreach(\OC::$APPSROOTS as $app_dir) {
500
-			if($dir = opendir( $app_dir['path'] )) {
501
-				while( false !== ( $filename = readdir( $dir ))) {
502
-					if( substr( $filename, 0, 1 ) != '.' and is_dir($app_dir['path']."/$filename") ) {
503
-						if( file_exists( $app_dir['path']."/$filename/appinfo/info.xml" )) {
504
-							if(!Installer::isInstalled($filename)) {
505
-								$info=OC_App::getAppInfo($filename);
506
-								$enabled = isset($info['default_enable']);
507
-								if (($enabled || in_array($filename, \OC::$server->getAppManager()->getAlwaysEnabledApps()))
508
-									  && \OC::$server->getConfig()->getAppValue($filename, 'enabled') !== 'no') {
509
-									if ($softErrors) {
510
-										try {
511
-											Installer::installShippedApp($filename);
512
-										} catch (HintException $e) {
513
-											if ($e->getPrevious() instanceof TableExistsException) {
514
-												$errors[$filename] = $e;
515
-												continue;
516
-											}
517
-											throw $e;
518
-										}
519
-									} else {
520
-										Installer::installShippedApp($filename);
521
-									}
522
-									\OC::$server->getConfig()->setAppValue($filename, 'enabled', 'yes');
523
-								}
524
-							}
525
-						}
526
-					}
527
-				}
528
-				closedir( $dir );
529
-			}
530
-		}
531
-
532
-		return $errors;
533
-	}
534
-
535
-	/**
536
-	 * install an app already placed in the app folder
537
-	 * @param string $app id of the app to install
538
-	 * @return integer
539
-	 */
540
-	public static function installShippedApp($app) {
541
-		//install the database
542
-		$appPath = OC_App::getAppPath($app);
543
-		\OC_App::registerAutoloading($app, $appPath);
544
-
545
-		if(is_file("$appPath/appinfo/database.xml")) {
546
-			try {
547
-				OC_DB::createDbFromStructure("$appPath/appinfo/database.xml");
548
-			} catch (TableExistsException $e) {
549
-				throw new HintException(
550
-					'Failed to enable app ' . $app,
551
-					'Please ask for help via one of our <a href="https://nextcloud.com/support/" target="_blank" rel="noreferrer noopener">support channels</a>.',
552
-					0, $e
553
-				);
554
-			}
555
-		} else {
556
-			$ms = new \OC\DB\MigrationService($app, \OC::$server->getDatabaseConnection());
557
-			$ms->migrate();
558
-		}
559
-
560
-		//run appinfo/install.php
561
-		self::includeAppScript("$appPath/appinfo/install.php");
562
-
563
-		$info = OC_App::getAppInfo($app);
564
-		if (is_null($info)) {
565
-			return false;
566
-		}
567
-		\OC_App::setupBackgroundJobs($info['background-jobs']);
568
-
569
-		OC_App::executeRepairSteps($app, $info['repair-steps']['install']);
570
-
571
-		$config = \OC::$server->getConfig();
572
-
573
-		$config->setAppValue($app, 'installed_version', OC_App::getAppVersion($app));
574
-		if (array_key_exists('ocsid', $info)) {
575
-			$config->setAppValue($app, 'ocsid', $info['ocsid']);
576
-		}
577
-
578
-		//set remote/public handlers
579
-		foreach($info['remote'] as $name=>$path) {
580
-			$config->setAppValue('core', 'remote_'.$name, $app.'/'.$path);
581
-		}
582
-		foreach($info['public'] as $name=>$path) {
583
-			$config->setAppValue('core', 'public_'.$name, $app.'/'.$path);
584
-		}
585
-
586
-		OC_App::setAppTypes($info['id']);
587
-
588
-		if(isset($info['settings']) && is_array($info['settings'])) {
589
-			// requires that autoloading was registered for the app,
590
-			// as happens before running the install.php some lines above
591
-			\OC::$server->getSettingsManager()->setupSettings($info['settings']);
592
-		}
593
-
594
-		return $info['id'];
595
-	}
596
-
597
-	/**
598
-	 * check the code of an app with some static code checks
599
-	 * @param string $folder the folder of the app to check
600
-	 * @return boolean true for app is o.k. and false for app is not o.k.
601
-	 */
602
-	public static function checkCode($folder) {
603
-		// is the code checker enabled?
604
-		if(!\OC::$server->getConfig()->getSystemValue('appcodechecker', false)) {
605
-			return true;
606
-		}
607
-
608
-		$codeChecker = new CodeChecker(new PrivateCheck(new EmptyCheck()));
609
-		$errors = $codeChecker->analyseFolder(basename($folder), $folder);
610
-
611
-		return empty($errors);
612
-	}
613
-
614
-	/**
615
-	 * @param string $script
616
-	 */
617
-	private static function includeAppScript($script) {
618
-		if ( file_exists($script) ){
619
-			include $script;
620
-		}
621
-	}
66
+    /** @var AppFetcher */
67
+    private $appFetcher;
68
+    /** @var IClientService */
69
+    private $clientService;
70
+    /** @var ITempManager */
71
+    private $tempManager;
72
+    /** @var ILogger */
73
+    private $logger;
74
+    /** @var IConfig */
75
+    private $config;
76
+
77
+    /**
78
+     * @param AppFetcher $appFetcher
79
+     * @param IClientService $clientService
80
+     * @param ITempManager $tempManager
81
+     * @param ILogger $logger
82
+     * @param IConfig $config
83
+     */
84
+    public function __construct(AppFetcher $appFetcher,
85
+                                IClientService $clientService,
86
+                                ITempManager $tempManager,
87
+                                ILogger $logger,
88
+                                IConfig $config) {
89
+        $this->appFetcher = $appFetcher;
90
+        $this->clientService = $clientService;
91
+        $this->tempManager = $tempManager;
92
+        $this->logger = $logger;
93
+        $this->config = $config;
94
+    }
95
+
96
+    /**
97
+     * Installs an app that is located in one of the app folders already
98
+     *
99
+     * @param string $appId App to install
100
+     * @throws \Exception
101
+     * @return string app ID
102
+     */
103
+    public function installApp($appId) {
104
+        $app = \OC_App::findAppInDirectories($appId);
105
+        if($app === false) {
106
+            throw new \Exception('App not found in any app directory');
107
+        }
108
+
109
+        $basedir = $app['path'].'/'.$appId;
110
+        $info = OC_App::getAppInfo($basedir.'/appinfo/info.xml', true);
111
+
112
+        $l = \OC::$server->getL10N('core');
113
+
114
+        if(!is_array($info)) {
115
+            throw new \Exception(
116
+                $l->t('App "%s" cannot be installed because appinfo file cannot be read.',
117
+                    [$info['name']]
118
+                )
119
+            );
120
+        }
121
+
122
+        $version = \OCP\Util::getVersion();
123
+        if (!\OC_App::isAppCompatible($version, $info)) {
124
+            throw new \Exception(
125
+                // TODO $l
126
+                $l->t('App "%s" cannot be installed because it is not compatible with this version of the server.',
127
+                    [$info['name']]
128
+                )
129
+            );
130
+        }
131
+
132
+        // check for required dependencies
133
+        \OC_App::checkAppDependencies($this->config, $l, $info);
134
+        \OC_App::registerAutoloading($appId, $basedir);
135
+
136
+        //install the database
137
+        if(is_file($basedir.'/appinfo/database.xml')) {
138
+            if (\OC::$server->getAppConfig()->getValue($info['id'], 'installed_version') === null) {
139
+                OC_DB::createDbFromStructure($basedir.'/appinfo/database.xml');
140
+            } else {
141
+                OC_DB::updateDbFromStructure($basedir.'/appinfo/database.xml');
142
+            }
143
+        } else {
144
+            $ms = new \OC\DB\MigrationService($info['id'], \OC::$server->getDatabaseConnection());
145
+            $ms->migrate();
146
+        }
147
+
148
+        \OC_App::setupBackgroundJobs($info['background-jobs']);
149
+        if(isset($info['settings']) && is_array($info['settings'])) {
150
+            \OC::$server->getSettingsManager()->setupSettings($info['settings']);
151
+        }
152
+
153
+        //run appinfo/install.php
154
+        if((!isset($data['noinstall']) or $data['noinstall']==false)) {
155
+            self::includeAppScript($basedir . '/appinfo/install.php');
156
+        }
157
+
158
+        $appData = OC_App::getAppInfo($appId);
159
+        OC_App::executeRepairSteps($appId, $appData['repair-steps']['install']);
160
+
161
+        //set the installed version
162
+        \OC::$server->getConfig()->setAppValue($info['id'], 'installed_version', OC_App::getAppVersion($info['id'], false));
163
+        \OC::$server->getConfig()->setAppValue($info['id'], 'enabled', 'no');
164
+
165
+        //set remote/public handlers
166
+        foreach($info['remote'] as $name=>$path) {
167
+            \OC::$server->getConfig()->setAppValue('core', 'remote_'.$name, $info['id'].'/'.$path);
168
+        }
169
+        foreach($info['public'] as $name=>$path) {
170
+            \OC::$server->getConfig()->setAppValue('core', 'public_'.$name, $info['id'].'/'.$path);
171
+        }
172
+
173
+        OC_App::setAppTypes($info['id']);
174
+
175
+        return $info['id'];
176
+    }
177
+
178
+    /**
179
+     * @brief checks whether or not an app is installed
180
+     * @param string $app app
181
+     * @returns bool
182
+     *
183
+     * Checks whether or not an app is installed, i.e. registered in apps table.
184
+     */
185
+    public static function isInstalled( $app ) {
186
+        return (\OC::$server->getConfig()->getAppValue($app, "installed_version", null) !== null);
187
+    }
188
+
189
+    /**
190
+     * Updates the specified app from the appstore
191
+     *
192
+     * @param string $appId
193
+     * @return bool
194
+     */
195
+    public function updateAppstoreApp($appId) {
196
+        if(self::isUpdateAvailable($appId, $this->appFetcher)) {
197
+            try {
198
+                $this->downloadApp($appId);
199
+            } catch (\Exception $e) {
200
+                $this->logger->error($e->getMessage(), ['app' => 'core']);
201
+                return false;
202
+            }
203
+            return OC_App::updateApp($appId);
204
+        }
205
+
206
+        return false;
207
+    }
208
+
209
+    /**
210
+     * Downloads an app and puts it into the app directory
211
+     *
212
+     * @param string $appId
213
+     *
214
+     * @throws \Exception If the installation was not successful
215
+     */
216
+    public function downloadApp($appId) {
217
+        $appId = strtolower($appId);
218
+
219
+        $apps = $this->appFetcher->get();
220
+        foreach($apps as $app) {
221
+            if($app['id'] === $appId) {
222
+                // Load the certificate
223
+                $certificate = new X509();
224
+                $certificate->loadCA(file_get_contents(__DIR__ . '/../../resources/codesigning/root.crt'));
225
+                $loadedCertificate = $certificate->loadX509($app['certificate']);
226
+
227
+                // Verify if the certificate has been revoked
228
+                $crl = new X509();
229
+                $crl->loadCA(file_get_contents(__DIR__ . '/../../resources/codesigning/root.crt'));
230
+                $crl->loadCRL(file_get_contents(__DIR__ . '/../../resources/codesigning/root.crl'));
231
+                if($crl->validateSignature() !== true) {
232
+                    throw new \Exception('Could not validate CRL signature');
233
+                }
234
+                $csn = $loadedCertificate['tbsCertificate']['serialNumber']->toString();
235
+                $revoked = $crl->getRevoked($csn);
236
+                if ($revoked !== false) {
237
+                    throw new \Exception(
238
+                        sprintf(
239
+                            'Certificate "%s" has been revoked',
240
+                            $csn
241
+                        )
242
+                    );
243
+                }
244
+
245
+                // Verify if the certificate has been issued by the Nextcloud Code Authority CA
246
+                if($certificate->validateSignature() !== true) {
247
+                    throw new \Exception(
248
+                        sprintf(
249
+                            'App with id %s has a certificate not issued by a trusted Code Signing Authority',
250
+                            $appId
251
+                        )
252
+                    );
253
+                }
254
+
255
+                // Verify if the certificate is issued for the requested app id
256
+                $certInfo = openssl_x509_parse($app['certificate']);
257
+                if(!isset($certInfo['subject']['CN'])) {
258
+                    throw new \Exception(
259
+                        sprintf(
260
+                            'App with id %s has a cert with no CN',
261
+                            $appId
262
+                        )
263
+                    );
264
+                }
265
+                if($certInfo['subject']['CN'] !== $appId) {
266
+                    throw new \Exception(
267
+                        sprintf(
268
+                            'App with id %s has a cert issued to %s',
269
+                            $appId,
270
+                            $certInfo['subject']['CN']
271
+                        )
272
+                    );
273
+                }
274
+
275
+                // Download the release
276
+                $tempFile = $this->tempManager->getTemporaryFile('.tar.gz');
277
+                $client = $this->clientService->newClient();
278
+                $client->get($app['releases'][0]['download'], ['save_to' => $tempFile]);
279
+
280
+                // Check if the signature actually matches the downloaded content
281
+                $certificate = openssl_get_publickey($app['certificate']);
282
+                $verified = (bool)openssl_verify(file_get_contents($tempFile), base64_decode($app['releases'][0]['signature']), $certificate, OPENSSL_ALGO_SHA512);
283
+                openssl_free_key($certificate);
284
+
285
+                if($verified === true) {
286
+                    // Seems to match, let's proceed
287
+                    $extractDir = $this->tempManager->getTemporaryFolder();
288
+                    $archive = new TAR($tempFile);
289
+
290
+                    if($archive) {
291
+                        if (!$archive->extract($extractDir)) {
292
+                            throw new \Exception(
293
+                                sprintf(
294
+                                    'Could not extract app %s',
295
+                                    $appId
296
+                                )
297
+                            );
298
+                        }
299
+                        $allFiles = scandir($extractDir);
300
+                        $folders = array_diff($allFiles, ['.', '..']);
301
+                        $folders = array_values($folders);
302
+
303
+                        if(count($folders) > 1) {
304
+                            throw new \Exception(
305
+                                sprintf(
306
+                                    'Extracted app %s has more than 1 folder',
307
+                                    $appId
308
+                                )
309
+                            );
310
+                        }
311
+
312
+                        // Check if appinfo/info.xml has the same app ID as well
313
+                        $loadEntities = libxml_disable_entity_loader(false);
314
+                        $xml = simplexml_load_file($extractDir . '/' . $folders[0] . '/appinfo/info.xml');
315
+                        libxml_disable_entity_loader($loadEntities);
316
+                        if((string)$xml->id !== $appId) {
317
+                            throw new \Exception(
318
+                                sprintf(
319
+                                    'App for id %s has a wrong app ID in info.xml: %s',
320
+                                    $appId,
321
+                                    (string)$xml->id
322
+                                )
323
+                            );
324
+                        }
325
+
326
+                        // Check if the version is lower than before
327
+                        $currentVersion = OC_App::getAppVersion($appId);
328
+                        $newVersion = (string)$xml->version;
329
+                        if(version_compare($currentVersion, $newVersion) === 1) {
330
+                            throw new \Exception(
331
+                                sprintf(
332
+                                    'App for id %s has version %s and tried to update to lower version %s',
333
+                                    $appId,
334
+                                    $currentVersion,
335
+                                    $newVersion
336
+                                )
337
+                            );
338
+                        }
339
+
340
+                        $baseDir = OC_App::getInstallPath() . '/' . $appId;
341
+                        // Remove old app with the ID if existent
342
+                        OC_Helper::rmdirr($baseDir);
343
+                        // Move to app folder
344
+                        if(@mkdir($baseDir)) {
345
+                            $extractDir .= '/' . $folders[0];
346
+                            OC_Helper::copyr($extractDir, $baseDir);
347
+                        }
348
+                        OC_Helper::copyr($extractDir, $baseDir);
349
+                        OC_Helper::rmdirr($extractDir);
350
+                        return;
351
+                    } else {
352
+                        throw new \Exception(
353
+                            sprintf(
354
+                                'Could not extract app with ID %s to %s',
355
+                                $appId,
356
+                                $extractDir
357
+                            )
358
+                        );
359
+                    }
360
+                } else {
361
+                    // Signature does not match
362
+                    throw new \Exception(
363
+                        sprintf(
364
+                            'App with id %s has invalid signature',
365
+                            $appId
366
+                        )
367
+                    );
368
+                }
369
+            }
370
+        }
371
+
372
+        throw new \Exception(
373
+            sprintf(
374
+                'Could not download app %s',
375
+                $appId
376
+            )
377
+        );
378
+    }
379
+
380
+    /**
381
+     * Check if an update for the app is available
382
+     *
383
+     * @param string $appId
384
+     * @param AppFetcher $appFetcher
385
+     * @return string|false false or the version number of the update
386
+     */
387
+    public static function isUpdateAvailable($appId,
388
+                                        AppFetcher $appFetcher) {
389
+        static $isInstanceReadyForUpdates = null;
390
+
391
+        if ($isInstanceReadyForUpdates === null) {
392
+            $installPath = OC_App::getInstallPath();
393
+            if ($installPath === false || $installPath === null) {
394
+                $isInstanceReadyForUpdates = false;
395
+            } else {
396
+                $isInstanceReadyForUpdates = true;
397
+            }
398
+        }
399
+
400
+        if ($isInstanceReadyForUpdates === false) {
401
+            return false;
402
+        }
403
+
404
+        $apps = $appFetcher->get();
405
+        foreach($apps as $app) {
406
+            if($app['id'] === $appId) {
407
+                $currentVersion = OC_App::getAppVersion($appId);
408
+                $newestVersion = $app['releases'][0]['version'];
409
+                if (version_compare($newestVersion, $currentVersion, '>')) {
410
+                    return $newestVersion;
411
+                } else {
412
+                    return false;
413
+                }
414
+            }
415
+        }
416
+
417
+        return false;
418
+    }
419
+
420
+    /**
421
+     * Check if app is already downloaded
422
+     * @param string $name name of the application to remove
423
+     * @return boolean
424
+     *
425
+     * The function will check if the app is already downloaded in the apps repository
426
+     */
427
+    public function isDownloaded($name) {
428
+        foreach(\OC::$APPSROOTS as $dir) {
429
+            $dirToTest  = $dir['path'];
430
+            $dirToTest .= '/';
431
+            $dirToTest .= $name;
432
+            $dirToTest .= '/';
433
+
434
+            if (is_dir($dirToTest)) {
435
+                return true;
436
+            }
437
+        }
438
+
439
+        return false;
440
+    }
441
+
442
+    /**
443
+     * Removes an app
444
+     * @param string $appId ID of the application to remove
445
+     * @return boolean
446
+     *
447
+     *
448
+     * This function works as follows
449
+     *   -# call uninstall repair steps
450
+     *   -# removing the files
451
+     *
452
+     * The function will not delete preferences, tables and the configuration,
453
+     * this has to be done by the function oc_app_uninstall().
454
+     */
455
+    public function removeApp($appId) {
456
+        if($this->isDownloaded( $appId )) {
457
+            $appDir = OC_App::getInstallPath() . '/' . $appId;
458
+            OC_Helper::rmdirr($appDir);
459
+            return true;
460
+        }else{
461
+            \OCP\Util::writeLog('core', 'can\'t remove app '.$appId.'. It is not installed.', \OCP\Util::ERROR);
462
+
463
+            return false;
464
+        }
465
+
466
+    }
467
+
468
+    /**
469
+     * Installs the app within the bundle and marks the bundle as installed
470
+     *
471
+     * @param Bundle $bundle
472
+     * @throws \Exception If app could not get installed
473
+     */
474
+    public function installAppBundle(Bundle $bundle) {
475
+        $appIds = $bundle->getAppIdentifiers();
476
+        foreach($appIds as $appId) {
477
+            if(!$this->isDownloaded($appId)) {
478
+                $this->downloadApp($appId);
479
+            }
480
+            $this->installApp($appId);
481
+            $app = new OC_App();
482
+            $app->enable($appId);
483
+        }
484
+        $bundles = json_decode($this->config->getAppValue('core', 'installed.bundles', json_encode([])), true);
485
+        $bundles[] = $bundle->getIdentifier();
486
+        $this->config->setAppValue('core', 'installed.bundles', json_encode($bundles));
487
+    }
488
+
489
+    /**
490
+     * Installs shipped apps
491
+     *
492
+     * This function installs all apps found in the 'apps' directory that should be enabled by default;
493
+     * @param bool $softErrors When updating we ignore errors and simply log them, better to have a
494
+     *                         working ownCloud at the end instead of an aborted update.
495
+     * @return array Array of error messages (appid => Exception)
496
+     */
497
+    public static function installShippedApps($softErrors = false) {
498
+        $errors = [];
499
+        foreach(\OC::$APPSROOTS as $app_dir) {
500
+            if($dir = opendir( $app_dir['path'] )) {
501
+                while( false !== ( $filename = readdir( $dir ))) {
502
+                    if( substr( $filename, 0, 1 ) != '.' and is_dir($app_dir['path']."/$filename") ) {
503
+                        if( file_exists( $app_dir['path']."/$filename/appinfo/info.xml" )) {
504
+                            if(!Installer::isInstalled($filename)) {
505
+                                $info=OC_App::getAppInfo($filename);
506
+                                $enabled = isset($info['default_enable']);
507
+                                if (($enabled || in_array($filename, \OC::$server->getAppManager()->getAlwaysEnabledApps()))
508
+                                      && \OC::$server->getConfig()->getAppValue($filename, 'enabled') !== 'no') {
509
+                                    if ($softErrors) {
510
+                                        try {
511
+                                            Installer::installShippedApp($filename);
512
+                                        } catch (HintException $e) {
513
+                                            if ($e->getPrevious() instanceof TableExistsException) {
514
+                                                $errors[$filename] = $e;
515
+                                                continue;
516
+                                            }
517
+                                            throw $e;
518
+                                        }
519
+                                    } else {
520
+                                        Installer::installShippedApp($filename);
521
+                                    }
522
+                                    \OC::$server->getConfig()->setAppValue($filename, 'enabled', 'yes');
523
+                                }
524
+                            }
525
+                        }
526
+                    }
527
+                }
528
+                closedir( $dir );
529
+            }
530
+        }
531
+
532
+        return $errors;
533
+    }
534
+
535
+    /**
536
+     * install an app already placed in the app folder
537
+     * @param string $app id of the app to install
538
+     * @return integer
539
+     */
540
+    public static function installShippedApp($app) {
541
+        //install the database
542
+        $appPath = OC_App::getAppPath($app);
543
+        \OC_App::registerAutoloading($app, $appPath);
544
+
545
+        if(is_file("$appPath/appinfo/database.xml")) {
546
+            try {
547
+                OC_DB::createDbFromStructure("$appPath/appinfo/database.xml");
548
+            } catch (TableExistsException $e) {
549
+                throw new HintException(
550
+                    'Failed to enable app ' . $app,
551
+                    'Please ask for help via one of our <a href="https://nextcloud.com/support/" target="_blank" rel="noreferrer noopener">support channels</a>.',
552
+                    0, $e
553
+                );
554
+            }
555
+        } else {
556
+            $ms = new \OC\DB\MigrationService($app, \OC::$server->getDatabaseConnection());
557
+            $ms->migrate();
558
+        }
559
+
560
+        //run appinfo/install.php
561
+        self::includeAppScript("$appPath/appinfo/install.php");
562
+
563
+        $info = OC_App::getAppInfo($app);
564
+        if (is_null($info)) {
565
+            return false;
566
+        }
567
+        \OC_App::setupBackgroundJobs($info['background-jobs']);
568
+
569
+        OC_App::executeRepairSteps($app, $info['repair-steps']['install']);
570
+
571
+        $config = \OC::$server->getConfig();
572
+
573
+        $config->setAppValue($app, 'installed_version', OC_App::getAppVersion($app));
574
+        if (array_key_exists('ocsid', $info)) {
575
+            $config->setAppValue($app, 'ocsid', $info['ocsid']);
576
+        }
577
+
578
+        //set remote/public handlers
579
+        foreach($info['remote'] as $name=>$path) {
580
+            $config->setAppValue('core', 'remote_'.$name, $app.'/'.$path);
581
+        }
582
+        foreach($info['public'] as $name=>$path) {
583
+            $config->setAppValue('core', 'public_'.$name, $app.'/'.$path);
584
+        }
585
+
586
+        OC_App::setAppTypes($info['id']);
587
+
588
+        if(isset($info['settings']) && is_array($info['settings'])) {
589
+            // requires that autoloading was registered for the app,
590
+            // as happens before running the install.php some lines above
591
+            \OC::$server->getSettingsManager()->setupSettings($info['settings']);
592
+        }
593
+
594
+        return $info['id'];
595
+    }
596
+
597
+    /**
598
+     * check the code of an app with some static code checks
599
+     * @param string $folder the folder of the app to check
600
+     * @return boolean true for app is o.k. and false for app is not o.k.
601
+     */
602
+    public static function checkCode($folder) {
603
+        // is the code checker enabled?
604
+        if(!\OC::$server->getConfig()->getSystemValue('appcodechecker', false)) {
605
+            return true;
606
+        }
607
+
608
+        $codeChecker = new CodeChecker(new PrivateCheck(new EmptyCheck()));
609
+        $errors = $codeChecker->analyseFolder(basename($folder), $folder);
610
+
611
+        return empty($errors);
612
+    }
613
+
614
+    /**
615
+     * @param string $script
616
+     */
617
+    private static function includeAppScript($script) {
618
+        if ( file_exists($script) ){
619
+            include $script;
620
+        }
621
+    }
622 622
 }
Please login to merge, or discard this patch.