Passed
Push — master ( 456412...602de2 )
by Joas
13:17 queued 10s
created
apps/dav/lib/CardDAV/Converter.php 1 patch
Indentation   +115 added lines, -115 removed lines patch added patch discarded remove patch
@@ -36,119 +36,119 @@
 block discarded – undo
36 36
 
37 37
 class Converter {
38 38
 
39
-	/** @var AccountManager */
40
-	private $accountManager;
41
-
42
-	/**
43
-	 * Converter constructor.
44
-	 *
45
-	 * @param AccountManager $accountManager
46
-	 */
47
-	public function __construct(AccountManager $accountManager) {
48
-		$this->accountManager = $accountManager;
49
-	}
50
-
51
-	/**
52
-	 * @param IUser $user
53
-	 * @return VCard|null
54
-	 */
55
-	public function createCardFromUser(IUser $user) {
56
-		$userData = $this->accountManager->getUser($user);
57
-
58
-		$uid = $user->getUID();
59
-		$cloudId = $user->getCloudId();
60
-		$image = $this->getAvatarImage($user);
61
-
62
-		$vCard = new VCard();
63
-		$vCard->VERSION = '3.0';
64
-		$vCard->UID = $uid;
65
-
66
-		$publish = false;
67
-
68
-		if ($image !== null && isset($userData[IAccountManager::PROPERTY_AVATAR])) {
69
-			$userData[IAccountManager::PROPERTY_AVATAR]['value'] = true;
70
-		}
71
-
72
-		foreach ($userData as $property => $value) {
73
-			$shareWithTrustedServers =
74
-				$value['scope'] === AccountManager::SCOPE_FEDERATED ||
75
-				$value['scope'] === AccountManager::SCOPE_PUBLISHED;
76
-
77
-			$emptyValue = !isset($value['value']) || $value['value'] === '';
78
-
79
-			if ($shareWithTrustedServers && !$emptyValue) {
80
-				$publish = true;
81
-				switch ($property) {
82
-					case IAccountManager::PROPERTY_DISPLAYNAME:
83
-						$vCard->add(new Text($vCard, 'FN', $value['value']));
84
-						$vCard->add(new Text($vCard, 'N', $this->splitFullName($value['value'])));
85
-						break;
86
-					case IAccountManager::PROPERTY_AVATAR:
87
-						if ($image !== null) {
88
-							$vCard->add('PHOTO', $image->data(), ['ENCODING' => 'b', 'TYPE' => $image->mimeType()]);
89
-						}
90
-						break;
91
-					case IAccountManager::PROPERTY_EMAIL:
92
-						$vCard->add(new Text($vCard, 'EMAIL', $value['value'], ['TYPE' => 'OTHER']));
93
-						break;
94
-					case IAccountManager::PROPERTY_WEBSITE:
95
-						$vCard->add(new Text($vCard, 'URL', $value['value']));
96
-						break;
97
-					case IAccountManager::PROPERTY_PHONE:
98
-						$vCard->add(new Text($vCard, 'TEL', $value['value'], ['TYPE' => 'OTHER']));
99
-						break;
100
-					case IAccountManager::PROPERTY_ADDRESS:
101
-						$vCard->add(new Text($vCard, 'ADR', $value['value'], ['TYPE' => 'OTHER']));
102
-						break;
103
-					case IAccountManager::PROPERTY_TWITTER:
104
-						$vCard->add(new Text($vCard, 'X-SOCIALPROFILE', $value['value'], ['TYPE' => 'TWITTER']));
105
-						break;
106
-				}
107
-			}
108
-		}
109
-
110
-		if ($publish && !empty($cloudId)) {
111
-			$vCard->add(new Text($vCard, 'CLOUD', $cloudId));
112
-			$vCard->validate();
113
-			return $vCard;
114
-		}
115
-
116
-		return null;
117
-	}
118
-
119
-	/**
120
-	 * @param string $fullName
121
-	 * @return string[]
122
-	 */
123
-	public function splitFullName($fullName) {
124
-		// Very basic western style parsing. I'm not gonna implement
125
-		// https://github.com/android/platform_packages_providers_contactsprovider/blob/master/src/com/android/providers/contacts/NameSplitter.java ;)
126
-
127
-		$elements = explode(' ', $fullName);
128
-		$result = ['', '', '', '', ''];
129
-		if (count($elements) > 2) {
130
-			$result[0] = implode(' ', array_slice($elements, count($elements) - 1));
131
-			$result[1] = $elements[0];
132
-			$result[2] = implode(' ', array_slice($elements, 1, count($elements) - 2));
133
-		} elseif (count($elements) === 2) {
134
-			$result[0] = $elements[1];
135
-			$result[1] = $elements[0];
136
-		} else {
137
-			$result[0] = $elements[0];
138
-		}
139
-
140
-		return $result;
141
-	}
142
-
143
-	/**
144
-	 * @param IUser $user
145
-	 * @return null|IImage
146
-	 */
147
-	private function getAvatarImage(IUser $user) {
148
-		try {
149
-			return $user->getAvatarImage(-1);
150
-		} catch (\Exception $ex) {
151
-			return null;
152
-		}
153
-	}
39
+    /** @var AccountManager */
40
+    private $accountManager;
41
+
42
+    /**
43
+     * Converter constructor.
44
+     *
45
+     * @param AccountManager $accountManager
46
+     */
47
+    public function __construct(AccountManager $accountManager) {
48
+        $this->accountManager = $accountManager;
49
+    }
50
+
51
+    /**
52
+     * @param IUser $user
53
+     * @return VCard|null
54
+     */
55
+    public function createCardFromUser(IUser $user) {
56
+        $userData = $this->accountManager->getUser($user);
57
+
58
+        $uid = $user->getUID();
59
+        $cloudId = $user->getCloudId();
60
+        $image = $this->getAvatarImage($user);
61
+
62
+        $vCard = new VCard();
63
+        $vCard->VERSION = '3.0';
64
+        $vCard->UID = $uid;
65
+
66
+        $publish = false;
67
+
68
+        if ($image !== null && isset($userData[IAccountManager::PROPERTY_AVATAR])) {
69
+            $userData[IAccountManager::PROPERTY_AVATAR]['value'] = true;
70
+        }
71
+
72
+        foreach ($userData as $property => $value) {
73
+            $shareWithTrustedServers =
74
+                $value['scope'] === AccountManager::SCOPE_FEDERATED ||
75
+                $value['scope'] === AccountManager::SCOPE_PUBLISHED;
76
+
77
+            $emptyValue = !isset($value['value']) || $value['value'] === '';
78
+
79
+            if ($shareWithTrustedServers && !$emptyValue) {
80
+                $publish = true;
81
+                switch ($property) {
82
+                    case IAccountManager::PROPERTY_DISPLAYNAME:
83
+                        $vCard->add(new Text($vCard, 'FN', $value['value']));
84
+                        $vCard->add(new Text($vCard, 'N', $this->splitFullName($value['value'])));
85
+                        break;
86
+                    case IAccountManager::PROPERTY_AVATAR:
87
+                        if ($image !== null) {
88
+                            $vCard->add('PHOTO', $image->data(), ['ENCODING' => 'b', 'TYPE' => $image->mimeType()]);
89
+                        }
90
+                        break;
91
+                    case IAccountManager::PROPERTY_EMAIL:
92
+                        $vCard->add(new Text($vCard, 'EMAIL', $value['value'], ['TYPE' => 'OTHER']));
93
+                        break;
94
+                    case IAccountManager::PROPERTY_WEBSITE:
95
+                        $vCard->add(new Text($vCard, 'URL', $value['value']));
96
+                        break;
97
+                    case IAccountManager::PROPERTY_PHONE:
98
+                        $vCard->add(new Text($vCard, 'TEL', $value['value'], ['TYPE' => 'OTHER']));
99
+                        break;
100
+                    case IAccountManager::PROPERTY_ADDRESS:
101
+                        $vCard->add(new Text($vCard, 'ADR', $value['value'], ['TYPE' => 'OTHER']));
102
+                        break;
103
+                    case IAccountManager::PROPERTY_TWITTER:
104
+                        $vCard->add(new Text($vCard, 'X-SOCIALPROFILE', $value['value'], ['TYPE' => 'TWITTER']));
105
+                        break;
106
+                }
107
+            }
108
+        }
109
+
110
+        if ($publish && !empty($cloudId)) {
111
+            $vCard->add(new Text($vCard, 'CLOUD', $cloudId));
112
+            $vCard->validate();
113
+            return $vCard;
114
+        }
115
+
116
+        return null;
117
+    }
118
+
119
+    /**
120
+     * @param string $fullName
121
+     * @return string[]
122
+     */
123
+    public function splitFullName($fullName) {
124
+        // Very basic western style parsing. I'm not gonna implement
125
+        // https://github.com/android/platform_packages_providers_contactsprovider/blob/master/src/com/android/providers/contacts/NameSplitter.java ;)
126
+
127
+        $elements = explode(' ', $fullName);
128
+        $result = ['', '', '', '', ''];
129
+        if (count($elements) > 2) {
130
+            $result[0] = implode(' ', array_slice($elements, count($elements) - 1));
131
+            $result[1] = $elements[0];
132
+            $result[2] = implode(' ', array_slice($elements, 1, count($elements) - 2));
133
+        } elseif (count($elements) === 2) {
134
+            $result[0] = $elements[1];
135
+            $result[1] = $elements[0];
136
+        } else {
137
+            $result[0] = $elements[0];
138
+        }
139
+
140
+        return $result;
141
+    }
142
+
143
+    /**
144
+     * @param IUser $user
145
+     * @return null|IImage
146
+     */
147
+    private function getAvatarImage(IUser $user) {
148
+        try {
149
+            return $user->getAvatarImage(-1);
150
+        } catch (\Exception $ex) {
151
+            return null;
152
+        }
153
+    }
154 154
 }
Please login to merge, or discard this patch.
apps/settings/templates/settings/personal/personal.info.php 1 patch
Indentation   +62 added lines, -62 removed lines patch added patch discarded remove patch
@@ -26,11 +26,11 @@  discard block
 block discarded – undo
26 26
 /** @var array $_ */
27 27
 
28 28
 script('settings', [
29
-	'usersettings',
30
-	'templates',
31
-	'federationsettingsview',
32
-	'federationscopemenu',
33
-	'settings/personalInfo',
29
+    'usersettings',
30
+    'templates',
31
+    'federationsettingsview',
32
+    'federationscopemenu',
33
+    'settings/personalInfo',
34 34
 ]);
35 35
 ?>
36 36
 
@@ -84,10 +84,10 @@  discard block
 block discarded – undo
84 84
 					<p class="quotatext">
85 85
 						<?php if ($_['quota'] === \OCP\Files\FileInfo::SPACE_UNLIMITED): ?>
86 86
 							<?php print_unescaped($l->t('You are using <strong>%s</strong>',
87
-								[$_['usage']]));?>
87
+                                [$_['usage']]));?>
88 88
 						<?php else: ?>
89 89
 							<?php print_unescaped($l->t('You are using <strong>%1$s</strong> of <strong>%2$s</strong> (<strong>%3$s %%</strong>)',
90
-								[$_['usage'], $_['total_space'],  $_['usage_relative']]));?>
90
+                                [$_['usage'], $_['total_space'],  $_['usage_relative']]));?>
91 91
 						<?php endif ?>
92 92
 					</p>
93 93
 				</div>
@@ -109,16 +109,16 @@  discard block
 block discarded – undo
109 109
 				</h3>
110 110
 				<input type="text" id="displayname" name="displayname"
111 111
 					<?php if (!$_['displayNameChangeSupported']) {
112
-									print_unescaped('class="hidden"');
113
-								} ?>
112
+                                    print_unescaped('class="hidden"');
113
+                                } ?>
114 114
 					   value="<?php p($_['displayName']) ?>"
115 115
 					   autocomplete="on" autocapitalize="none" autocorrect="off" />
116 116
 				<?php if (!$_['displayNameChangeSupported']) { ?>
117 117
 					<span><?php if (isset($_['displayName']) && !empty($_['displayName'])) {
118
-									p($_['displayName']);
119
-								} else {
120
-									p($l->t('No display name set'));
121
-								} ?></span>
118
+                                    p($_['displayName']);
119
+                                } else {
120
+                                    p($l->t('No display name set'));
121
+                                } ?></span>
122 122
 				<?php } ?>
123 123
 				<span class="icon-checkmark hidden"></span>
124 124
 				<span class="icon-error hidden" ></span>
@@ -138,36 +138,36 @@  discard block
 block discarded – undo
138 138
 					</div>
139 139
 				</h3>
140 140
 				<div class="verify <?php if ($_['email'] === '' || $_['emailScope'] !== 'public') {
141
-									p('hidden');
142
-								} ?>">
141
+                                    p('hidden');
142
+                                } ?>">
143 143
 					<img id="verify-email" title="<?php p($_['emailMessage']); ?>" data-status="<?php p($_['emailVerification']) ?>" src="
144 144
 				<?php
145
-					switch ($_['emailVerification']) {
146
-						case \OC\Accounts\AccountManager::VERIFICATION_IN_PROGRESS:
147
-							p(image_path('core', 'actions/verifying.svg'));
148
-							break;
149
-						case \OC\Accounts\AccountManager::VERIFIED:
150
-							p(image_path('core', 'actions/verified.svg'));
151
-							break;
152
-						default:
153
-							p(image_path('core', 'actions/verify.svg'));
154
-					}
155
-					?>">
145
+                    switch ($_['emailVerification']) {
146
+                        case \OC\Accounts\AccountManager::VERIFICATION_IN_PROGRESS:
147
+                            p(image_path('core', 'actions/verifying.svg'));
148
+                            break;
149
+                        case \OC\Accounts\AccountManager::VERIFIED:
150
+                            p(image_path('core', 'actions/verified.svg'));
151
+                            break;
152
+                        default:
153
+                            p(image_path('core', 'actions/verify.svg'));
154
+                    }
155
+                    ?>">
156 156
 				</div>
157 157
 				<input type="email" name="email" id="email" value="<?php p($_['email']); ?>"
158 158
 					<?php if (!$_['displayNameChangeSupported']) {
159
-						print_unescaped('class="hidden"');
160
-					} ?>
159
+                        print_unescaped('class="hidden"');
160
+                    } ?>
161 161
 					   placeholder="<?php p($l->t('Your email address')); ?>"
162 162
 					   autocomplete="on" autocapitalize="none" autocorrect="off" />
163 163
 				<span class="icon-checkmark hidden"></span>
164 164
 				<span class="icon-error hidden" ></span>
165 165
 				<?php if (!$_['displayNameChangeSupported']) { ?>
166 166
 					<span><?php if (isset($_['email']) && !empty($_['email'])) {
167
-						p($_['email']);
168
-					} else {
169
-						p($l->t('No email address set'));
170
-					}?></span>
167
+                        p($_['email']);
168
+                    } else {
169
+                        p($l->t('No email address set'));
170
+                    }?></span>
171 171
 				<?php } ?>
172 172
 				<?php if ($_['displayNameChangeSupported']) { ?>
173 173
 					<em><?php p($l->t('For password reset and notifications')); ?></em>
@@ -227,24 +227,24 @@  discard block
 block discarded – undo
227 227
 				</h3>
228 228
 				<?php if ($_['lookupServerUploadEnabled']) { ?>
229 229
 				<div class="verify <?php if ($_['website'] === '' || $_['websiteScope'] !== 'public') {
230
-						p('hidden');
231
-					} ?>">
230
+                        p('hidden');
231
+                    } ?>">
232 232
 					<img id="verify-website" title="<?php p($_['websiteMessage']); ?>" data-status="<?php p($_['websiteVerification']) ?>" src="
233 233
 					<?php
234
-					switch ($_['websiteVerification']) {
235
-						case \OC\Accounts\AccountManager::VERIFICATION_IN_PROGRESS:
236
-							p(image_path('core', 'actions/verifying.svg'));
237
-							break;
238
-						case \OC\Accounts\AccountManager::VERIFIED:
239
-							p(image_path('core', 'actions/verified.svg'));
240
-							break;
241
-						default:
242
-							p(image_path('core', 'actions/verify.svg'));
243
-					}
244
-					?>"
234
+                    switch ($_['websiteVerification']) {
235
+                        case \OC\Accounts\AccountManager::VERIFICATION_IN_PROGRESS:
236
+                            p(image_path('core', 'actions/verifying.svg'));
237
+                            break;
238
+                        case \OC\Accounts\AccountManager::VERIFIED:
239
+                            p(image_path('core', 'actions/verified.svg'));
240
+                            break;
241
+                        default:
242
+                            p(image_path('core', 'actions/verify.svg'));
243
+                    }
244
+                    ?>"
245 245
 					<?php if ($_['websiteVerification'] === \OC\Accounts\AccountManager::VERIFICATION_IN_PROGRESS || $_['websiteVerification'] === \OC\Accounts\AccountManager::NOT_VERIFIED) {
246
-						print_unescaped(' class="verify-action"');
247
-					} ?>
246
+                        print_unescaped(' class="verify-action"');
247
+                    } ?>
248 248
 					>
249 249
 					<div class="verification-dialog popovermenu bubble menu">
250 250
 						<div class="verification-dialog-content">
@@ -276,24 +276,24 @@  discard block
 block discarded – undo
276 276
 				</h3>
277 277
 				<?php if ($_['lookupServerUploadEnabled']) { ?>
278 278
 				<div class="verify <?php if ($_['twitter'] === '' || $_['twitterScope'] !== 'public') {
279
-						p('hidden');
280
-					} ?>">
279
+                        p('hidden');
280
+                    } ?>">
281 281
 					<img id="verify-twitter" title="<?php p($_['twitterMessage']); ?>" data-status="<?php p($_['twitterVerification']) ?>" src="
282 282
 					<?php
283
-					switch ($_['twitterVerification']) {
284
-						case \OC\Accounts\AccountManager::VERIFICATION_IN_PROGRESS:
285
-							p(image_path('core', 'actions/verifying.svg'));
286
-							break;
287
-						case \OC\Accounts\AccountManager::VERIFIED:
288
-							p(image_path('core', 'actions/verified.svg'));
289
-							break;
290
-						default:
291
-							p(image_path('core', 'actions/verify.svg'));
292
-					}
293
-					?>"
283
+                    switch ($_['twitterVerification']) {
284
+                        case \OC\Accounts\AccountManager::VERIFICATION_IN_PROGRESS:
285
+                            p(image_path('core', 'actions/verifying.svg'));
286
+                            break;
287
+                        case \OC\Accounts\AccountManager::VERIFIED:
288
+                            p(image_path('core', 'actions/verified.svg'));
289
+                            break;
290
+                        default:
291
+                            p(image_path('core', 'actions/verify.svg'));
292
+                    }
293
+                    ?>"
294 294
 					<?php if ($_['twitterVerification'] === \OC\Accounts\AccountManager::VERIFICATION_IN_PROGRESS || $_['twitterVerification'] === \OC\Accounts\AccountManager::NOT_VERIFIED) {
295
-						print_unescaped(' class="verify-action"');
296
-					} ?>
295
+                        print_unescaped(' class="verify-action"');
296
+                    } ?>
297 297
 					>
298 298
 					<div class="verification-dialog popovermenu bubble menu">
299 299
 						<div class="verification-dialog-content">
Please login to merge, or discard this patch.
apps/settings/lib/Settings/Personal/PersonalInfo.php 1 patch
Indentation   +232 added lines, -232 removed lines patch added patch discarded remove patch
@@ -53,236 +53,236 @@
 block discarded – undo
53 53
 
54 54
 class PersonalInfo implements ISettings {
55 55
 
56
-	/** @var IConfig */
57
-	private $config;
58
-	/** @var IUserManager */
59
-	private $userManager;
60
-	/** @var AccountManager */
61
-	private $accountManager;
62
-	/** @var IGroupManager */
63
-	private $groupManager;
64
-	/** @var IAppManager */
65
-	private $appManager;
66
-	/** @var IFactory */
67
-	private $l10nFactory;
68
-	/** @var IL10N */
69
-	private $l;
70
-
71
-	public function __construct(
72
-		IConfig $config,
73
-		IUserManager $userManager,
74
-		IGroupManager $groupManager,
75
-		AccountManager $accountManager,
76
-		IAppManager $appManager,
77
-		IFactory $l10nFactory,
78
-		IL10N $l
79
-	) {
80
-		$this->config = $config;
81
-		$this->userManager = $userManager;
82
-		$this->accountManager = $accountManager;
83
-		$this->groupManager = $groupManager;
84
-		$this->appManager = $appManager;
85
-		$this->l10nFactory = $l10nFactory;
86
-		$this->l = $l;
87
-	}
88
-
89
-	public function getForm(): TemplateResponse {
90
-		$federatedFileSharingEnabled = $this->appManager->isEnabledForUser('federatedfilesharing');
91
-		$lookupServerUploadEnabled = false;
92
-		if ($federatedFileSharingEnabled) {
93
-			/** @var FederatedShareProvider $shareProvider */
94
-			$shareProvider = \OC::$server->query(FederatedShareProvider::class);
95
-			$lookupServerUploadEnabled = $shareProvider->isLookupServerUploadEnabled();
96
-		}
97
-
98
-		$uid = \OC_User::getUser();
99
-		$user = $this->userManager->get($uid);
100
-		$account = $this->accountManager->getAccount($user);
101
-
102
-		// make sure FS is setup before querying storage related stuff...
103
-		\OC_Util::setupFS($user->getUID());
104
-
105
-		$storageInfo = \OC_Helper::getStorageInfo('/');
106
-		if ($storageInfo['quota'] === FileInfo::SPACE_UNLIMITED) {
107
-			$totalSpace = $this->l->t('Unlimited');
108
-		} else {
109
-			$totalSpace = \OC_Helper::humanFileSize($storageInfo['total']);
110
-		}
111
-
112
-		$languageParameters = $this->getLanguages($user);
113
-		$localeParameters = $this->getLocales($user);
114
-		$messageParameters = $this->getMessageParameters($account);
115
-
116
-		$parameters = [
117
-			'total_space' => $totalSpace,
118
-			'usage' => \OC_Helper::humanFileSize($storageInfo['used']),
119
-			'usage_relative' => round($storageInfo['relative']),
120
-			'quota' => $storageInfo['quota'],
121
-			'avatarChangeSupported' => $user->canChangeAvatar(),
122
-			'lookupServerUploadEnabled' => $lookupServerUploadEnabled,
123
-			'avatarScope' => $account->getProperty(IAccountManager::PROPERTY_AVATAR)->getScope(),
124
-			'displayNameChangeSupported' => $user->canChangeDisplayName(),
125
-			'displayName' => $account->getProperty(IAccountManager::PROPERTY_DISPLAYNAME)->getValue(),
126
-			'displayNameScope' => $account->getProperty(IAccountManager::PROPERTY_DISPLAYNAME)->getScope(),
127
-			'email' => $account->getProperty(IAccountManager::PROPERTY_EMAIL)->getValue(),
128
-			'emailScope' => $account->getProperty(IAccountManager::PROPERTY_EMAIL)->getScope(),
129
-			'emailVerification' => $account->getProperty(IAccountManager::PROPERTY_EMAIL)->getVerified(),
130
-			'phone' => $account->getProperty(IAccountManager::PROPERTY_PHONE)->getValue(),
131
-			'phoneScope' => $account->getProperty(IAccountManager::PROPERTY_PHONE)->getScope(),
132
-			'address' => $account->getProperty(IAccountManager::PROPERTY_ADDRESS)->getValue(),
133
-			'addressScope' => $account->getProperty(IAccountManager::PROPERTY_ADDRESS)->getScope(),
134
-			'website' => $account->getProperty(IAccountManager::PROPERTY_WEBSITE)->getValue(),
135
-			'websiteScope' => $account->getProperty(IAccountManager::PROPERTY_WEBSITE)->getScope(),
136
-			'websiteVerification' => $account->getProperty(IAccountManager::PROPERTY_WEBSITE)->getVerified(),
137
-			'twitter' => $account->getProperty(IAccountManager::PROPERTY_TWITTER)->getValue(),
138
-			'twitterScope' => $account->getProperty(IAccountManager::PROPERTY_TWITTER)->getScope(),
139
-			'twitterVerification' => $account->getProperty(IAccountManager::PROPERTY_TWITTER)->getVerified(),
140
-			'groups' => $this->getGroups($user),
141
-		] + $messageParameters + $languageParameters + $localeParameters;
142
-
143
-
144
-		return new TemplateResponse('settings', 'settings/personal/personal.info', $parameters, '');
145
-	}
146
-
147
-	/**
148
-	 * @return string the section ID, e.g. 'sharing'
149
-	 * @since 9.1
150
-	 */
151
-	public function getSection(): string {
152
-		return 'personal-info';
153
-	}
154
-
155
-	/**
156
-	 * @return int whether the form should be rather on the top or bottom of
157
-	 * the admin section. The forms are arranged in ascending order of the
158
-	 * priority values. It is required to return a value between 0 and 100.
159
-	 *
160
-	 * E.g.: 70
161
-	 * @since 9.1
162
-	 */
163
-	public function getPriority(): int {
164
-		return 10;
165
-	}
166
-
167
-	/**
168
-	 * returns a sorted list of the user's group GIDs
169
-	 *
170
-	 * @param IUser $user
171
-	 * @return array
172
-	 */
173
-	private function getGroups(IUser $user): array {
174
-		$groups = array_map(
175
-			static function (IGroup $group) {
176
-				return $group->getDisplayName();
177
-			},
178
-			$this->groupManager->getUserGroups($user)
179
-		);
180
-		sort($groups);
181
-
182
-		return $groups;
183
-	}
184
-
185
-	/**
186
-	 * returns the user language, common language and other languages in an
187
-	 * associative array
188
-	 *
189
-	 * @param IUser $user
190
-	 * @return array
191
-	 */
192
-	private function getLanguages(IUser $user): array {
193
-		$forceLanguage = $this->config->getSystemValue('force_language', false);
194
-		if ($forceLanguage !== false) {
195
-			return [];
196
-		}
197
-
198
-		$uid = $user->getUID();
199
-
200
-		$userConfLang = $this->config->getUserValue($uid, 'core', 'lang', $this->l10nFactory->findLanguage());
201
-		$languages = $this->l10nFactory->getLanguages();
202
-
203
-		// associate the user language with the proper array
204
-		$userLangIndex = array_search($userConfLang, array_column($languages['commonlanguages'], 'code'));
205
-		$userLang = $languages['commonlanguages'][$userLangIndex];
206
-		// search in the other languages
207
-		if ($userLangIndex === false) {
208
-			$userLangIndex = array_search($userConfLang, array_column($languages['languages'], 'code'));
209
-			$userLang = $languages['languages'][$userLangIndex];
210
-		}
211
-		// if user language is not available but set somehow: show the actual code as name
212
-		if (!is_array($userLang)) {
213
-			$userLang = [
214
-				'code' => $userConfLang,
215
-				'name' => $userConfLang,
216
-			];
217
-		}
218
-
219
-		return array_merge(
220
-			['activelanguage' => $userLang],
221
-			$languages
222
-		);
223
-	}
224
-
225
-	private function getLocales(IUser $user): array {
226
-		$forceLanguage = $this->config->getSystemValue('force_locale', false);
227
-		if ($forceLanguage !== false) {
228
-			return [];
229
-		}
230
-
231
-		$uid = $user->getUID();
232
-
233
-		$userLocaleString = $this->config->getUserValue($uid, 'core', 'locale', $this->l10nFactory->findLocale());
234
-
235
-		$userLang = $this->config->getUserValue($uid, 'core', 'lang', $this->l10nFactory->findLanguage());
236
-
237
-		$localeCodes = $this->l10nFactory->findAvailableLocales();
238
-
239
-		$userLocale = array_filter($localeCodes, function ($value) use ($userLocaleString) {
240
-			return $userLocaleString === $value['code'];
241
-		});
242
-
243
-		if (!empty($userLocale)) {
244
-			$userLocale = reset($userLocale);
245
-		}
246
-
247
-		$localesForLanguage = array_filter($localeCodes, function ($localeCode) use ($userLang) {
248
-			return 0 === strpos($localeCode['code'], $userLang);
249
-		});
250
-
251
-		if (!$userLocale) {
252
-			$userLocale = [
253
-				'code' => 'en',
254
-				'name' => 'English'
255
-			];
256
-		}
257
-
258
-		return [
259
-			'activelocaleLang' => $userLocaleString,
260
-			'activelocale' => $userLocale,
261
-			'locales' => $localeCodes,
262
-			'localesForLanguage' => $localesForLanguage,
263
-		];
264
-	}
265
-
266
-	/**
267
-	 * @param IAccount $account
268
-	 * @return array
269
-	 */
270
-	private function getMessageParameters(IAccount $account): array {
271
-		$needVerifyMessage = [IAccountManager::PROPERTY_EMAIL, IAccountManager::PROPERTY_WEBSITE, IAccountManager::PROPERTY_TWITTER];
272
-		$messageParameters = [];
273
-		foreach ($needVerifyMessage as $property) {
274
-			switch ($account->getProperty($property)->getVerified()) {
275
-				case AccountManager::VERIFIED:
276
-					$message = $this->l->t('Verifying');
277
-					break;
278
-				case AccountManager::VERIFICATION_IN_PROGRESS:
279
-					$message = $this->l->t('Verifying …');
280
-					break;
281
-				default:
282
-					$message = $this->l->t('Verify');
283
-			}
284
-			$messageParameters[$property . 'Message'] = $message;
285
-		}
286
-		return $messageParameters;
287
-	}
56
+    /** @var IConfig */
57
+    private $config;
58
+    /** @var IUserManager */
59
+    private $userManager;
60
+    /** @var AccountManager */
61
+    private $accountManager;
62
+    /** @var IGroupManager */
63
+    private $groupManager;
64
+    /** @var IAppManager */
65
+    private $appManager;
66
+    /** @var IFactory */
67
+    private $l10nFactory;
68
+    /** @var IL10N */
69
+    private $l;
70
+
71
+    public function __construct(
72
+        IConfig $config,
73
+        IUserManager $userManager,
74
+        IGroupManager $groupManager,
75
+        AccountManager $accountManager,
76
+        IAppManager $appManager,
77
+        IFactory $l10nFactory,
78
+        IL10N $l
79
+    ) {
80
+        $this->config = $config;
81
+        $this->userManager = $userManager;
82
+        $this->accountManager = $accountManager;
83
+        $this->groupManager = $groupManager;
84
+        $this->appManager = $appManager;
85
+        $this->l10nFactory = $l10nFactory;
86
+        $this->l = $l;
87
+    }
88
+
89
+    public function getForm(): TemplateResponse {
90
+        $federatedFileSharingEnabled = $this->appManager->isEnabledForUser('federatedfilesharing');
91
+        $lookupServerUploadEnabled = false;
92
+        if ($federatedFileSharingEnabled) {
93
+            /** @var FederatedShareProvider $shareProvider */
94
+            $shareProvider = \OC::$server->query(FederatedShareProvider::class);
95
+            $lookupServerUploadEnabled = $shareProvider->isLookupServerUploadEnabled();
96
+        }
97
+
98
+        $uid = \OC_User::getUser();
99
+        $user = $this->userManager->get($uid);
100
+        $account = $this->accountManager->getAccount($user);
101
+
102
+        // make sure FS is setup before querying storage related stuff...
103
+        \OC_Util::setupFS($user->getUID());
104
+
105
+        $storageInfo = \OC_Helper::getStorageInfo('/');
106
+        if ($storageInfo['quota'] === FileInfo::SPACE_UNLIMITED) {
107
+            $totalSpace = $this->l->t('Unlimited');
108
+        } else {
109
+            $totalSpace = \OC_Helper::humanFileSize($storageInfo['total']);
110
+        }
111
+
112
+        $languageParameters = $this->getLanguages($user);
113
+        $localeParameters = $this->getLocales($user);
114
+        $messageParameters = $this->getMessageParameters($account);
115
+
116
+        $parameters = [
117
+            'total_space' => $totalSpace,
118
+            'usage' => \OC_Helper::humanFileSize($storageInfo['used']),
119
+            'usage_relative' => round($storageInfo['relative']),
120
+            'quota' => $storageInfo['quota'],
121
+            'avatarChangeSupported' => $user->canChangeAvatar(),
122
+            'lookupServerUploadEnabled' => $lookupServerUploadEnabled,
123
+            'avatarScope' => $account->getProperty(IAccountManager::PROPERTY_AVATAR)->getScope(),
124
+            'displayNameChangeSupported' => $user->canChangeDisplayName(),
125
+            'displayName' => $account->getProperty(IAccountManager::PROPERTY_DISPLAYNAME)->getValue(),
126
+            'displayNameScope' => $account->getProperty(IAccountManager::PROPERTY_DISPLAYNAME)->getScope(),
127
+            'email' => $account->getProperty(IAccountManager::PROPERTY_EMAIL)->getValue(),
128
+            'emailScope' => $account->getProperty(IAccountManager::PROPERTY_EMAIL)->getScope(),
129
+            'emailVerification' => $account->getProperty(IAccountManager::PROPERTY_EMAIL)->getVerified(),
130
+            'phone' => $account->getProperty(IAccountManager::PROPERTY_PHONE)->getValue(),
131
+            'phoneScope' => $account->getProperty(IAccountManager::PROPERTY_PHONE)->getScope(),
132
+            'address' => $account->getProperty(IAccountManager::PROPERTY_ADDRESS)->getValue(),
133
+            'addressScope' => $account->getProperty(IAccountManager::PROPERTY_ADDRESS)->getScope(),
134
+            'website' => $account->getProperty(IAccountManager::PROPERTY_WEBSITE)->getValue(),
135
+            'websiteScope' => $account->getProperty(IAccountManager::PROPERTY_WEBSITE)->getScope(),
136
+            'websiteVerification' => $account->getProperty(IAccountManager::PROPERTY_WEBSITE)->getVerified(),
137
+            'twitter' => $account->getProperty(IAccountManager::PROPERTY_TWITTER)->getValue(),
138
+            'twitterScope' => $account->getProperty(IAccountManager::PROPERTY_TWITTER)->getScope(),
139
+            'twitterVerification' => $account->getProperty(IAccountManager::PROPERTY_TWITTER)->getVerified(),
140
+            'groups' => $this->getGroups($user),
141
+        ] + $messageParameters + $languageParameters + $localeParameters;
142
+
143
+
144
+        return new TemplateResponse('settings', 'settings/personal/personal.info', $parameters, '');
145
+    }
146
+
147
+    /**
148
+     * @return string the section ID, e.g. 'sharing'
149
+     * @since 9.1
150
+     */
151
+    public function getSection(): string {
152
+        return 'personal-info';
153
+    }
154
+
155
+    /**
156
+     * @return int whether the form should be rather on the top or bottom of
157
+     * the admin section. The forms are arranged in ascending order of the
158
+     * priority values. It is required to return a value between 0 and 100.
159
+     *
160
+     * E.g.: 70
161
+     * @since 9.1
162
+     */
163
+    public function getPriority(): int {
164
+        return 10;
165
+    }
166
+
167
+    /**
168
+     * returns a sorted list of the user's group GIDs
169
+     *
170
+     * @param IUser $user
171
+     * @return array
172
+     */
173
+    private function getGroups(IUser $user): array {
174
+        $groups = array_map(
175
+            static function (IGroup $group) {
176
+                return $group->getDisplayName();
177
+            },
178
+            $this->groupManager->getUserGroups($user)
179
+        );
180
+        sort($groups);
181
+
182
+        return $groups;
183
+    }
184
+
185
+    /**
186
+     * returns the user language, common language and other languages in an
187
+     * associative array
188
+     *
189
+     * @param IUser $user
190
+     * @return array
191
+     */
192
+    private function getLanguages(IUser $user): array {
193
+        $forceLanguage = $this->config->getSystemValue('force_language', false);
194
+        if ($forceLanguage !== false) {
195
+            return [];
196
+        }
197
+
198
+        $uid = $user->getUID();
199
+
200
+        $userConfLang = $this->config->getUserValue($uid, 'core', 'lang', $this->l10nFactory->findLanguage());
201
+        $languages = $this->l10nFactory->getLanguages();
202
+
203
+        // associate the user language with the proper array
204
+        $userLangIndex = array_search($userConfLang, array_column($languages['commonlanguages'], 'code'));
205
+        $userLang = $languages['commonlanguages'][$userLangIndex];
206
+        // search in the other languages
207
+        if ($userLangIndex === false) {
208
+            $userLangIndex = array_search($userConfLang, array_column($languages['languages'], 'code'));
209
+            $userLang = $languages['languages'][$userLangIndex];
210
+        }
211
+        // if user language is not available but set somehow: show the actual code as name
212
+        if (!is_array($userLang)) {
213
+            $userLang = [
214
+                'code' => $userConfLang,
215
+                'name' => $userConfLang,
216
+            ];
217
+        }
218
+
219
+        return array_merge(
220
+            ['activelanguage' => $userLang],
221
+            $languages
222
+        );
223
+    }
224
+
225
+    private function getLocales(IUser $user): array {
226
+        $forceLanguage = $this->config->getSystemValue('force_locale', false);
227
+        if ($forceLanguage !== false) {
228
+            return [];
229
+        }
230
+
231
+        $uid = $user->getUID();
232
+
233
+        $userLocaleString = $this->config->getUserValue($uid, 'core', 'locale', $this->l10nFactory->findLocale());
234
+
235
+        $userLang = $this->config->getUserValue($uid, 'core', 'lang', $this->l10nFactory->findLanguage());
236
+
237
+        $localeCodes = $this->l10nFactory->findAvailableLocales();
238
+
239
+        $userLocale = array_filter($localeCodes, function ($value) use ($userLocaleString) {
240
+            return $userLocaleString === $value['code'];
241
+        });
242
+
243
+        if (!empty($userLocale)) {
244
+            $userLocale = reset($userLocale);
245
+        }
246
+
247
+        $localesForLanguage = array_filter($localeCodes, function ($localeCode) use ($userLang) {
248
+            return 0 === strpos($localeCode['code'], $userLang);
249
+        });
250
+
251
+        if (!$userLocale) {
252
+            $userLocale = [
253
+                'code' => 'en',
254
+                'name' => 'English'
255
+            ];
256
+        }
257
+
258
+        return [
259
+            'activelocaleLang' => $userLocaleString,
260
+            'activelocale' => $userLocale,
261
+            'locales' => $localeCodes,
262
+            'localesForLanguage' => $localesForLanguage,
263
+        ];
264
+    }
265
+
266
+    /**
267
+     * @param IAccount $account
268
+     * @return array
269
+     */
270
+    private function getMessageParameters(IAccount $account): array {
271
+        $needVerifyMessage = [IAccountManager::PROPERTY_EMAIL, IAccountManager::PROPERTY_WEBSITE, IAccountManager::PROPERTY_TWITTER];
272
+        $messageParameters = [];
273
+        foreach ($needVerifyMessage as $property) {
274
+            switch ($account->getProperty($property)->getVerified()) {
275
+                case AccountManager::VERIFIED:
276
+                    $message = $this->l->t('Verifying');
277
+                    break;
278
+                case AccountManager::VERIFICATION_IN_PROGRESS:
279
+                    $message = $this->l->t('Verifying …');
280
+                    break;
281
+                default:
282
+                    $message = $this->l->t('Verify');
283
+            }
284
+            $messageParameters[$property . 'Message'] = $message;
285
+        }
286
+        return $messageParameters;
287
+    }
288 288
 }
Please login to merge, or discard this patch.
apps/settings/lib/Controller/UsersController.php 1 patch
Indentation   +510 added lines, -510 removed lines patch added patch discarded remove patch
@@ -70,514 +70,514 @@
 block discarded – undo
70 70
 use function in_array;
71 71
 
72 72
 class UsersController extends Controller {
73
-	/** @var UserManager */
74
-	private $userManager;
75
-	/** @var GroupManager */
76
-	private $groupManager;
77
-	/** @var IUserSession */
78
-	private $userSession;
79
-	/** @var IConfig */
80
-	private $config;
81
-	/** @var bool */
82
-	private $isAdmin;
83
-	/** @var IL10N */
84
-	private $l10n;
85
-	/** @var IMailer */
86
-	private $mailer;
87
-	/** @var Factory */
88
-	private $l10nFactory;
89
-	/** @var IAppManager */
90
-	private $appManager;
91
-	/** @var AccountManager */
92
-	private $accountManager;
93
-	/** @var Manager */
94
-	private $keyManager;
95
-	/** @var IJobList */
96
-	private $jobList;
97
-	/** @var IManager */
98
-	private $encryptionManager;
99
-	/** @var KnownUserService */
100
-	private $knownUserService;
101
-	/** @var IEventDispatcher */
102
-	private $dispatcher;
103
-
104
-
105
-	public function __construct(
106
-		string $appName,
107
-		IRequest $request,
108
-		IUserManager $userManager,
109
-		IGroupManager $groupManager,
110
-		IUserSession $userSession,
111
-		IConfig $config,
112
-		bool $isAdmin,
113
-		IL10N $l10n,
114
-		IMailer $mailer,
115
-		IFactory $l10nFactory,
116
-		IAppManager $appManager,
117
-		AccountManager $accountManager,
118
-		Manager $keyManager,
119
-		IJobList $jobList,
120
-		IManager $encryptionManager,
121
-		KnownUserService $knownUserService,
122
-		IEventDispatcher $dispatcher
123
-	) {
124
-		parent::__construct($appName, $request);
125
-		$this->userManager = $userManager;
126
-		$this->groupManager = $groupManager;
127
-		$this->userSession = $userSession;
128
-		$this->config = $config;
129
-		$this->isAdmin = $isAdmin;
130
-		$this->l10n = $l10n;
131
-		$this->mailer = $mailer;
132
-		$this->l10nFactory = $l10nFactory;
133
-		$this->appManager = $appManager;
134
-		$this->accountManager = $accountManager;
135
-		$this->keyManager = $keyManager;
136
-		$this->jobList = $jobList;
137
-		$this->encryptionManager = $encryptionManager;
138
-		$this->knownUserService = $knownUserService;
139
-		$this->dispatcher = $dispatcher;
140
-	}
141
-
142
-
143
-	/**
144
-	 * @NoCSRFRequired
145
-	 * @NoAdminRequired
146
-	 *
147
-	 * Display users list template
148
-	 *
149
-	 * @return TemplateResponse
150
-	 */
151
-	public function usersListByGroup(): TemplateResponse {
152
-		return $this->usersList();
153
-	}
154
-
155
-	/**
156
-	 * @NoCSRFRequired
157
-	 * @NoAdminRequired
158
-	 *
159
-	 * Display users list template
160
-	 *
161
-	 * @return TemplateResponse
162
-	 */
163
-	public function usersList(): TemplateResponse {
164
-		$user = $this->userSession->getUser();
165
-		$uid = $user->getUID();
166
-
167
-		\OC::$server->getNavigationManager()->setActiveEntry('core_users');
168
-
169
-		/* SORT OPTION: SORT_USERCOUNT or SORT_GROUPNAME */
170
-		$sortGroupsBy = \OC\Group\MetaData::SORT_USERCOUNT;
171
-		$isLDAPUsed = false;
172
-		if ($this->config->getSystemValue('sort_groups_by_name', false)) {
173
-			$sortGroupsBy = \OC\Group\MetaData::SORT_GROUPNAME;
174
-		} else {
175
-			if ($this->appManager->isEnabledForUser('user_ldap')) {
176
-				$isLDAPUsed =
177
-					$this->groupManager->isBackendUsed('\OCA\User_LDAP\Group_Proxy');
178
-				if ($isLDAPUsed) {
179
-					// LDAP user count can be slow, so we sort by group name here
180
-					$sortGroupsBy = \OC\Group\MetaData::SORT_GROUPNAME;
181
-				}
182
-			}
183
-		}
184
-
185
-		$canChangePassword = $this->canAdminChangeUserPasswords();
186
-
187
-		/* GROUPS */
188
-		$groupsInfo = new \OC\Group\MetaData(
189
-			$uid,
190
-			$this->isAdmin,
191
-			$this->groupManager,
192
-			$this->userSession
193
-		);
194
-
195
-		$groupsInfo->setSorting($sortGroupsBy);
196
-		[$adminGroup, $groups] = $groupsInfo->get();
197
-
198
-		if (!$isLDAPUsed && $this->appManager->isEnabledForUser('user_ldap')) {
199
-			$isLDAPUsed = (bool)array_reduce($this->userManager->getBackends(), function ($ldapFound, $backend) {
200
-				return $ldapFound || $backend instanceof User_Proxy;
201
-			});
202
-		}
203
-
204
-		$disabledUsers = -1;
205
-		$userCount = 0;
206
-
207
-		if (!$isLDAPUsed) {
208
-			if ($this->isAdmin) {
209
-				$disabledUsers = $this->userManager->countDisabledUsers();
210
-				$userCount = array_reduce($this->userManager->countUsers(), function ($v, $w) {
211
-					return $v + (int)$w;
212
-				}, 0);
213
-			} else {
214
-				// User is subadmin !
215
-				// Map group list to names to retrieve the countDisabledUsersOfGroups
216
-				$userGroups = $this->groupManager->getUserGroups($user);
217
-				$groupsNames = [];
218
-
219
-				foreach ($groups as $key => $group) {
220
-					// $userCount += (int)$group['usercount'];
221
-					array_push($groupsNames, $group['name']);
222
-					// we prevent subadmins from looking up themselves
223
-					// so we lower the count of the groups he belongs to
224
-					if (array_key_exists($group['id'], $userGroups)) {
225
-						$groups[$key]['usercount']--;
226
-						$userCount -= 1; // we also lower from one the total count
227
-					}
228
-				}
229
-				$userCount += $this->userManager->countUsersOfGroups($groupsInfo->getGroups());
230
-				$disabledUsers = $this->userManager->countDisabledUsersOfGroups($groupsNames);
231
-			}
232
-
233
-			$userCount -= $disabledUsers;
234
-		}
235
-
236
-		$disabledUsersGroup = [
237
-			'id' => 'disabled',
238
-			'name' => 'Disabled users',
239
-			'usercount' => $disabledUsers
240
-		];
241
-
242
-		/* QUOTAS PRESETS */
243
-		$quotaPreset = $this->parseQuotaPreset($this->config->getAppValue('files', 'quota_preset', '1 GB, 5 GB, 10 GB'));
244
-		$defaultQuota = $this->config->getAppValue('files', 'default_quota', 'none');
245
-
246
-		$event = new BeforeTemplateRenderedEvent();
247
-		$this->dispatcher->dispatch('OC\Settings\Users::loadAdditionalScripts', $event);
248
-		$this->dispatcher->dispatchTyped($event);
249
-
250
-		/* LANGUAGES */
251
-		$languages = $this->l10nFactory->getLanguages();
252
-
253
-		/* FINAL DATA */
254
-		$serverData = [];
255
-		// groups
256
-		$serverData['groups'] = array_merge_recursive($adminGroup, [$disabledUsersGroup], $groups);
257
-		// Various data
258
-		$serverData['isAdmin'] = $this->isAdmin;
259
-		$serverData['sortGroups'] = $sortGroupsBy;
260
-		$serverData['quotaPreset'] = $quotaPreset;
261
-		$serverData['userCount'] = $userCount;
262
-		$serverData['languages'] = $languages;
263
-		$serverData['defaultLanguage'] = $this->config->getSystemValue('default_language', 'en');
264
-		$serverData['forceLanguage'] = $this->config->getSystemValue('force_language', false);
265
-		// Settings
266
-		$serverData['defaultQuota'] = $defaultQuota;
267
-		$serverData['canChangePassword'] = $canChangePassword;
268
-		$serverData['newUserGenerateUserID'] = $this->config->getAppValue('core', 'newUser.generateUserID', 'no') === 'yes';
269
-		$serverData['newUserRequireEmail'] = $this->config->getAppValue('core', 'newUser.requireEmail', 'no') === 'yes';
270
-		$serverData['newUserSendEmail'] = $this->config->getAppValue('core', 'newUser.sendEmail', 'yes') === 'yes';
271
-
272
-		return new TemplateResponse('settings', 'settings-vue', ['serverData' => $serverData]);
273
-	}
274
-
275
-	/**
276
-	 * @param string $key
277
-	 * @param string $value
278
-	 *
279
-	 * @return JSONResponse
280
-	 */
281
-	public function setPreference(string $key, string $value): JSONResponse {
282
-		$allowed = ['newUser.sendEmail'];
283
-		if (!in_array($key, $allowed, true)) {
284
-			return new JSONResponse([], Http::STATUS_FORBIDDEN);
285
-		}
286
-
287
-		$this->config->setAppValue('core', $key, $value);
288
-
289
-		return new JSONResponse([]);
290
-	}
291
-
292
-	/**
293
-	 * Parse the app value for quota_present
294
-	 *
295
-	 * @param string $quotaPreset
296
-	 * @return array
297
-	 */
298
-	protected function parseQuotaPreset(string $quotaPreset): array {
299
-		// 1 GB, 5 GB, 10 GB => [1 GB, 5 GB, 10 GB]
300
-		$presets = array_filter(array_map('trim', explode(',', $quotaPreset)));
301
-		// Drop default and none, Make array indexes numerically
302
-		return array_values(array_diff($presets, ['default', 'none']));
303
-	}
304
-
305
-	/**
306
-	 * check if the admin can change the users password
307
-	 *
308
-	 * The admin can change the passwords if:
309
-	 *
310
-	 *   - no encryption module is loaded and encryption is disabled
311
-	 *   - encryption module is loaded but it doesn't require per user keys
312
-	 *
313
-	 * The admin can not change the passwords if:
314
-	 *
315
-	 *   - an encryption module is loaded and it uses per-user keys
316
-	 *   - encryption is enabled but no encryption modules are loaded
317
-	 *
318
-	 * @return bool
319
-	 */
320
-	protected function canAdminChangeUserPasswords(): bool {
321
-		$isEncryptionEnabled = $this->encryptionManager->isEnabled();
322
-		try {
323
-			$noUserSpecificEncryptionKeys = !$this->encryptionManager->getEncryptionModule()->needDetailedAccessList();
324
-			$isEncryptionModuleLoaded = true;
325
-		} catch (ModuleDoesNotExistsException $e) {
326
-			$noUserSpecificEncryptionKeys = true;
327
-			$isEncryptionModuleLoaded = false;
328
-		}
329
-		$canChangePassword = ($isEncryptionModuleLoaded && $noUserSpecificEncryptionKeys)
330
-			|| (!$isEncryptionModuleLoaded && !$isEncryptionEnabled);
331
-
332
-		return $canChangePassword;
333
-	}
334
-
335
-	/**
336
-	 * @NoAdminRequired
337
-	 * @NoSubAdminRequired
338
-	 * @PasswordConfirmationRequired
339
-	 *
340
-	 * @param string|null $avatarScope
341
-	 * @param string|null $displayname
342
-	 * @param string|null $displaynameScope
343
-	 * @param string|null $phone
344
-	 * @param string|null $phoneScope
345
-	 * @param string|null $email
346
-	 * @param string|null $emailScope
347
-	 * @param string|null $website
348
-	 * @param string|null $websiteScope
349
-	 * @param string|null $address
350
-	 * @param string|null $addressScope
351
-	 * @param string|null $twitter
352
-	 * @param string|null $twitterScope
353
-	 *
354
-	 * @return DataResponse
355
-	 */
356
-	public function setUserSettings(?string $avatarScope = null,
357
-									?string $displayname = null,
358
-									?string $displaynameScope = null,
359
-									?string $phone = null,
360
-									?string $phoneScope = null,
361
-									?string $email = null,
362
-									?string $emailScope = null,
363
-									?string $website = null,
364
-									?string $websiteScope = null,
365
-									?string $address = null,
366
-									?string $addressScope = null,
367
-									?string $twitter = null,
368
-									?string $twitterScope = null
369
-	) {
370
-		$user = $this->userSession->getUser();
371
-		if (!$user instanceof IUser) {
372
-			return new DataResponse(
373
-				[
374
-					'status' => 'error',
375
-					'data' => [
376
-						'message' => $this->l10n->t('Invalid user')
377
-					]
378
-				],
379
-				Http::STATUS_UNAUTHORIZED
380
-			);
381
-		}
382
-
383
-		$email = strtolower($email);
384
-		if (!empty($email) && !$this->mailer->validateMailAddress($email)) {
385
-			return new DataResponse(
386
-				[
387
-					'status' => 'error',
388
-					'data' => [
389
-						'message' => $this->l10n->t('Invalid mail address')
390
-					]
391
-				],
392
-				Http::STATUS_UNPROCESSABLE_ENTITY
393
-			);
394
-		}
395
-
396
-		$data = $this->accountManager->getUser($user);
397
-		$beforeData = $data;
398
-		$data[IAccountManager::PROPERTY_AVATAR] = ['scope' => $avatarScope];
399
-		if ($this->config->getSystemValue('allow_user_to_change_display_name', true) !== false) {
400
-			$data[IAccountManager::PROPERTY_DISPLAYNAME] = ['value' => $displayname, 'scope' => $displaynameScope];
401
-			$data[IAccountManager::PROPERTY_EMAIL] = ['value' => $email, 'scope' => $emailScope];
402
-		}
403
-		$data[IAccountManager::PROPERTY_WEBSITE] = ['value' => $website, 'scope' => $websiteScope];
404
-		$data[IAccountManager::PROPERTY_ADDRESS] = ['value' => $address, 'scope' => $addressScope];
405
-		$data[IAccountManager::PROPERTY_PHONE] = ['value' => $phone, 'scope' => $phoneScope];
406
-		$data[IAccountManager::PROPERTY_TWITTER] = ['value' => $twitter, 'scope' => $twitterScope];
407
-
408
-		try {
409
-			$data = $this->saveUserSettings($user, $data);
410
-			if ($beforeData[IAccountManager::PROPERTY_PHONE]['value'] !== $data[IAccountManager::PROPERTY_PHONE]['value']) {
411
-				$this->knownUserService->deleteByContactUserId($user->getUID());
412
-			}
413
-			return new DataResponse(
414
-				[
415
-					'status' => 'success',
416
-					'data' => [
417
-						'userId' => $user->getUID(),
418
-						'avatarScope' => $data[IAccountManager::PROPERTY_AVATAR]['scope'],
419
-						'displayname' => $data[IAccountManager::PROPERTY_DISPLAYNAME]['value'],
420
-						'displaynameScope' => $data[IAccountManager::PROPERTY_DISPLAYNAME]['scope'],
421
-						'phone' => $data[IAccountManager::PROPERTY_PHONE]['value'],
422
-						'phoneScope' => $data[IAccountManager::PROPERTY_PHONE]['scope'],
423
-						'email' => $data[IAccountManager::PROPERTY_EMAIL]['value'],
424
-						'emailScope' => $data[IAccountManager::PROPERTY_EMAIL]['scope'],
425
-						'website' => $data[IAccountManager::PROPERTY_WEBSITE]['value'],
426
-						'websiteScope' => $data[IAccountManager::PROPERTY_WEBSITE]['scope'],
427
-						'address' => $data[IAccountManager::PROPERTY_ADDRESS]['value'],
428
-						'addressScope' => $data[IAccountManager::PROPERTY_ADDRESS]['scope'],
429
-						'twitter' => $data[IAccountManager::PROPERTY_TWITTER]['value'],
430
-						'twitterScope' => $data[IAccountManager::PROPERTY_TWITTER]['scope'],
431
-						'message' => $this->l10n->t('Settings saved')
432
-					]
433
-				],
434
-				Http::STATUS_OK
435
-			);
436
-		} catch (ForbiddenException $e) {
437
-			return new DataResponse([
438
-				'status' => 'error',
439
-				'data' => [
440
-					'message' => $e->getMessage()
441
-				],
442
-			]);
443
-		} catch (\InvalidArgumentException $e) {
444
-			return new DataResponse([
445
-				'status' => 'error',
446
-				'data' => [
447
-					'message' => $e->getMessage()
448
-				],
449
-			]);
450
-		}
451
-	}
452
-	/**
453
-	 * update account manager with new user data
454
-	 *
455
-	 * @param IUser $user
456
-	 * @param array $data
457
-	 * @return array
458
-	 * @throws ForbiddenException
459
-	 * @throws \InvalidArgumentException
460
-	 */
461
-	protected function saveUserSettings(IUser $user, array $data): array {
462
-		// keep the user back-end up-to-date with the latest display name and email
463
-		// address
464
-		$oldDisplayName = $user->getDisplayName();
465
-		$oldDisplayName = is_null($oldDisplayName) ? '' : $oldDisplayName;
466
-		if (isset($data[IAccountManager::PROPERTY_DISPLAYNAME]['value'])
467
-			&& $oldDisplayName !== $data[IAccountManager::PROPERTY_DISPLAYNAME]['value']
468
-		) {
469
-			$result = $user->setDisplayName($data[IAccountManager::PROPERTY_DISPLAYNAME]['value']);
470
-			if ($result === false) {
471
-				throw new ForbiddenException($this->l10n->t('Unable to change full name'));
472
-			}
473
-		}
474
-
475
-		$oldEmailAddress = $user->getEMailAddress();
476
-		$oldEmailAddress = is_null($oldEmailAddress) ? '' : strtolower($oldEmailAddress);
477
-		if (isset($data[IAccountManager::PROPERTY_EMAIL]['value'])
478
-			&& $oldEmailAddress !== $data[IAccountManager::PROPERTY_EMAIL]['value']
479
-		) {
480
-			// this is the only permission a backend provides and is also used
481
-			// for the permission of setting a email address
482
-			if (!$user->canChangeDisplayName()) {
483
-				throw new ForbiddenException($this->l10n->t('Unable to change email address'));
484
-			}
485
-			$user->setEMailAddress($data[IAccountManager::PROPERTY_EMAIL]['value']);
486
-		}
487
-
488
-		try {
489
-			return $this->accountManager->updateUser($user, $data, true);
490
-		} catch (\InvalidArgumentException $e) {
491
-			if ($e->getMessage() === IAccountManager::PROPERTY_PHONE) {
492
-				throw new \InvalidArgumentException($this->l10n->t('Unable to set invalid phone number'));
493
-			}
494
-			throw new \InvalidArgumentException($this->l10n->t('Some account data was invalid'));
495
-		}
496
-	}
497
-
498
-	/**
499
-	 * Set the mail address of a user
500
-	 *
501
-	 * @NoAdminRequired
502
-	 * @NoSubAdminRequired
503
-	 * @PasswordConfirmationRequired
504
-	 *
505
-	 * @param string $account
506
-	 * @param bool $onlyVerificationCode only return verification code without updating the data
507
-	 * @return DataResponse
508
-	 */
509
-	public function getVerificationCode(string $account, bool $onlyVerificationCode): DataResponse {
510
-		$user = $this->userSession->getUser();
511
-
512
-		if ($user === null) {
513
-			return new DataResponse([], Http::STATUS_BAD_REQUEST);
514
-		}
515
-
516
-		$accountData = $this->accountManager->getUser($user);
517
-		$cloudId = $user->getCloudId();
518
-		$message = 'Use my Federated Cloud ID to share with me: ' . $cloudId;
519
-		$signature = $this->signMessage($user, $message);
520
-
521
-		$code = $message . ' ' . $signature;
522
-		$codeMd5 = $message . ' ' . md5($signature);
523
-
524
-		switch ($account) {
525
-			case 'verify-twitter':
526
-				$accountData[IAccountManager::PROPERTY_TWITTER]['verified'] = AccountManager::VERIFICATION_IN_PROGRESS;
527
-				$msg = $this->l10n->t('In order to verify your Twitter account, post the following tweet on Twitter (please make sure to post it without any line breaks):');
528
-				$code = $codeMd5;
529
-				$type = IAccountManager::PROPERTY_TWITTER;
530
-				$accountData[IAccountManager::PROPERTY_TWITTER]['signature'] = $signature;
531
-				break;
532
-			case 'verify-website':
533
-				$accountData[IAccountManager::PROPERTY_WEBSITE]['verified'] = AccountManager::VERIFICATION_IN_PROGRESS;
534
-				$msg = $this->l10n->t('In order to verify your Website, store the following content in your web-root at \'.well-known/CloudIdVerificationCode.txt\' (please make sure that the complete text is in one line):');
535
-				$type = IAccountManager::PROPERTY_WEBSITE;
536
-				$accountData[IAccountManager::PROPERTY_WEBSITE]['signature'] = $signature;
537
-				break;
538
-			default:
539
-				return new DataResponse([], Http::STATUS_BAD_REQUEST);
540
-		}
541
-
542
-		if ($onlyVerificationCode === false) {
543
-			$accountData = $this->accountManager->updateUser($user, $accountData);
544
-			$data = $accountData[$type]['value'];
545
-
546
-			$this->jobList->add(VerifyUserData::class,
547
-				[
548
-					'verificationCode' => $code,
549
-					'data' => $data,
550
-					'type' => $type,
551
-					'uid' => $user->getUID(),
552
-					'try' => 0,
553
-					'lastRun' => $this->getCurrentTime()
554
-				]
555
-			);
556
-		}
557
-
558
-		return new DataResponse(['msg' => $msg, 'code' => $code]);
559
-	}
560
-
561
-	/**
562
-	 * get current timestamp
563
-	 *
564
-	 * @return int
565
-	 */
566
-	protected function getCurrentTime(): int {
567
-		return time();
568
-	}
569
-
570
-	/**
571
-	 * sign message with users private key
572
-	 *
573
-	 * @param IUser $user
574
-	 * @param string $message
575
-	 *
576
-	 * @return string base64 encoded signature
577
-	 */
578
-	protected function signMessage(IUser $user, string $message): string {
579
-		$privateKey = $this->keyManager->getKey($user)->getPrivate();
580
-		openssl_sign(json_encode($message), $signature, $privateKey, OPENSSL_ALGO_SHA512);
581
-		return base64_encode($signature);
582
-	}
73
+    /** @var UserManager */
74
+    private $userManager;
75
+    /** @var GroupManager */
76
+    private $groupManager;
77
+    /** @var IUserSession */
78
+    private $userSession;
79
+    /** @var IConfig */
80
+    private $config;
81
+    /** @var bool */
82
+    private $isAdmin;
83
+    /** @var IL10N */
84
+    private $l10n;
85
+    /** @var IMailer */
86
+    private $mailer;
87
+    /** @var Factory */
88
+    private $l10nFactory;
89
+    /** @var IAppManager */
90
+    private $appManager;
91
+    /** @var AccountManager */
92
+    private $accountManager;
93
+    /** @var Manager */
94
+    private $keyManager;
95
+    /** @var IJobList */
96
+    private $jobList;
97
+    /** @var IManager */
98
+    private $encryptionManager;
99
+    /** @var KnownUserService */
100
+    private $knownUserService;
101
+    /** @var IEventDispatcher */
102
+    private $dispatcher;
103
+
104
+
105
+    public function __construct(
106
+        string $appName,
107
+        IRequest $request,
108
+        IUserManager $userManager,
109
+        IGroupManager $groupManager,
110
+        IUserSession $userSession,
111
+        IConfig $config,
112
+        bool $isAdmin,
113
+        IL10N $l10n,
114
+        IMailer $mailer,
115
+        IFactory $l10nFactory,
116
+        IAppManager $appManager,
117
+        AccountManager $accountManager,
118
+        Manager $keyManager,
119
+        IJobList $jobList,
120
+        IManager $encryptionManager,
121
+        KnownUserService $knownUserService,
122
+        IEventDispatcher $dispatcher
123
+    ) {
124
+        parent::__construct($appName, $request);
125
+        $this->userManager = $userManager;
126
+        $this->groupManager = $groupManager;
127
+        $this->userSession = $userSession;
128
+        $this->config = $config;
129
+        $this->isAdmin = $isAdmin;
130
+        $this->l10n = $l10n;
131
+        $this->mailer = $mailer;
132
+        $this->l10nFactory = $l10nFactory;
133
+        $this->appManager = $appManager;
134
+        $this->accountManager = $accountManager;
135
+        $this->keyManager = $keyManager;
136
+        $this->jobList = $jobList;
137
+        $this->encryptionManager = $encryptionManager;
138
+        $this->knownUserService = $knownUserService;
139
+        $this->dispatcher = $dispatcher;
140
+    }
141
+
142
+
143
+    /**
144
+     * @NoCSRFRequired
145
+     * @NoAdminRequired
146
+     *
147
+     * Display users list template
148
+     *
149
+     * @return TemplateResponse
150
+     */
151
+    public function usersListByGroup(): TemplateResponse {
152
+        return $this->usersList();
153
+    }
154
+
155
+    /**
156
+     * @NoCSRFRequired
157
+     * @NoAdminRequired
158
+     *
159
+     * Display users list template
160
+     *
161
+     * @return TemplateResponse
162
+     */
163
+    public function usersList(): TemplateResponse {
164
+        $user = $this->userSession->getUser();
165
+        $uid = $user->getUID();
166
+
167
+        \OC::$server->getNavigationManager()->setActiveEntry('core_users');
168
+
169
+        /* SORT OPTION: SORT_USERCOUNT or SORT_GROUPNAME */
170
+        $sortGroupsBy = \OC\Group\MetaData::SORT_USERCOUNT;
171
+        $isLDAPUsed = false;
172
+        if ($this->config->getSystemValue('sort_groups_by_name', false)) {
173
+            $sortGroupsBy = \OC\Group\MetaData::SORT_GROUPNAME;
174
+        } else {
175
+            if ($this->appManager->isEnabledForUser('user_ldap')) {
176
+                $isLDAPUsed =
177
+                    $this->groupManager->isBackendUsed('\OCA\User_LDAP\Group_Proxy');
178
+                if ($isLDAPUsed) {
179
+                    // LDAP user count can be slow, so we sort by group name here
180
+                    $sortGroupsBy = \OC\Group\MetaData::SORT_GROUPNAME;
181
+                }
182
+            }
183
+        }
184
+
185
+        $canChangePassword = $this->canAdminChangeUserPasswords();
186
+
187
+        /* GROUPS */
188
+        $groupsInfo = new \OC\Group\MetaData(
189
+            $uid,
190
+            $this->isAdmin,
191
+            $this->groupManager,
192
+            $this->userSession
193
+        );
194
+
195
+        $groupsInfo->setSorting($sortGroupsBy);
196
+        [$adminGroup, $groups] = $groupsInfo->get();
197
+
198
+        if (!$isLDAPUsed && $this->appManager->isEnabledForUser('user_ldap')) {
199
+            $isLDAPUsed = (bool)array_reduce($this->userManager->getBackends(), function ($ldapFound, $backend) {
200
+                return $ldapFound || $backend instanceof User_Proxy;
201
+            });
202
+        }
203
+
204
+        $disabledUsers = -1;
205
+        $userCount = 0;
206
+
207
+        if (!$isLDAPUsed) {
208
+            if ($this->isAdmin) {
209
+                $disabledUsers = $this->userManager->countDisabledUsers();
210
+                $userCount = array_reduce($this->userManager->countUsers(), function ($v, $w) {
211
+                    return $v + (int)$w;
212
+                }, 0);
213
+            } else {
214
+                // User is subadmin !
215
+                // Map group list to names to retrieve the countDisabledUsersOfGroups
216
+                $userGroups = $this->groupManager->getUserGroups($user);
217
+                $groupsNames = [];
218
+
219
+                foreach ($groups as $key => $group) {
220
+                    // $userCount += (int)$group['usercount'];
221
+                    array_push($groupsNames, $group['name']);
222
+                    // we prevent subadmins from looking up themselves
223
+                    // so we lower the count of the groups he belongs to
224
+                    if (array_key_exists($group['id'], $userGroups)) {
225
+                        $groups[$key]['usercount']--;
226
+                        $userCount -= 1; // we also lower from one the total count
227
+                    }
228
+                }
229
+                $userCount += $this->userManager->countUsersOfGroups($groupsInfo->getGroups());
230
+                $disabledUsers = $this->userManager->countDisabledUsersOfGroups($groupsNames);
231
+            }
232
+
233
+            $userCount -= $disabledUsers;
234
+        }
235
+
236
+        $disabledUsersGroup = [
237
+            'id' => 'disabled',
238
+            'name' => 'Disabled users',
239
+            'usercount' => $disabledUsers
240
+        ];
241
+
242
+        /* QUOTAS PRESETS */
243
+        $quotaPreset = $this->parseQuotaPreset($this->config->getAppValue('files', 'quota_preset', '1 GB, 5 GB, 10 GB'));
244
+        $defaultQuota = $this->config->getAppValue('files', 'default_quota', 'none');
245
+
246
+        $event = new BeforeTemplateRenderedEvent();
247
+        $this->dispatcher->dispatch('OC\Settings\Users::loadAdditionalScripts', $event);
248
+        $this->dispatcher->dispatchTyped($event);
249
+
250
+        /* LANGUAGES */
251
+        $languages = $this->l10nFactory->getLanguages();
252
+
253
+        /* FINAL DATA */
254
+        $serverData = [];
255
+        // groups
256
+        $serverData['groups'] = array_merge_recursive($adminGroup, [$disabledUsersGroup], $groups);
257
+        // Various data
258
+        $serverData['isAdmin'] = $this->isAdmin;
259
+        $serverData['sortGroups'] = $sortGroupsBy;
260
+        $serverData['quotaPreset'] = $quotaPreset;
261
+        $serverData['userCount'] = $userCount;
262
+        $serverData['languages'] = $languages;
263
+        $serverData['defaultLanguage'] = $this->config->getSystemValue('default_language', 'en');
264
+        $serverData['forceLanguage'] = $this->config->getSystemValue('force_language', false);
265
+        // Settings
266
+        $serverData['defaultQuota'] = $defaultQuota;
267
+        $serverData['canChangePassword'] = $canChangePassword;
268
+        $serverData['newUserGenerateUserID'] = $this->config->getAppValue('core', 'newUser.generateUserID', 'no') === 'yes';
269
+        $serverData['newUserRequireEmail'] = $this->config->getAppValue('core', 'newUser.requireEmail', 'no') === 'yes';
270
+        $serverData['newUserSendEmail'] = $this->config->getAppValue('core', 'newUser.sendEmail', 'yes') === 'yes';
271
+
272
+        return new TemplateResponse('settings', 'settings-vue', ['serverData' => $serverData]);
273
+    }
274
+
275
+    /**
276
+     * @param string $key
277
+     * @param string $value
278
+     *
279
+     * @return JSONResponse
280
+     */
281
+    public function setPreference(string $key, string $value): JSONResponse {
282
+        $allowed = ['newUser.sendEmail'];
283
+        if (!in_array($key, $allowed, true)) {
284
+            return new JSONResponse([], Http::STATUS_FORBIDDEN);
285
+        }
286
+
287
+        $this->config->setAppValue('core', $key, $value);
288
+
289
+        return new JSONResponse([]);
290
+    }
291
+
292
+    /**
293
+     * Parse the app value for quota_present
294
+     *
295
+     * @param string $quotaPreset
296
+     * @return array
297
+     */
298
+    protected function parseQuotaPreset(string $quotaPreset): array {
299
+        // 1 GB, 5 GB, 10 GB => [1 GB, 5 GB, 10 GB]
300
+        $presets = array_filter(array_map('trim', explode(',', $quotaPreset)));
301
+        // Drop default and none, Make array indexes numerically
302
+        return array_values(array_diff($presets, ['default', 'none']));
303
+    }
304
+
305
+    /**
306
+     * check if the admin can change the users password
307
+     *
308
+     * The admin can change the passwords if:
309
+     *
310
+     *   - no encryption module is loaded and encryption is disabled
311
+     *   - encryption module is loaded but it doesn't require per user keys
312
+     *
313
+     * The admin can not change the passwords if:
314
+     *
315
+     *   - an encryption module is loaded and it uses per-user keys
316
+     *   - encryption is enabled but no encryption modules are loaded
317
+     *
318
+     * @return bool
319
+     */
320
+    protected function canAdminChangeUserPasswords(): bool {
321
+        $isEncryptionEnabled = $this->encryptionManager->isEnabled();
322
+        try {
323
+            $noUserSpecificEncryptionKeys = !$this->encryptionManager->getEncryptionModule()->needDetailedAccessList();
324
+            $isEncryptionModuleLoaded = true;
325
+        } catch (ModuleDoesNotExistsException $e) {
326
+            $noUserSpecificEncryptionKeys = true;
327
+            $isEncryptionModuleLoaded = false;
328
+        }
329
+        $canChangePassword = ($isEncryptionModuleLoaded && $noUserSpecificEncryptionKeys)
330
+            || (!$isEncryptionModuleLoaded && !$isEncryptionEnabled);
331
+
332
+        return $canChangePassword;
333
+    }
334
+
335
+    /**
336
+     * @NoAdminRequired
337
+     * @NoSubAdminRequired
338
+     * @PasswordConfirmationRequired
339
+     *
340
+     * @param string|null $avatarScope
341
+     * @param string|null $displayname
342
+     * @param string|null $displaynameScope
343
+     * @param string|null $phone
344
+     * @param string|null $phoneScope
345
+     * @param string|null $email
346
+     * @param string|null $emailScope
347
+     * @param string|null $website
348
+     * @param string|null $websiteScope
349
+     * @param string|null $address
350
+     * @param string|null $addressScope
351
+     * @param string|null $twitter
352
+     * @param string|null $twitterScope
353
+     *
354
+     * @return DataResponse
355
+     */
356
+    public function setUserSettings(?string $avatarScope = null,
357
+                                    ?string $displayname = null,
358
+                                    ?string $displaynameScope = null,
359
+                                    ?string $phone = null,
360
+                                    ?string $phoneScope = null,
361
+                                    ?string $email = null,
362
+                                    ?string $emailScope = null,
363
+                                    ?string $website = null,
364
+                                    ?string $websiteScope = null,
365
+                                    ?string $address = null,
366
+                                    ?string $addressScope = null,
367
+                                    ?string $twitter = null,
368
+                                    ?string $twitterScope = null
369
+    ) {
370
+        $user = $this->userSession->getUser();
371
+        if (!$user instanceof IUser) {
372
+            return new DataResponse(
373
+                [
374
+                    'status' => 'error',
375
+                    'data' => [
376
+                        'message' => $this->l10n->t('Invalid user')
377
+                    ]
378
+                ],
379
+                Http::STATUS_UNAUTHORIZED
380
+            );
381
+        }
382
+
383
+        $email = strtolower($email);
384
+        if (!empty($email) && !$this->mailer->validateMailAddress($email)) {
385
+            return new DataResponse(
386
+                [
387
+                    'status' => 'error',
388
+                    'data' => [
389
+                        'message' => $this->l10n->t('Invalid mail address')
390
+                    ]
391
+                ],
392
+                Http::STATUS_UNPROCESSABLE_ENTITY
393
+            );
394
+        }
395
+
396
+        $data = $this->accountManager->getUser($user);
397
+        $beforeData = $data;
398
+        $data[IAccountManager::PROPERTY_AVATAR] = ['scope' => $avatarScope];
399
+        if ($this->config->getSystemValue('allow_user_to_change_display_name', true) !== false) {
400
+            $data[IAccountManager::PROPERTY_DISPLAYNAME] = ['value' => $displayname, 'scope' => $displaynameScope];
401
+            $data[IAccountManager::PROPERTY_EMAIL] = ['value' => $email, 'scope' => $emailScope];
402
+        }
403
+        $data[IAccountManager::PROPERTY_WEBSITE] = ['value' => $website, 'scope' => $websiteScope];
404
+        $data[IAccountManager::PROPERTY_ADDRESS] = ['value' => $address, 'scope' => $addressScope];
405
+        $data[IAccountManager::PROPERTY_PHONE] = ['value' => $phone, 'scope' => $phoneScope];
406
+        $data[IAccountManager::PROPERTY_TWITTER] = ['value' => $twitter, 'scope' => $twitterScope];
407
+
408
+        try {
409
+            $data = $this->saveUserSettings($user, $data);
410
+            if ($beforeData[IAccountManager::PROPERTY_PHONE]['value'] !== $data[IAccountManager::PROPERTY_PHONE]['value']) {
411
+                $this->knownUserService->deleteByContactUserId($user->getUID());
412
+            }
413
+            return new DataResponse(
414
+                [
415
+                    'status' => 'success',
416
+                    'data' => [
417
+                        'userId' => $user->getUID(),
418
+                        'avatarScope' => $data[IAccountManager::PROPERTY_AVATAR]['scope'],
419
+                        'displayname' => $data[IAccountManager::PROPERTY_DISPLAYNAME]['value'],
420
+                        'displaynameScope' => $data[IAccountManager::PROPERTY_DISPLAYNAME]['scope'],
421
+                        'phone' => $data[IAccountManager::PROPERTY_PHONE]['value'],
422
+                        'phoneScope' => $data[IAccountManager::PROPERTY_PHONE]['scope'],
423
+                        'email' => $data[IAccountManager::PROPERTY_EMAIL]['value'],
424
+                        'emailScope' => $data[IAccountManager::PROPERTY_EMAIL]['scope'],
425
+                        'website' => $data[IAccountManager::PROPERTY_WEBSITE]['value'],
426
+                        'websiteScope' => $data[IAccountManager::PROPERTY_WEBSITE]['scope'],
427
+                        'address' => $data[IAccountManager::PROPERTY_ADDRESS]['value'],
428
+                        'addressScope' => $data[IAccountManager::PROPERTY_ADDRESS]['scope'],
429
+                        'twitter' => $data[IAccountManager::PROPERTY_TWITTER]['value'],
430
+                        'twitterScope' => $data[IAccountManager::PROPERTY_TWITTER]['scope'],
431
+                        'message' => $this->l10n->t('Settings saved')
432
+                    ]
433
+                ],
434
+                Http::STATUS_OK
435
+            );
436
+        } catch (ForbiddenException $e) {
437
+            return new DataResponse([
438
+                'status' => 'error',
439
+                'data' => [
440
+                    'message' => $e->getMessage()
441
+                ],
442
+            ]);
443
+        } catch (\InvalidArgumentException $e) {
444
+            return new DataResponse([
445
+                'status' => 'error',
446
+                'data' => [
447
+                    'message' => $e->getMessage()
448
+                ],
449
+            ]);
450
+        }
451
+    }
452
+    /**
453
+     * update account manager with new user data
454
+     *
455
+     * @param IUser $user
456
+     * @param array $data
457
+     * @return array
458
+     * @throws ForbiddenException
459
+     * @throws \InvalidArgumentException
460
+     */
461
+    protected function saveUserSettings(IUser $user, array $data): array {
462
+        // keep the user back-end up-to-date with the latest display name and email
463
+        // address
464
+        $oldDisplayName = $user->getDisplayName();
465
+        $oldDisplayName = is_null($oldDisplayName) ? '' : $oldDisplayName;
466
+        if (isset($data[IAccountManager::PROPERTY_DISPLAYNAME]['value'])
467
+            && $oldDisplayName !== $data[IAccountManager::PROPERTY_DISPLAYNAME]['value']
468
+        ) {
469
+            $result = $user->setDisplayName($data[IAccountManager::PROPERTY_DISPLAYNAME]['value']);
470
+            if ($result === false) {
471
+                throw new ForbiddenException($this->l10n->t('Unable to change full name'));
472
+            }
473
+        }
474
+
475
+        $oldEmailAddress = $user->getEMailAddress();
476
+        $oldEmailAddress = is_null($oldEmailAddress) ? '' : strtolower($oldEmailAddress);
477
+        if (isset($data[IAccountManager::PROPERTY_EMAIL]['value'])
478
+            && $oldEmailAddress !== $data[IAccountManager::PROPERTY_EMAIL]['value']
479
+        ) {
480
+            // this is the only permission a backend provides and is also used
481
+            // for the permission of setting a email address
482
+            if (!$user->canChangeDisplayName()) {
483
+                throw new ForbiddenException($this->l10n->t('Unable to change email address'));
484
+            }
485
+            $user->setEMailAddress($data[IAccountManager::PROPERTY_EMAIL]['value']);
486
+        }
487
+
488
+        try {
489
+            return $this->accountManager->updateUser($user, $data, true);
490
+        } catch (\InvalidArgumentException $e) {
491
+            if ($e->getMessage() === IAccountManager::PROPERTY_PHONE) {
492
+                throw new \InvalidArgumentException($this->l10n->t('Unable to set invalid phone number'));
493
+            }
494
+            throw new \InvalidArgumentException($this->l10n->t('Some account data was invalid'));
495
+        }
496
+    }
497
+
498
+    /**
499
+     * Set the mail address of a user
500
+     *
501
+     * @NoAdminRequired
502
+     * @NoSubAdminRequired
503
+     * @PasswordConfirmationRequired
504
+     *
505
+     * @param string $account
506
+     * @param bool $onlyVerificationCode only return verification code without updating the data
507
+     * @return DataResponse
508
+     */
509
+    public function getVerificationCode(string $account, bool $onlyVerificationCode): DataResponse {
510
+        $user = $this->userSession->getUser();
511
+
512
+        if ($user === null) {
513
+            return new DataResponse([], Http::STATUS_BAD_REQUEST);
514
+        }
515
+
516
+        $accountData = $this->accountManager->getUser($user);
517
+        $cloudId = $user->getCloudId();
518
+        $message = 'Use my Federated Cloud ID to share with me: ' . $cloudId;
519
+        $signature = $this->signMessage($user, $message);
520
+
521
+        $code = $message . ' ' . $signature;
522
+        $codeMd5 = $message . ' ' . md5($signature);
523
+
524
+        switch ($account) {
525
+            case 'verify-twitter':
526
+                $accountData[IAccountManager::PROPERTY_TWITTER]['verified'] = AccountManager::VERIFICATION_IN_PROGRESS;
527
+                $msg = $this->l10n->t('In order to verify your Twitter account, post the following tweet on Twitter (please make sure to post it without any line breaks):');
528
+                $code = $codeMd5;
529
+                $type = IAccountManager::PROPERTY_TWITTER;
530
+                $accountData[IAccountManager::PROPERTY_TWITTER]['signature'] = $signature;
531
+                break;
532
+            case 'verify-website':
533
+                $accountData[IAccountManager::PROPERTY_WEBSITE]['verified'] = AccountManager::VERIFICATION_IN_PROGRESS;
534
+                $msg = $this->l10n->t('In order to verify your Website, store the following content in your web-root at \'.well-known/CloudIdVerificationCode.txt\' (please make sure that the complete text is in one line):');
535
+                $type = IAccountManager::PROPERTY_WEBSITE;
536
+                $accountData[IAccountManager::PROPERTY_WEBSITE]['signature'] = $signature;
537
+                break;
538
+            default:
539
+                return new DataResponse([], Http::STATUS_BAD_REQUEST);
540
+        }
541
+
542
+        if ($onlyVerificationCode === false) {
543
+            $accountData = $this->accountManager->updateUser($user, $accountData);
544
+            $data = $accountData[$type]['value'];
545
+
546
+            $this->jobList->add(VerifyUserData::class,
547
+                [
548
+                    'verificationCode' => $code,
549
+                    'data' => $data,
550
+                    'type' => $type,
551
+                    'uid' => $user->getUID(),
552
+                    'try' => 0,
553
+                    'lastRun' => $this->getCurrentTime()
554
+                ]
555
+            );
556
+        }
557
+
558
+        return new DataResponse(['msg' => $msg, 'code' => $code]);
559
+    }
560
+
561
+    /**
562
+     * get current timestamp
563
+     *
564
+     * @return int
565
+     */
566
+    protected function getCurrentTime(): int {
567
+        return time();
568
+    }
569
+
570
+    /**
571
+     * sign message with users private key
572
+     *
573
+     * @param IUser $user
574
+     * @param string $message
575
+     *
576
+     * @return string base64 encoded signature
577
+     */
578
+    protected function signMessage(IUser $user, string $message): string {
579
+        $privateKey = $this->keyManager->getKey($user)->getPrivate();
580
+        openssl_sign(json_encode($message), $signature, $privateKey, OPENSSL_ALGO_SHA512);
581
+        return base64_encode($signature);
582
+    }
583 583
 }
Please login to merge, or discard this patch.
apps/lookup_server_connector/lib/BackgroundJobs/RetryJob.php 1 patch
Indentation   +172 added lines, -172 removed lines patch added patch discarded remove patch
@@ -44,176 +44,176 @@
 block discarded – undo
44 44
 use OCP\IUserManager;
45 45
 
46 46
 class RetryJob extends Job {
47
-	/** @var IClientService */
48
-	private $clientService;
49
-	/** @var string */
50
-	private $lookupServer;
51
-	/** @var IConfig */
52
-	private $config;
53
-	/** @var IUserManager */
54
-	private $userManager;
55
-	/** @var IAccountManager */
56
-	private $accountManager;
57
-	/** @var Signer */
58
-	private $signer;
59
-	/** @var int */
60
-	protected $retries = 0;
61
-	/** @var bool */
62
-	protected $retainJob = false;
63
-
64
-	/**
65
-	 * @param ITimeFactory $time
66
-	 * @param IClientService $clientService
67
-	 * @param IConfig $config
68
-	 * @param IUserManager $userManager
69
-	 * @param IAccountManager $accountManager
70
-	 * @param Signer $signer
71
-	 */
72
-	public function __construct(ITimeFactory $time,
73
-								IClientService $clientService,
74
-								IConfig $config,
75
-								IUserManager $userManager,
76
-								IAccountManager $accountManager,
77
-								Signer $signer) {
78
-		parent::__construct($time);
79
-		$this->clientService = $clientService;
80
-		$this->config = $config;
81
-		$this->userManager = $userManager;
82
-		$this->accountManager = $accountManager;
83
-		$this->signer = $signer;
84
-
85
-		$this->lookupServer = $config->getSystemValue('lookup_server', 'https://lookup.nextcloud.com');
86
-		if (!empty($this->lookupServer)) {
87
-			$this->lookupServer = rtrim($this->lookupServer, '/');
88
-			$this->lookupServer .= '/users';
89
-		}
90
-	}
91
-
92
-	/**
93
-	 * run the job, then remove it from the jobList
94
-	 *
95
-	 * @param IJobList $jobList
96
-	 * @param ILogger|null $logger
97
-	 */
98
-	public function execute(IJobList $jobList, ILogger $logger = null): void {
99
-		if (!isset($this->argument['userId'])) {
100
-			// Old background job without user id, just drop it.
101
-			$jobList->remove($this, $this->argument);
102
-			return;
103
-		}
104
-
105
-		$this->retries = (int) $this->config->getUserValue($this->argument['userId'], 'lookup_server_connector', 'update_retries', 0);
106
-
107
-		if ($this->shouldRemoveBackgroundJob()) {
108
-			$jobList->remove($this, $this->argument);
109
-			return;
110
-		}
111
-
112
-		if ($this->shouldRun()) {
113
-			parent::execute($jobList, $logger);
114
-			if (!$this->retainJob) {
115
-				$jobList->remove($this, $this->argument);
116
-			}
117
-		}
118
-	}
119
-
120
-	/**
121
-	 * Check if we should kill the background job:
122
-	 *
123
-	 * - internet connection is disabled
124
-	 * - no valid lookup server URL given
125
-	 * - lookup server was disabled by the admin
126
-	 * - max retries are reached (set to 5)
127
-	 *
128
-	 * @return bool
129
-	 */
130
-	protected function shouldRemoveBackgroundJob(): bool {
131
-		return $this->config->getSystemValueBool('has_internet_connection', true) === false ||
132
-			$this->config->getSystemValueString('lookup_server', 'https://lookup.nextcloud.com') === '' ||
133
-			$this->config->getAppValue('files_sharing', 'lookupServerUploadEnabled', 'yes') !== 'yes' ||
134
-			$this->retries >= 5;
135
-	}
136
-
137
-	protected function shouldRun(): bool {
138
-		$delay = 100 * 6 ** $this->retries;
139
-		return ($this->time->getTime() - $this->lastRun) > $delay;
140
-	}
141
-
142
-	protected function run($argument): void {
143
-		$user = $this->userManager->get($this->argument['userId']);
144
-		if (!$user instanceof IUser) {
145
-			// User does not exist anymore
146
-			return;
147
-		}
148
-
149
-		$data = $this->getUserAccountData($user);
150
-		$signedData = $this->signer->sign('lookupserver', $data, $user);
151
-		$client = $this->clientService->newClient();
152
-
153
-		try {
154
-			if (count($data) === 1) {
155
-				// No public data, just the federation Id
156
-				$client->delete($this->lookupServer,
157
-					[
158
-						'body' => json_encode($signedData),
159
-						'timeout' => 10,
160
-						'connect_timeout' => 3,
161
-					]
162
-				);
163
-			} else {
164
-				$client->post($this->lookupServer,
165
-					[
166
-						'body' => json_encode($signedData),
167
-						'timeout' => 10,
168
-						'connect_timeout' => 3,
169
-					]
170
-				);
171
-			}
172
-
173
-			// Reset retry counter
174
-			$this->config->deleteUserValue(
175
-				$user->getUID(),
176
-				'lookup_server_connector',
177
-				'update_retries'
178
-			);
179
-		} catch (\Exception $e) {
180
-			// An error occurred, retry later
181
-			$this->retainJob = true;
182
-			$this->config->setUserValue(
183
-				$user->getUID(),
184
-				'lookup_server_connector',
185
-				'update_retries',
186
-				$this->retries + 1
187
-			);
188
-		}
189
-	}
190
-
191
-	protected function getUserAccountData(IUser $user): array {
192
-		$account = $this->accountManager->getAccount($user);
193
-
194
-		$publicData = [];
195
-		foreach ($account->getProperties() as $property) {
196
-			if ($property->getScope() === IAccountManager::SCOPE_PUBLISHED) {
197
-				$publicData[$property->getName()] = $property->getValue();
198
-			}
199
-		}
200
-
201
-		$data = ['federationId' => $user->getCloudId()];
202
-		if (!empty($publicData)) {
203
-			$data['name'] = $publicData[IAccountManager::PROPERTY_DISPLAYNAME]['value'] ?? '';
204
-			$data['email'] = $publicData[IAccountManager::PROPERTY_EMAIL]['value'] ?? '';
205
-			$data['address'] = $publicData[IAccountManager::PROPERTY_ADDRESS]['value'] ?? '';
206
-			$data['website'] = $publicData[IAccountManager::PROPERTY_WEBSITE]['value'] ?? '';
207
-			$data['twitter'] = $publicData[IAccountManager::PROPERTY_TWITTER]['value'] ?? '';
208
-			$data['phone'] = $publicData[IAccountManager::PROPERTY_PHONE]['value'] ?? '';
209
-			$data['twitter_signature'] = $publicData[IAccountManager::PROPERTY_TWITTER]['signature'] ?? '';
210
-			$data['website_signature'] = $publicData[IAccountManager::PROPERTY_WEBSITE]['signature'] ?? '';
211
-			$data['verificationStatus'] = [
212
-				IAccountManager::PROPERTY_WEBSITE => $publicData[IAccountManager::PROPERTY_WEBSITE]['verified'] ?? '',
213
-				IAccountManager::PROPERTY_TWITTER => $publicData[IAccountManager::PROPERTY_TWITTER]['verified'] ?? '',
214
-			];
215
-		}
216
-
217
-		return $data;
218
-	}
47
+    /** @var IClientService */
48
+    private $clientService;
49
+    /** @var string */
50
+    private $lookupServer;
51
+    /** @var IConfig */
52
+    private $config;
53
+    /** @var IUserManager */
54
+    private $userManager;
55
+    /** @var IAccountManager */
56
+    private $accountManager;
57
+    /** @var Signer */
58
+    private $signer;
59
+    /** @var int */
60
+    protected $retries = 0;
61
+    /** @var bool */
62
+    protected $retainJob = false;
63
+
64
+    /**
65
+     * @param ITimeFactory $time
66
+     * @param IClientService $clientService
67
+     * @param IConfig $config
68
+     * @param IUserManager $userManager
69
+     * @param IAccountManager $accountManager
70
+     * @param Signer $signer
71
+     */
72
+    public function __construct(ITimeFactory $time,
73
+                                IClientService $clientService,
74
+                                IConfig $config,
75
+                                IUserManager $userManager,
76
+                                IAccountManager $accountManager,
77
+                                Signer $signer) {
78
+        parent::__construct($time);
79
+        $this->clientService = $clientService;
80
+        $this->config = $config;
81
+        $this->userManager = $userManager;
82
+        $this->accountManager = $accountManager;
83
+        $this->signer = $signer;
84
+
85
+        $this->lookupServer = $config->getSystemValue('lookup_server', 'https://lookup.nextcloud.com');
86
+        if (!empty($this->lookupServer)) {
87
+            $this->lookupServer = rtrim($this->lookupServer, '/');
88
+            $this->lookupServer .= '/users';
89
+        }
90
+    }
91
+
92
+    /**
93
+     * run the job, then remove it from the jobList
94
+     *
95
+     * @param IJobList $jobList
96
+     * @param ILogger|null $logger
97
+     */
98
+    public function execute(IJobList $jobList, ILogger $logger = null): void {
99
+        if (!isset($this->argument['userId'])) {
100
+            // Old background job without user id, just drop it.
101
+            $jobList->remove($this, $this->argument);
102
+            return;
103
+        }
104
+
105
+        $this->retries = (int) $this->config->getUserValue($this->argument['userId'], 'lookup_server_connector', 'update_retries', 0);
106
+
107
+        if ($this->shouldRemoveBackgroundJob()) {
108
+            $jobList->remove($this, $this->argument);
109
+            return;
110
+        }
111
+
112
+        if ($this->shouldRun()) {
113
+            parent::execute($jobList, $logger);
114
+            if (!$this->retainJob) {
115
+                $jobList->remove($this, $this->argument);
116
+            }
117
+        }
118
+    }
119
+
120
+    /**
121
+     * Check if we should kill the background job:
122
+     *
123
+     * - internet connection is disabled
124
+     * - no valid lookup server URL given
125
+     * - lookup server was disabled by the admin
126
+     * - max retries are reached (set to 5)
127
+     *
128
+     * @return bool
129
+     */
130
+    protected function shouldRemoveBackgroundJob(): bool {
131
+        return $this->config->getSystemValueBool('has_internet_connection', true) === false ||
132
+            $this->config->getSystemValueString('lookup_server', 'https://lookup.nextcloud.com') === '' ||
133
+            $this->config->getAppValue('files_sharing', 'lookupServerUploadEnabled', 'yes') !== 'yes' ||
134
+            $this->retries >= 5;
135
+    }
136
+
137
+    protected function shouldRun(): bool {
138
+        $delay = 100 * 6 ** $this->retries;
139
+        return ($this->time->getTime() - $this->lastRun) > $delay;
140
+    }
141
+
142
+    protected function run($argument): void {
143
+        $user = $this->userManager->get($this->argument['userId']);
144
+        if (!$user instanceof IUser) {
145
+            // User does not exist anymore
146
+            return;
147
+        }
148
+
149
+        $data = $this->getUserAccountData($user);
150
+        $signedData = $this->signer->sign('lookupserver', $data, $user);
151
+        $client = $this->clientService->newClient();
152
+
153
+        try {
154
+            if (count($data) === 1) {
155
+                // No public data, just the federation Id
156
+                $client->delete($this->lookupServer,
157
+                    [
158
+                        'body' => json_encode($signedData),
159
+                        'timeout' => 10,
160
+                        'connect_timeout' => 3,
161
+                    ]
162
+                );
163
+            } else {
164
+                $client->post($this->lookupServer,
165
+                    [
166
+                        'body' => json_encode($signedData),
167
+                        'timeout' => 10,
168
+                        'connect_timeout' => 3,
169
+                    ]
170
+                );
171
+            }
172
+
173
+            // Reset retry counter
174
+            $this->config->deleteUserValue(
175
+                $user->getUID(),
176
+                'lookup_server_connector',
177
+                'update_retries'
178
+            );
179
+        } catch (\Exception $e) {
180
+            // An error occurred, retry later
181
+            $this->retainJob = true;
182
+            $this->config->setUserValue(
183
+                $user->getUID(),
184
+                'lookup_server_connector',
185
+                'update_retries',
186
+                $this->retries + 1
187
+            );
188
+        }
189
+    }
190
+
191
+    protected function getUserAccountData(IUser $user): array {
192
+        $account = $this->accountManager->getAccount($user);
193
+
194
+        $publicData = [];
195
+        foreach ($account->getProperties() as $property) {
196
+            if ($property->getScope() === IAccountManager::SCOPE_PUBLISHED) {
197
+                $publicData[$property->getName()] = $property->getValue();
198
+            }
199
+        }
200
+
201
+        $data = ['federationId' => $user->getCloudId()];
202
+        if (!empty($publicData)) {
203
+            $data['name'] = $publicData[IAccountManager::PROPERTY_DISPLAYNAME]['value'] ?? '';
204
+            $data['email'] = $publicData[IAccountManager::PROPERTY_EMAIL]['value'] ?? '';
205
+            $data['address'] = $publicData[IAccountManager::PROPERTY_ADDRESS]['value'] ?? '';
206
+            $data['website'] = $publicData[IAccountManager::PROPERTY_WEBSITE]['value'] ?? '';
207
+            $data['twitter'] = $publicData[IAccountManager::PROPERTY_TWITTER]['value'] ?? '';
208
+            $data['phone'] = $publicData[IAccountManager::PROPERTY_PHONE]['value'] ?? '';
209
+            $data['twitter_signature'] = $publicData[IAccountManager::PROPERTY_TWITTER]['signature'] ?? '';
210
+            $data['website_signature'] = $publicData[IAccountManager::PROPERTY_WEBSITE]['signature'] ?? '';
211
+            $data['verificationStatus'] = [
212
+                IAccountManager::PROPERTY_WEBSITE => $publicData[IAccountManager::PROPERTY_WEBSITE]['verified'] ?? '',
213
+                IAccountManager::PROPERTY_TWITTER => $publicData[IAccountManager::PROPERTY_TWITTER]['verified'] ?? '',
214
+            ];
215
+        }
216
+
217
+        return $data;
218
+    }
219 219
 }
Please login to merge, or discard this patch.
apps/files_sharing/lib/Controller/ShareController.php 1 patch
Indentation   +660 added lines, -660 removed lines patch added patch discarded remove patch
@@ -85,666 +85,666 @@
 block discarded – undo
85 85
  */
86 86
 class ShareController extends AuthPublicShareController {
87 87
 
88
-	/** @var IConfig */
89
-	protected $config;
90
-	/** @var IUserManager */
91
-	protected $userManager;
92
-	/** @var ILogger */
93
-	protected $logger;
94
-	/** @var \OCP\Activity\IManager */
95
-	protected $activityManager;
96
-	/** @var IPreview */
97
-	protected $previewManager;
98
-	/** @var IRootFolder */
99
-	protected $rootFolder;
100
-	/** @var FederatedShareProvider */
101
-	protected $federatedShareProvider;
102
-	/** @var IAccountManager */
103
-	protected $accountManager;
104
-	/** @var IEventDispatcher */
105
-	protected $eventDispatcher;
106
-	/** @var IL10N */
107
-	protected $l10n;
108
-	/** @var Defaults */
109
-	protected $defaults;
110
-	/** @var ShareManager */
111
-	protected $shareManager;
112
-
113
-	/** @var Share\IShare */
114
-	protected $share;
115
-
116
-	/**
117
-	 * @param string $appName
118
-	 * @param IRequest $request
119
-	 * @param IConfig $config
120
-	 * @param IURLGenerator $urlGenerator
121
-	 * @param IUserManager $userManager
122
-	 * @param ILogger $logger
123
-	 * @param \OCP\Activity\IManager $activityManager
124
-	 * @param \OCP\Share\IManager $shareManager
125
-	 * @param ISession $session
126
-	 * @param IPreview $previewManager
127
-	 * @param IRootFolder $rootFolder
128
-	 * @param FederatedShareProvider $federatedShareProvider
129
-	 * @param IAccountManager $accountManager
130
-	 * @param IEventDispatcher $eventDispatcher
131
-	 * @param IL10N $l10n
132
-	 * @param Defaults $defaults
133
-	 */
134
-	public function __construct(string $appName,
135
-								IRequest $request,
136
-								IConfig $config,
137
-								IURLGenerator $urlGenerator,
138
-								IUserManager $userManager,
139
-								ILogger $logger,
140
-								\OCP\Activity\IManager $activityManager,
141
-								ShareManager $shareManager,
142
-								ISession $session,
143
-								IPreview $previewManager,
144
-								IRootFolder $rootFolder,
145
-								FederatedShareProvider $federatedShareProvider,
146
-								IAccountManager $accountManager,
147
-								IEventDispatcher $eventDispatcher,
148
-								IL10N $l10n,
149
-								Defaults $defaults) {
150
-		parent::__construct($appName, $request, $session, $urlGenerator);
151
-
152
-		$this->config = $config;
153
-		$this->userManager = $userManager;
154
-		$this->logger = $logger;
155
-		$this->activityManager = $activityManager;
156
-		$this->previewManager = $previewManager;
157
-		$this->rootFolder = $rootFolder;
158
-		$this->federatedShareProvider = $federatedShareProvider;
159
-		$this->accountManager = $accountManager;
160
-		$this->eventDispatcher = $eventDispatcher;
161
-		$this->l10n = $l10n;
162
-		$this->defaults = $defaults;
163
-		$this->shareManager = $shareManager;
164
-	}
165
-
166
-	/**
167
-	 * @PublicPage
168
-	 * @NoCSRFRequired
169
-	 *
170
-	 * Show the authentication page
171
-	 * The form has to submit to the authenticate method route
172
-	 */
173
-	public function showAuthenticate(): TemplateResponse {
174
-		$templateParameters = ['share' => $this->share];
175
-
176
-		$this->eventDispatcher->dispatchTyped(new BeforeTemplateRenderedEvent($this->share, BeforeTemplateRenderedEvent::SCOPE_PUBLIC_SHARE_AUTH));
177
-
178
-		$response = new TemplateResponse('core', 'publicshareauth', $templateParameters, 'guest');
179
-		if ($this->share->getSendPasswordByTalk()) {
180
-			$csp = new ContentSecurityPolicy();
181
-			$csp->addAllowedConnectDomain('*');
182
-			$csp->addAllowedMediaDomain('blob:');
183
-			$response->setContentSecurityPolicy($csp);
184
-		}
185
-
186
-		return $response;
187
-	}
188
-
189
-	/**
190
-	 * The template to show when authentication failed
191
-	 */
192
-	protected function showAuthFailed(): TemplateResponse {
193
-		$templateParameters = ['share' => $this->share, 'wrongpw' => true];
194
-
195
-		$this->eventDispatcher->dispatchTyped(new BeforeTemplateRenderedEvent($this->share, BeforeTemplateRenderedEvent::SCOPE_PUBLIC_SHARE_AUTH));
196
-
197
-		$response = new TemplateResponse('core', 'publicshareauth', $templateParameters, 'guest');
198
-		if ($this->share->getSendPasswordByTalk()) {
199
-			$csp = new ContentSecurityPolicy();
200
-			$csp->addAllowedConnectDomain('*');
201
-			$csp->addAllowedMediaDomain('blob:');
202
-			$response->setContentSecurityPolicy($csp);
203
-		}
204
-
205
-		return $response;
206
-	}
207
-
208
-	protected function verifyPassword(string $password): bool {
209
-		return $this->shareManager->checkPassword($this->share, $password);
210
-	}
211
-
212
-	protected function getPasswordHash(): string {
213
-		return $this->share->getPassword();
214
-	}
215
-
216
-	public function isValidToken(): bool {
217
-		try {
218
-			$this->share = $this->shareManager->getShareByToken($this->getToken());
219
-		} catch (ShareNotFound $e) {
220
-			return false;
221
-		}
222
-
223
-		return true;
224
-	}
225
-
226
-	protected function isPasswordProtected(): bool {
227
-		return $this->share->getPassword() !== null;
228
-	}
229
-
230
-	protected function authSucceeded() {
231
-		// For share this was always set so it is still used in other apps
232
-		$this->session->set('public_link_authenticated', (string)$this->share->getId());
233
-	}
234
-
235
-	protected function authFailed() {
236
-		$this->emitAccessShareHook($this->share, 403, 'Wrong password');
237
-	}
238
-
239
-	/**
240
-	 * throws hooks when a share is attempted to be accessed
241
-	 *
242
-	 * @param \OCP\Share\IShare|string $share the Share instance if available,
243
-	 * otherwise token
244
-	 * @param int $errorCode
245
-	 * @param string $errorMessage
246
-	 * @throws \OC\HintException
247
-	 * @throws \OC\ServerNotAvailableException
248
-	 */
249
-	protected function emitAccessShareHook($share, $errorCode = 200, $errorMessage = '') {
250
-		$itemType = $itemSource = $uidOwner = '';
251
-		$token = $share;
252
-		$exception = null;
253
-		if ($share instanceof \OCP\Share\IShare) {
254
-			try {
255
-				$token = $share->getToken();
256
-				$uidOwner = $share->getSharedBy();
257
-				$itemType = $share->getNodeType();
258
-				$itemSource = $share->getNodeId();
259
-			} catch (\Exception $e) {
260
-				// we log what we know and pass on the exception afterwards
261
-				$exception = $e;
262
-			}
263
-		}
264
-		\OC_Hook::emit(Share::class, 'share_link_access', [
265
-			'itemType' => $itemType,
266
-			'itemSource' => $itemSource,
267
-			'uidOwner' => $uidOwner,
268
-			'token' => $token,
269
-			'errorCode' => $errorCode,
270
-			'errorMessage' => $errorMessage,
271
-		]);
272
-		if (!is_null($exception)) {
273
-			throw $exception;
274
-		}
275
-	}
276
-
277
-	/**
278
-	 * Validate the permissions of the share
279
-	 *
280
-	 * @param Share\IShare $share
281
-	 * @return bool
282
-	 */
283
-	private function validateShare(\OCP\Share\IShare $share) {
284
-		// If the owner is disabled no access to the linke is granted
285
-		$owner = $this->userManager->get($share->getShareOwner());
286
-		if ($owner === null || !$owner->isEnabled()) {
287
-			return false;
288
-		}
289
-
290
-		// If the initiator of the share is disabled no access is granted
291
-		$initiator = $this->userManager->get($share->getSharedBy());
292
-		if ($initiator === null || !$initiator->isEnabled()) {
293
-			return false;
294
-		}
295
-
296
-		return $share->getNode()->isReadable() && $share->getNode()->isShareable();
297
-	}
298
-
299
-	/**
300
-	 * @PublicPage
301
-	 * @NoCSRFRequired
302
-	 *
303
-	 *
304
-	 * @param string $path
305
-	 * @return TemplateResponse
306
-	 * @throws NotFoundException
307
-	 * @throws \Exception
308
-	 */
309
-	public function showShare($path = ''): TemplateResponse {
310
-		\OC_User::setIncognitoMode(true);
311
-
312
-		// Check whether share exists
313
-		try {
314
-			$share = $this->shareManager->getShareByToken($this->getToken());
315
-		} catch (ShareNotFound $e) {
316
-			$this->emitAccessShareHook($this->getToken(), 404, 'Share not found');
317
-			throw new NotFoundException();
318
-		}
319
-
320
-		if (!$this->validateShare($share)) {
321
-			throw new NotFoundException();
322
-		}
323
-
324
-		$shareNode = $share->getNode();
325
-
326
-		// We can't get the path of a file share
327
-		try {
328
-			if ($shareNode instanceof \OCP\Files\File && $path !== '') {
329
-				$this->emitAccessShareHook($share, 404, 'Share not found');
330
-				throw new NotFoundException();
331
-			}
332
-		} catch (\Exception $e) {
333
-			$this->emitAccessShareHook($share, 404, 'Share not found');
334
-			throw $e;
335
-		}
336
-
337
-		$shareTmpl = [];
338
-		$shareTmpl['owner'] = '';
339
-		$shareTmpl['shareOwner'] = '';
340
-
341
-		$owner = $this->userManager->get($share->getShareOwner());
342
-		if ($owner instanceof IUser) {
343
-			$ownerAccount = $this->accountManager->getAccount($owner);
344
-
345
-			$ownerName = $ownerAccount->getProperty(IAccountManager::PROPERTY_DISPLAYNAME);
346
-			if ($ownerName->getScope() === IAccountManager::SCOPE_PUBLISHED) {
347
-				$shareTmpl['owner'] = $owner->getUID();
348
-				$shareTmpl['shareOwner'] = $owner->getDisplayName();
349
-			}
350
-		}
351
-
352
-		$shareTmpl['filename'] = $shareNode->getName();
353
-		$shareTmpl['directory_path'] = $share->getTarget();
354
-		$shareTmpl['note'] = $share->getNote();
355
-		$shareTmpl['mimetype'] = $shareNode->getMimetype();
356
-		$shareTmpl['previewSupported'] = $this->previewManager->isMimeSupported($shareNode->getMimetype());
357
-		$shareTmpl['dirToken'] = $this->getToken();
358
-		$shareTmpl['sharingToken'] = $this->getToken();
359
-		$shareTmpl['server2serversharing'] = $this->federatedShareProvider->isOutgoingServer2serverShareEnabled();
360
-		$shareTmpl['protected'] = $share->getPassword() !== null ? 'true' : 'false';
361
-		$shareTmpl['dir'] = '';
362
-		$shareTmpl['nonHumanFileSize'] = $shareNode->getSize();
363
-		$shareTmpl['fileSize'] = \OCP\Util::humanFileSize($shareNode->getSize());
364
-		$shareTmpl['hideDownload'] = $share->getHideDownload();
365
-
366
-		$hideFileList = false;
367
-
368
-		if ($shareNode instanceof \OCP\Files\Folder) {
369
-			$shareIsFolder = true;
370
-
371
-			try {
372
-				$folderNode = $shareNode->get($path);
373
-			} catch (\OCP\Files\NotFoundException $e) {
374
-				$this->emitAccessShareHook($share, 404, 'Share not found');
375
-				throw new NotFoundException();
376
-			}
377
-
378
-			$shareTmpl['dir'] = $shareNode->getRelativePath($folderNode->getPath());
379
-
380
-			/*
88
+    /** @var IConfig */
89
+    protected $config;
90
+    /** @var IUserManager */
91
+    protected $userManager;
92
+    /** @var ILogger */
93
+    protected $logger;
94
+    /** @var \OCP\Activity\IManager */
95
+    protected $activityManager;
96
+    /** @var IPreview */
97
+    protected $previewManager;
98
+    /** @var IRootFolder */
99
+    protected $rootFolder;
100
+    /** @var FederatedShareProvider */
101
+    protected $federatedShareProvider;
102
+    /** @var IAccountManager */
103
+    protected $accountManager;
104
+    /** @var IEventDispatcher */
105
+    protected $eventDispatcher;
106
+    /** @var IL10N */
107
+    protected $l10n;
108
+    /** @var Defaults */
109
+    protected $defaults;
110
+    /** @var ShareManager */
111
+    protected $shareManager;
112
+
113
+    /** @var Share\IShare */
114
+    protected $share;
115
+
116
+    /**
117
+     * @param string $appName
118
+     * @param IRequest $request
119
+     * @param IConfig $config
120
+     * @param IURLGenerator $urlGenerator
121
+     * @param IUserManager $userManager
122
+     * @param ILogger $logger
123
+     * @param \OCP\Activity\IManager $activityManager
124
+     * @param \OCP\Share\IManager $shareManager
125
+     * @param ISession $session
126
+     * @param IPreview $previewManager
127
+     * @param IRootFolder $rootFolder
128
+     * @param FederatedShareProvider $federatedShareProvider
129
+     * @param IAccountManager $accountManager
130
+     * @param IEventDispatcher $eventDispatcher
131
+     * @param IL10N $l10n
132
+     * @param Defaults $defaults
133
+     */
134
+    public function __construct(string $appName,
135
+                                IRequest $request,
136
+                                IConfig $config,
137
+                                IURLGenerator $urlGenerator,
138
+                                IUserManager $userManager,
139
+                                ILogger $logger,
140
+                                \OCP\Activity\IManager $activityManager,
141
+                                ShareManager $shareManager,
142
+                                ISession $session,
143
+                                IPreview $previewManager,
144
+                                IRootFolder $rootFolder,
145
+                                FederatedShareProvider $federatedShareProvider,
146
+                                IAccountManager $accountManager,
147
+                                IEventDispatcher $eventDispatcher,
148
+                                IL10N $l10n,
149
+                                Defaults $defaults) {
150
+        parent::__construct($appName, $request, $session, $urlGenerator);
151
+
152
+        $this->config = $config;
153
+        $this->userManager = $userManager;
154
+        $this->logger = $logger;
155
+        $this->activityManager = $activityManager;
156
+        $this->previewManager = $previewManager;
157
+        $this->rootFolder = $rootFolder;
158
+        $this->federatedShareProvider = $federatedShareProvider;
159
+        $this->accountManager = $accountManager;
160
+        $this->eventDispatcher = $eventDispatcher;
161
+        $this->l10n = $l10n;
162
+        $this->defaults = $defaults;
163
+        $this->shareManager = $shareManager;
164
+    }
165
+
166
+    /**
167
+     * @PublicPage
168
+     * @NoCSRFRequired
169
+     *
170
+     * Show the authentication page
171
+     * The form has to submit to the authenticate method route
172
+     */
173
+    public function showAuthenticate(): TemplateResponse {
174
+        $templateParameters = ['share' => $this->share];
175
+
176
+        $this->eventDispatcher->dispatchTyped(new BeforeTemplateRenderedEvent($this->share, BeforeTemplateRenderedEvent::SCOPE_PUBLIC_SHARE_AUTH));
177
+
178
+        $response = new TemplateResponse('core', 'publicshareauth', $templateParameters, 'guest');
179
+        if ($this->share->getSendPasswordByTalk()) {
180
+            $csp = new ContentSecurityPolicy();
181
+            $csp->addAllowedConnectDomain('*');
182
+            $csp->addAllowedMediaDomain('blob:');
183
+            $response->setContentSecurityPolicy($csp);
184
+        }
185
+
186
+        return $response;
187
+    }
188
+
189
+    /**
190
+     * The template to show when authentication failed
191
+     */
192
+    protected function showAuthFailed(): TemplateResponse {
193
+        $templateParameters = ['share' => $this->share, 'wrongpw' => true];
194
+
195
+        $this->eventDispatcher->dispatchTyped(new BeforeTemplateRenderedEvent($this->share, BeforeTemplateRenderedEvent::SCOPE_PUBLIC_SHARE_AUTH));
196
+
197
+        $response = new TemplateResponse('core', 'publicshareauth', $templateParameters, 'guest');
198
+        if ($this->share->getSendPasswordByTalk()) {
199
+            $csp = new ContentSecurityPolicy();
200
+            $csp->addAllowedConnectDomain('*');
201
+            $csp->addAllowedMediaDomain('blob:');
202
+            $response->setContentSecurityPolicy($csp);
203
+        }
204
+
205
+        return $response;
206
+    }
207
+
208
+    protected function verifyPassword(string $password): bool {
209
+        return $this->shareManager->checkPassword($this->share, $password);
210
+    }
211
+
212
+    protected function getPasswordHash(): string {
213
+        return $this->share->getPassword();
214
+    }
215
+
216
+    public function isValidToken(): bool {
217
+        try {
218
+            $this->share = $this->shareManager->getShareByToken($this->getToken());
219
+        } catch (ShareNotFound $e) {
220
+            return false;
221
+        }
222
+
223
+        return true;
224
+    }
225
+
226
+    protected function isPasswordProtected(): bool {
227
+        return $this->share->getPassword() !== null;
228
+    }
229
+
230
+    protected function authSucceeded() {
231
+        // For share this was always set so it is still used in other apps
232
+        $this->session->set('public_link_authenticated', (string)$this->share->getId());
233
+    }
234
+
235
+    protected function authFailed() {
236
+        $this->emitAccessShareHook($this->share, 403, 'Wrong password');
237
+    }
238
+
239
+    /**
240
+     * throws hooks when a share is attempted to be accessed
241
+     *
242
+     * @param \OCP\Share\IShare|string $share the Share instance if available,
243
+     * otherwise token
244
+     * @param int $errorCode
245
+     * @param string $errorMessage
246
+     * @throws \OC\HintException
247
+     * @throws \OC\ServerNotAvailableException
248
+     */
249
+    protected function emitAccessShareHook($share, $errorCode = 200, $errorMessage = '') {
250
+        $itemType = $itemSource = $uidOwner = '';
251
+        $token = $share;
252
+        $exception = null;
253
+        if ($share instanceof \OCP\Share\IShare) {
254
+            try {
255
+                $token = $share->getToken();
256
+                $uidOwner = $share->getSharedBy();
257
+                $itemType = $share->getNodeType();
258
+                $itemSource = $share->getNodeId();
259
+            } catch (\Exception $e) {
260
+                // we log what we know and pass on the exception afterwards
261
+                $exception = $e;
262
+            }
263
+        }
264
+        \OC_Hook::emit(Share::class, 'share_link_access', [
265
+            'itemType' => $itemType,
266
+            'itemSource' => $itemSource,
267
+            'uidOwner' => $uidOwner,
268
+            'token' => $token,
269
+            'errorCode' => $errorCode,
270
+            'errorMessage' => $errorMessage,
271
+        ]);
272
+        if (!is_null($exception)) {
273
+            throw $exception;
274
+        }
275
+    }
276
+
277
+    /**
278
+     * Validate the permissions of the share
279
+     *
280
+     * @param Share\IShare $share
281
+     * @return bool
282
+     */
283
+    private function validateShare(\OCP\Share\IShare $share) {
284
+        // If the owner is disabled no access to the linke is granted
285
+        $owner = $this->userManager->get($share->getShareOwner());
286
+        if ($owner === null || !$owner->isEnabled()) {
287
+            return false;
288
+        }
289
+
290
+        // If the initiator of the share is disabled no access is granted
291
+        $initiator = $this->userManager->get($share->getSharedBy());
292
+        if ($initiator === null || !$initiator->isEnabled()) {
293
+            return false;
294
+        }
295
+
296
+        return $share->getNode()->isReadable() && $share->getNode()->isShareable();
297
+    }
298
+
299
+    /**
300
+     * @PublicPage
301
+     * @NoCSRFRequired
302
+     *
303
+     *
304
+     * @param string $path
305
+     * @return TemplateResponse
306
+     * @throws NotFoundException
307
+     * @throws \Exception
308
+     */
309
+    public function showShare($path = ''): TemplateResponse {
310
+        \OC_User::setIncognitoMode(true);
311
+
312
+        // Check whether share exists
313
+        try {
314
+            $share = $this->shareManager->getShareByToken($this->getToken());
315
+        } catch (ShareNotFound $e) {
316
+            $this->emitAccessShareHook($this->getToken(), 404, 'Share not found');
317
+            throw new NotFoundException();
318
+        }
319
+
320
+        if (!$this->validateShare($share)) {
321
+            throw new NotFoundException();
322
+        }
323
+
324
+        $shareNode = $share->getNode();
325
+
326
+        // We can't get the path of a file share
327
+        try {
328
+            if ($shareNode instanceof \OCP\Files\File && $path !== '') {
329
+                $this->emitAccessShareHook($share, 404, 'Share not found');
330
+                throw new NotFoundException();
331
+            }
332
+        } catch (\Exception $e) {
333
+            $this->emitAccessShareHook($share, 404, 'Share not found');
334
+            throw $e;
335
+        }
336
+
337
+        $shareTmpl = [];
338
+        $shareTmpl['owner'] = '';
339
+        $shareTmpl['shareOwner'] = '';
340
+
341
+        $owner = $this->userManager->get($share->getShareOwner());
342
+        if ($owner instanceof IUser) {
343
+            $ownerAccount = $this->accountManager->getAccount($owner);
344
+
345
+            $ownerName = $ownerAccount->getProperty(IAccountManager::PROPERTY_DISPLAYNAME);
346
+            if ($ownerName->getScope() === IAccountManager::SCOPE_PUBLISHED) {
347
+                $shareTmpl['owner'] = $owner->getUID();
348
+                $shareTmpl['shareOwner'] = $owner->getDisplayName();
349
+            }
350
+        }
351
+
352
+        $shareTmpl['filename'] = $shareNode->getName();
353
+        $shareTmpl['directory_path'] = $share->getTarget();
354
+        $shareTmpl['note'] = $share->getNote();
355
+        $shareTmpl['mimetype'] = $shareNode->getMimetype();
356
+        $shareTmpl['previewSupported'] = $this->previewManager->isMimeSupported($shareNode->getMimetype());
357
+        $shareTmpl['dirToken'] = $this->getToken();
358
+        $shareTmpl['sharingToken'] = $this->getToken();
359
+        $shareTmpl['server2serversharing'] = $this->federatedShareProvider->isOutgoingServer2serverShareEnabled();
360
+        $shareTmpl['protected'] = $share->getPassword() !== null ? 'true' : 'false';
361
+        $shareTmpl['dir'] = '';
362
+        $shareTmpl['nonHumanFileSize'] = $shareNode->getSize();
363
+        $shareTmpl['fileSize'] = \OCP\Util::humanFileSize($shareNode->getSize());
364
+        $shareTmpl['hideDownload'] = $share->getHideDownload();
365
+
366
+        $hideFileList = false;
367
+
368
+        if ($shareNode instanceof \OCP\Files\Folder) {
369
+            $shareIsFolder = true;
370
+
371
+            try {
372
+                $folderNode = $shareNode->get($path);
373
+            } catch (\OCP\Files\NotFoundException $e) {
374
+                $this->emitAccessShareHook($share, 404, 'Share not found');
375
+                throw new NotFoundException();
376
+            }
377
+
378
+            $shareTmpl['dir'] = $shareNode->getRelativePath($folderNode->getPath());
379
+
380
+            /*
381 381
 			 * The OC_Util methods require a view. This just uses the node API
382 382
 			 */
383
-			$freeSpace = $share->getNode()->getStorage()->free_space($share->getNode()->getInternalPath());
384
-			if ($freeSpace < \OCP\Files\FileInfo::SPACE_UNLIMITED) {
385
-				$freeSpace = max($freeSpace, 0);
386
-			} else {
387
-				$freeSpace = (INF > 0) ? INF: PHP_INT_MAX; // work around https://bugs.php.net/bug.php?id=69188
388
-			}
389
-
390
-			$hideFileList = !($share->getPermissions() & \OCP\Constants::PERMISSION_READ);
391
-			$maxUploadFilesize = $freeSpace;
392
-
393
-			$folder = new Template('files', 'list', '');
394
-
395
-			$folder->assign('dir', $shareNode->getRelativePath($folderNode->getPath()));
396
-			$folder->assign('dirToken', $this->getToken());
397
-			$folder->assign('permissions', \OCP\Constants::PERMISSION_READ);
398
-			$folder->assign('isPublic', true);
399
-			$folder->assign('hideFileList', $hideFileList);
400
-			$folder->assign('publicUploadEnabled', 'no');
401
-			// default to list view
402
-			$folder->assign('showgridview', false);
403
-			$folder->assign('uploadMaxFilesize', $maxUploadFilesize);
404
-			$folder->assign('uploadMaxHumanFilesize', \OCP\Util::humanFileSize($maxUploadFilesize));
405
-			$folder->assign('freeSpace', $freeSpace);
406
-			$folder->assign('usedSpacePercent', 0);
407
-			$folder->assign('trash', false);
408
-			$shareTmpl['folder'] = $folder->fetchPage();
409
-		} else {
410
-			$shareIsFolder = false;
411
-		}
412
-
413
-		// default to list view
414
-		$shareTmpl['showgridview'] = false;
415
-
416
-		$shareTmpl['hideFileList'] = $hideFileList;
417
-		$shareTmpl['downloadURL'] = $this->urlGenerator->linkToRouteAbsolute('files_sharing.sharecontroller.downloadShare', [
418
-			'token' => $this->getToken(),
419
-			'filename' => $shareIsFolder ? null : $shareNode->getName()
420
-		]);
421
-		$shareTmpl['shareUrl'] = $this->urlGenerator->linkToRouteAbsolute('files_sharing.sharecontroller.showShare', ['token' => $this->getToken()]);
422
-		$shareTmpl['maxSizeAnimateGif'] = $this->config->getSystemValue('max_filesize_animated_gifs_public_sharing', 10);
423
-		$shareTmpl['previewEnabled'] = $this->config->getSystemValue('enable_previews', true);
424
-		$shareTmpl['previewMaxX'] = $this->config->getSystemValue('preview_max_x', 1024);
425
-		$shareTmpl['previewMaxY'] = $this->config->getSystemValue('preview_max_y', 1024);
426
-		$shareTmpl['disclaimer'] = $this->config->getAppValue('core', 'shareapi_public_link_disclaimertext', null);
427
-		$shareTmpl['previewURL'] = $shareTmpl['downloadURL'];
428
-
429
-		if ($shareTmpl['previewSupported']) {
430
-			$shareTmpl['previewImage'] = $this->urlGenerator->linkToRouteAbsolute('files_sharing.PublicPreview.getPreview',
431
-				['x' => 200, 'y' => 200, 'file' => $shareTmpl['directory_path'], 'token' => $shareTmpl['dirToken']]);
432
-			$ogPreview = $shareTmpl['previewImage'];
433
-
434
-			// We just have direct previews for image files
435
-			if ($shareNode->getMimePart() === 'image') {
436
-				$shareTmpl['previewURL'] = $this->urlGenerator->linkToRouteAbsolute('files_sharing.publicpreview.directLink', ['token' => $this->getToken()]);
437
-
438
-				$ogPreview = $shareTmpl['previewURL'];
439
-
440
-				//Whatapp is kind of picky about their size requirements
441
-				if ($this->request->isUserAgent(['/^WhatsApp/'])) {
442
-					$ogPreview = $this->urlGenerator->linkToRouteAbsolute('files_sharing.PublicPreview.getPreview', [
443
-						'token' => $this->getToken(),
444
-						'x' => 256,
445
-						'y' => 256,
446
-						'a' => true,
447
-					]);
448
-				}
449
-			}
450
-		} else {
451
-			$shareTmpl['previewImage'] = $this->urlGenerator->getAbsoluteURL($this->urlGenerator->imagePath('core', 'favicon-fb.png'));
452
-			$ogPreview = $shareTmpl['previewImage'];
453
-		}
454
-
455
-		// Load files we need
456
-		\OCP\Util::addScript('files', 'semaphore');
457
-		\OCP\Util::addScript('files', 'file-upload');
458
-		\OCP\Util::addStyle('files_sharing', 'publicView');
459
-		\OCP\Util::addScript('files_sharing', 'public');
460
-		\OCP\Util::addScript('files_sharing', 'templates');
461
-		\OCP\Util::addScript('files', 'fileactions');
462
-		\OCP\Util::addScript('files', 'fileactionsmenu');
463
-		\OCP\Util::addScript('files', 'jquery.fileupload');
464
-		\OCP\Util::addScript('files_sharing', 'files_drop');
465
-
466
-		if (isset($shareTmpl['folder'])) {
467
-			// JS required for folders
468
-			\OCP\Util::addStyle('files', 'merged');
469
-			\OCP\Util::addScript('files', 'filesummary');
470
-			\OCP\Util::addScript('files', 'templates');
471
-			\OCP\Util::addScript('files', 'breadcrumb');
472
-			\OCP\Util::addScript('files', 'fileinfomodel');
473
-			\OCP\Util::addScript('files', 'newfilemenu');
474
-			\OCP\Util::addScript('files', 'files');
475
-			\OCP\Util::addScript('files', 'filemultiselectmenu');
476
-			\OCP\Util::addScript('files', 'filelist');
477
-			\OCP\Util::addScript('files', 'keyboardshortcuts');
478
-			\OCP\Util::addScript('files', 'operationprogressbar');
479
-
480
-			// Load Viewer scripts
481
-			if (class_exists(LoadViewer::class)) {
482
-				$this->eventDispatcher->dispatchTyped(new LoadViewer());
483
-			}
484
-		}
485
-
486
-		// OpenGraph Support: http://ogp.me/
487
-		\OCP\Util::addHeader('meta', ['property' => "og:title", 'content' => $shareTmpl['filename']]);
488
-		\OCP\Util::addHeader('meta', ['property' => "og:description", 'content' => $this->defaults->getName() . ($this->defaults->getSlogan() !== '' ? ' - ' . $this->defaults->getSlogan() : '')]);
489
-		\OCP\Util::addHeader('meta', ['property' => "og:site_name", 'content' => $this->defaults->getName()]);
490
-		\OCP\Util::addHeader('meta', ['property' => "og:url", 'content' => $shareTmpl['shareUrl']]);
491
-		\OCP\Util::addHeader('meta', ['property' => "og:type", 'content' => "object"]);
492
-		\OCP\Util::addHeader('meta', ['property' => "og:image", 'content' => $ogPreview]);
493
-
494
-		$this->eventDispatcher->dispatchTyped(new BeforeTemplateRenderedEvent($share));
495
-
496
-		$csp = new \OCP\AppFramework\Http\ContentSecurityPolicy();
497
-		$csp->addAllowedFrameDomain('\'self\'');
498
-
499
-		$response = new PublicTemplateResponse($this->appName, 'public', $shareTmpl);
500
-		$response->setHeaderTitle($shareTmpl['filename']);
501
-		if ($shareTmpl['shareOwner'] !== '') {
502
-			$response->setHeaderDetails($this->l10n->t('shared by %s', [$shareTmpl['shareOwner']]));
503
-		}
504
-
505
-		$isNoneFileDropFolder = $shareIsFolder === false || $share->getPermissions() !== \OCP\Constants::PERMISSION_CREATE;
506
-
507
-		if ($isNoneFileDropFolder && !$share->getHideDownload()) {
508
-			\OCP\Util::addScript('files_sharing', 'public_note');
509
-
510
-			$downloadWhite = new SimpleMenuAction('download', $this->l10n->t('Download'), 'icon-download-white', $shareTmpl['downloadURL'], 0);
511
-			$downloadAllWhite = new SimpleMenuAction('download', $this->l10n->t('Download all files'), 'icon-download-white', $shareTmpl['downloadURL'], 0);
512
-			$download = new SimpleMenuAction('download', $this->l10n->t('Download'), 'icon-download', $shareTmpl['downloadURL'], 10, $shareTmpl['fileSize']);
513
-			$downloadAll = new SimpleMenuAction('download', $this->l10n->t('Download all files'), 'icon-download', $shareTmpl['downloadURL'], 10, $shareTmpl['fileSize']);
514
-			$directLink = new LinkMenuAction($this->l10n->t('Direct link'), 'icon-public', $shareTmpl['previewURL']);
515
-			$externalShare = new ExternalShareMenuAction($this->l10n->t('Add to your Nextcloud'), 'icon-external', $shareTmpl['owner'], $shareTmpl['shareOwner'], $shareTmpl['filename']);
516
-
517
-			$responseComposer = [];
518
-
519
-			if ($shareIsFolder) {
520
-				$responseComposer[] = $downloadAllWhite;
521
-				$responseComposer[] = $downloadAll;
522
-			} else {
523
-				$responseComposer[] = $downloadWhite;
524
-				$responseComposer[] = $download;
525
-			}
526
-			$responseComposer[] = $directLink;
527
-			if ($this->federatedShareProvider->isOutgoingServer2serverShareEnabled()) {
528
-				$responseComposer[] = $externalShare;
529
-			}
530
-
531
-			$response->setHeaderActions($responseComposer);
532
-		}
533
-
534
-		$response->setContentSecurityPolicy($csp);
535
-
536
-		$this->emitAccessShareHook($share);
537
-
538
-		return $response;
539
-	}
540
-
541
-	/**
542
-	 * @PublicPage
543
-	 * @NoCSRFRequired
544
-	 * @NoSameSiteCookieRequired
545
-	 *
546
-	 * @param string $token
547
-	 * @param string $files
548
-	 * @param string $path
549
-	 * @param string $downloadStartSecret
550
-	 * @return void|\OCP\AppFramework\Http\Response
551
-	 * @throws NotFoundException
552
-	 */
553
-	public function downloadShare($token, $files = null, $path = '', $downloadStartSecret = '') {
554
-		\OC_User::setIncognitoMode(true);
555
-
556
-		$share = $this->shareManager->getShareByToken($token);
557
-
558
-		if (!($share->getPermissions() & \OCP\Constants::PERMISSION_READ)) {
559
-			return new \OCP\AppFramework\Http\DataResponse('Share has no read permission');
560
-		}
561
-
562
-		$files_list = null;
563
-		if (!is_null($files)) { // download selected files
564
-			$files_list = json_decode($files);
565
-			// in case we get only a single file
566
-			if ($files_list === null) {
567
-				$files_list = [$files];
568
-			}
569
-			// Just in case $files is a single int like '1234'
570
-			if (!is_array($files_list)) {
571
-				$files_list = [$files_list];
572
-			}
573
-		}
574
-
575
-		if (!$this->validateShare($share)) {
576
-			throw new NotFoundException();
577
-		}
578
-
579
-		$userFolder = $this->rootFolder->getUserFolder($share->getShareOwner());
580
-		$originalSharePath = $userFolder->getRelativePath($share->getNode()->getPath());
581
-
582
-
583
-		// Single file share
584
-		if ($share->getNode() instanceof \OCP\Files\File) {
585
-			// Single file download
586
-			$this->singleFileDownloaded($share, $share->getNode());
587
-		}
588
-		// Directory share
589
-		else {
590
-			/** @var \OCP\Files\Folder $node */
591
-			$node = $share->getNode();
592
-
593
-			// Try to get the path
594
-			if ($path !== '') {
595
-				try {
596
-					$node = $node->get($path);
597
-				} catch (NotFoundException $e) {
598
-					$this->emitAccessShareHook($share, 404, 'Share not found');
599
-					return new NotFoundResponse();
600
-				}
601
-			}
602
-
603
-			$originalSharePath = $userFolder->getRelativePath($node->getPath());
604
-
605
-			if ($node instanceof \OCP\Files\File) {
606
-				// Single file download
607
-				$this->singleFileDownloaded($share, $share->getNode());
608
-			} else {
609
-				try {
610
-					if (!empty($files_list)) {
611
-						$this->fileListDownloaded($share, $files_list, $node);
612
-					} else {
613
-						// The folder is downloaded
614
-						$this->singleFileDownloaded($share, $share->getNode());
615
-					}
616
-				} catch (NotFoundException $e) {
617
-					return new NotFoundResponse();
618
-				}
619
-			}
620
-		}
621
-
622
-		/* FIXME: We should do this all nicely in OCP */
623
-		OC_Util::tearDownFS();
624
-		OC_Util::setupFS($share->getShareOwner());
625
-
626
-		/**
627
-		 * this sets a cookie to be able to recognize the start of the download
628
-		 * the content must not be longer than 32 characters and must only contain
629
-		 * alphanumeric characters
630
-		 */
631
-		if (!empty($downloadStartSecret)
632
-			&& !isset($downloadStartSecret[32])
633
-			&& preg_match('!^[a-zA-Z0-9]+$!', $downloadStartSecret) === 1) {
634
-
635
-			// FIXME: set on the response once we use an actual app framework response
636
-			setcookie('ocDownloadStarted', $downloadStartSecret, time() + 20, '/');
637
-		}
638
-
639
-		$this->emitAccessShareHook($share);
640
-
641
-		$server_params = [ 'head' => $this->request->getMethod() === 'HEAD' ];
642
-
643
-		/**
644
-		 * Http range requests support
645
-		 */
646
-		if (isset($_SERVER['HTTP_RANGE'])) {
647
-			$server_params['range'] = $this->request->getHeader('Range');
648
-		}
649
-
650
-		// download selected files
651
-		if (!is_null($files) && $files !== '') {
652
-			// FIXME: The exit is required here because otherwise the AppFramework is trying to add headers as well
653
-			// after dispatching the request which results in a "Cannot modify header information" notice.
654
-			OC_Files::get($originalSharePath, $files_list, $server_params);
655
-			exit();
656
-		} else {
657
-			// FIXME: The exit is required here because otherwise the AppFramework is trying to add headers as well
658
-			// after dispatching the request which results in a "Cannot modify header information" notice.
659
-			OC_Files::get(dirname($originalSharePath), basename($originalSharePath), $server_params);
660
-			exit();
661
-		}
662
-	}
663
-
664
-	/**
665
-	 * create activity for every downloaded file
666
-	 *
667
-	 * @param Share\IShare $share
668
-	 * @param array $files_list
669
-	 * @param \OCP\Files\Folder $node
670
-	 * @throws NotFoundException when trying to download a folder or multiple files of a "hide download" share
671
-	 */
672
-	protected function fileListDownloaded(Share\IShare $share, array $files_list, \OCP\Files\Folder $node) {
673
-		if ($share->getHideDownload() && count($files_list) > 1) {
674
-			throw new NotFoundException('Downloading more than 1 file');
675
-		}
676
-
677
-		foreach ($files_list as $file) {
678
-			$subNode = $node->get($file);
679
-			$this->singleFileDownloaded($share, $subNode);
680
-		}
681
-	}
682
-
683
-	/**
684
-	 * create activity if a single file was downloaded from a link share
685
-	 *
686
-	 * @param Share\IShare $share
687
-	 * @throws NotFoundException when trying to download a folder of a "hide download" share
688
-	 */
689
-	protected function singleFileDownloaded(Share\IShare $share, \OCP\Files\Node $node) {
690
-		if ($share->getHideDownload() && $node instanceof Folder) {
691
-			throw new NotFoundException('Downloading a folder');
692
-		}
693
-
694
-		$fileId = $node->getId();
695
-
696
-		$userFolder = $this->rootFolder->getUserFolder($share->getSharedBy());
697
-		$userNodeList = $userFolder->getById($fileId);
698
-		$userNode = $userNodeList[0];
699
-		$ownerFolder = $this->rootFolder->getUserFolder($share->getShareOwner());
700
-		$userPath = $userFolder->getRelativePath($userNode->getPath());
701
-		$ownerPath = $ownerFolder->getRelativePath($node->getPath());
702
-
703
-		$parameters = [$userPath];
704
-
705
-		if ($share->getShareType() === IShare::TYPE_EMAIL) {
706
-			if ($node instanceof \OCP\Files\File) {
707
-				$subject = Downloads::SUBJECT_SHARED_FILE_BY_EMAIL_DOWNLOADED;
708
-			} else {
709
-				$subject = Downloads::SUBJECT_SHARED_FOLDER_BY_EMAIL_DOWNLOADED;
710
-			}
711
-			$parameters[] = $share->getSharedWith();
712
-		} else {
713
-			if ($node instanceof \OCP\Files\File) {
714
-				$subject = Downloads::SUBJECT_PUBLIC_SHARED_FILE_DOWNLOADED;
715
-			} else {
716
-				$subject = Downloads::SUBJECT_PUBLIC_SHARED_FOLDER_DOWNLOADED;
717
-			}
718
-		}
719
-
720
-		$this->publishActivity($subject, $parameters, $share->getSharedBy(), $fileId, $userPath);
721
-
722
-		if ($share->getShareOwner() !== $share->getSharedBy()) {
723
-			$parameters[0] = $ownerPath;
724
-			$this->publishActivity($subject, $parameters, $share->getShareOwner(), $fileId, $ownerPath);
725
-		}
726
-	}
727
-
728
-	/**
729
-	 * publish activity
730
-	 *
731
-	 * @param string $subject
732
-	 * @param array $parameters
733
-	 * @param string $affectedUser
734
-	 * @param int $fileId
735
-	 * @param string $filePath
736
-	 */
737
-	protected function publishActivity($subject,
738
-										array $parameters,
739
-										$affectedUser,
740
-										$fileId,
741
-										$filePath) {
742
-		$event = $this->activityManager->generateEvent();
743
-		$event->setApp('files_sharing')
744
-			->setType('public_links')
745
-			->setSubject($subject, $parameters)
746
-			->setAffectedUser($affectedUser)
747
-			->setObject('files', $fileId, $filePath);
748
-		$this->activityManager->publish($event);
749
-	}
383
+            $freeSpace = $share->getNode()->getStorage()->free_space($share->getNode()->getInternalPath());
384
+            if ($freeSpace < \OCP\Files\FileInfo::SPACE_UNLIMITED) {
385
+                $freeSpace = max($freeSpace, 0);
386
+            } else {
387
+                $freeSpace = (INF > 0) ? INF: PHP_INT_MAX; // work around https://bugs.php.net/bug.php?id=69188
388
+            }
389
+
390
+            $hideFileList = !($share->getPermissions() & \OCP\Constants::PERMISSION_READ);
391
+            $maxUploadFilesize = $freeSpace;
392
+
393
+            $folder = new Template('files', 'list', '');
394
+
395
+            $folder->assign('dir', $shareNode->getRelativePath($folderNode->getPath()));
396
+            $folder->assign('dirToken', $this->getToken());
397
+            $folder->assign('permissions', \OCP\Constants::PERMISSION_READ);
398
+            $folder->assign('isPublic', true);
399
+            $folder->assign('hideFileList', $hideFileList);
400
+            $folder->assign('publicUploadEnabled', 'no');
401
+            // default to list view
402
+            $folder->assign('showgridview', false);
403
+            $folder->assign('uploadMaxFilesize', $maxUploadFilesize);
404
+            $folder->assign('uploadMaxHumanFilesize', \OCP\Util::humanFileSize($maxUploadFilesize));
405
+            $folder->assign('freeSpace', $freeSpace);
406
+            $folder->assign('usedSpacePercent', 0);
407
+            $folder->assign('trash', false);
408
+            $shareTmpl['folder'] = $folder->fetchPage();
409
+        } else {
410
+            $shareIsFolder = false;
411
+        }
412
+
413
+        // default to list view
414
+        $shareTmpl['showgridview'] = false;
415
+
416
+        $shareTmpl['hideFileList'] = $hideFileList;
417
+        $shareTmpl['downloadURL'] = $this->urlGenerator->linkToRouteAbsolute('files_sharing.sharecontroller.downloadShare', [
418
+            'token' => $this->getToken(),
419
+            'filename' => $shareIsFolder ? null : $shareNode->getName()
420
+        ]);
421
+        $shareTmpl['shareUrl'] = $this->urlGenerator->linkToRouteAbsolute('files_sharing.sharecontroller.showShare', ['token' => $this->getToken()]);
422
+        $shareTmpl['maxSizeAnimateGif'] = $this->config->getSystemValue('max_filesize_animated_gifs_public_sharing', 10);
423
+        $shareTmpl['previewEnabled'] = $this->config->getSystemValue('enable_previews', true);
424
+        $shareTmpl['previewMaxX'] = $this->config->getSystemValue('preview_max_x', 1024);
425
+        $shareTmpl['previewMaxY'] = $this->config->getSystemValue('preview_max_y', 1024);
426
+        $shareTmpl['disclaimer'] = $this->config->getAppValue('core', 'shareapi_public_link_disclaimertext', null);
427
+        $shareTmpl['previewURL'] = $shareTmpl['downloadURL'];
428
+
429
+        if ($shareTmpl['previewSupported']) {
430
+            $shareTmpl['previewImage'] = $this->urlGenerator->linkToRouteAbsolute('files_sharing.PublicPreview.getPreview',
431
+                ['x' => 200, 'y' => 200, 'file' => $shareTmpl['directory_path'], 'token' => $shareTmpl['dirToken']]);
432
+            $ogPreview = $shareTmpl['previewImage'];
433
+
434
+            // We just have direct previews for image files
435
+            if ($shareNode->getMimePart() === 'image') {
436
+                $shareTmpl['previewURL'] = $this->urlGenerator->linkToRouteAbsolute('files_sharing.publicpreview.directLink', ['token' => $this->getToken()]);
437
+
438
+                $ogPreview = $shareTmpl['previewURL'];
439
+
440
+                //Whatapp is kind of picky about their size requirements
441
+                if ($this->request->isUserAgent(['/^WhatsApp/'])) {
442
+                    $ogPreview = $this->urlGenerator->linkToRouteAbsolute('files_sharing.PublicPreview.getPreview', [
443
+                        'token' => $this->getToken(),
444
+                        'x' => 256,
445
+                        'y' => 256,
446
+                        'a' => true,
447
+                    ]);
448
+                }
449
+            }
450
+        } else {
451
+            $shareTmpl['previewImage'] = $this->urlGenerator->getAbsoluteURL($this->urlGenerator->imagePath('core', 'favicon-fb.png'));
452
+            $ogPreview = $shareTmpl['previewImage'];
453
+        }
454
+
455
+        // Load files we need
456
+        \OCP\Util::addScript('files', 'semaphore');
457
+        \OCP\Util::addScript('files', 'file-upload');
458
+        \OCP\Util::addStyle('files_sharing', 'publicView');
459
+        \OCP\Util::addScript('files_sharing', 'public');
460
+        \OCP\Util::addScript('files_sharing', 'templates');
461
+        \OCP\Util::addScript('files', 'fileactions');
462
+        \OCP\Util::addScript('files', 'fileactionsmenu');
463
+        \OCP\Util::addScript('files', 'jquery.fileupload');
464
+        \OCP\Util::addScript('files_sharing', 'files_drop');
465
+
466
+        if (isset($shareTmpl['folder'])) {
467
+            // JS required for folders
468
+            \OCP\Util::addStyle('files', 'merged');
469
+            \OCP\Util::addScript('files', 'filesummary');
470
+            \OCP\Util::addScript('files', 'templates');
471
+            \OCP\Util::addScript('files', 'breadcrumb');
472
+            \OCP\Util::addScript('files', 'fileinfomodel');
473
+            \OCP\Util::addScript('files', 'newfilemenu');
474
+            \OCP\Util::addScript('files', 'files');
475
+            \OCP\Util::addScript('files', 'filemultiselectmenu');
476
+            \OCP\Util::addScript('files', 'filelist');
477
+            \OCP\Util::addScript('files', 'keyboardshortcuts');
478
+            \OCP\Util::addScript('files', 'operationprogressbar');
479
+
480
+            // Load Viewer scripts
481
+            if (class_exists(LoadViewer::class)) {
482
+                $this->eventDispatcher->dispatchTyped(new LoadViewer());
483
+            }
484
+        }
485
+
486
+        // OpenGraph Support: http://ogp.me/
487
+        \OCP\Util::addHeader('meta', ['property' => "og:title", 'content' => $shareTmpl['filename']]);
488
+        \OCP\Util::addHeader('meta', ['property' => "og:description", 'content' => $this->defaults->getName() . ($this->defaults->getSlogan() !== '' ? ' - ' . $this->defaults->getSlogan() : '')]);
489
+        \OCP\Util::addHeader('meta', ['property' => "og:site_name", 'content' => $this->defaults->getName()]);
490
+        \OCP\Util::addHeader('meta', ['property' => "og:url", 'content' => $shareTmpl['shareUrl']]);
491
+        \OCP\Util::addHeader('meta', ['property' => "og:type", 'content' => "object"]);
492
+        \OCP\Util::addHeader('meta', ['property' => "og:image", 'content' => $ogPreview]);
493
+
494
+        $this->eventDispatcher->dispatchTyped(new BeforeTemplateRenderedEvent($share));
495
+
496
+        $csp = new \OCP\AppFramework\Http\ContentSecurityPolicy();
497
+        $csp->addAllowedFrameDomain('\'self\'');
498
+
499
+        $response = new PublicTemplateResponse($this->appName, 'public', $shareTmpl);
500
+        $response->setHeaderTitle($shareTmpl['filename']);
501
+        if ($shareTmpl['shareOwner'] !== '') {
502
+            $response->setHeaderDetails($this->l10n->t('shared by %s', [$shareTmpl['shareOwner']]));
503
+        }
504
+
505
+        $isNoneFileDropFolder = $shareIsFolder === false || $share->getPermissions() !== \OCP\Constants::PERMISSION_CREATE;
506
+
507
+        if ($isNoneFileDropFolder && !$share->getHideDownload()) {
508
+            \OCP\Util::addScript('files_sharing', 'public_note');
509
+
510
+            $downloadWhite = new SimpleMenuAction('download', $this->l10n->t('Download'), 'icon-download-white', $shareTmpl['downloadURL'], 0);
511
+            $downloadAllWhite = new SimpleMenuAction('download', $this->l10n->t('Download all files'), 'icon-download-white', $shareTmpl['downloadURL'], 0);
512
+            $download = new SimpleMenuAction('download', $this->l10n->t('Download'), 'icon-download', $shareTmpl['downloadURL'], 10, $shareTmpl['fileSize']);
513
+            $downloadAll = new SimpleMenuAction('download', $this->l10n->t('Download all files'), 'icon-download', $shareTmpl['downloadURL'], 10, $shareTmpl['fileSize']);
514
+            $directLink = new LinkMenuAction($this->l10n->t('Direct link'), 'icon-public', $shareTmpl['previewURL']);
515
+            $externalShare = new ExternalShareMenuAction($this->l10n->t('Add to your Nextcloud'), 'icon-external', $shareTmpl['owner'], $shareTmpl['shareOwner'], $shareTmpl['filename']);
516
+
517
+            $responseComposer = [];
518
+
519
+            if ($shareIsFolder) {
520
+                $responseComposer[] = $downloadAllWhite;
521
+                $responseComposer[] = $downloadAll;
522
+            } else {
523
+                $responseComposer[] = $downloadWhite;
524
+                $responseComposer[] = $download;
525
+            }
526
+            $responseComposer[] = $directLink;
527
+            if ($this->federatedShareProvider->isOutgoingServer2serverShareEnabled()) {
528
+                $responseComposer[] = $externalShare;
529
+            }
530
+
531
+            $response->setHeaderActions($responseComposer);
532
+        }
533
+
534
+        $response->setContentSecurityPolicy($csp);
535
+
536
+        $this->emitAccessShareHook($share);
537
+
538
+        return $response;
539
+    }
540
+
541
+    /**
542
+     * @PublicPage
543
+     * @NoCSRFRequired
544
+     * @NoSameSiteCookieRequired
545
+     *
546
+     * @param string $token
547
+     * @param string $files
548
+     * @param string $path
549
+     * @param string $downloadStartSecret
550
+     * @return void|\OCP\AppFramework\Http\Response
551
+     * @throws NotFoundException
552
+     */
553
+    public function downloadShare($token, $files = null, $path = '', $downloadStartSecret = '') {
554
+        \OC_User::setIncognitoMode(true);
555
+
556
+        $share = $this->shareManager->getShareByToken($token);
557
+
558
+        if (!($share->getPermissions() & \OCP\Constants::PERMISSION_READ)) {
559
+            return new \OCP\AppFramework\Http\DataResponse('Share has no read permission');
560
+        }
561
+
562
+        $files_list = null;
563
+        if (!is_null($files)) { // download selected files
564
+            $files_list = json_decode($files);
565
+            // in case we get only a single file
566
+            if ($files_list === null) {
567
+                $files_list = [$files];
568
+            }
569
+            // Just in case $files is a single int like '1234'
570
+            if (!is_array($files_list)) {
571
+                $files_list = [$files_list];
572
+            }
573
+        }
574
+
575
+        if (!$this->validateShare($share)) {
576
+            throw new NotFoundException();
577
+        }
578
+
579
+        $userFolder = $this->rootFolder->getUserFolder($share->getShareOwner());
580
+        $originalSharePath = $userFolder->getRelativePath($share->getNode()->getPath());
581
+
582
+
583
+        // Single file share
584
+        if ($share->getNode() instanceof \OCP\Files\File) {
585
+            // Single file download
586
+            $this->singleFileDownloaded($share, $share->getNode());
587
+        }
588
+        // Directory share
589
+        else {
590
+            /** @var \OCP\Files\Folder $node */
591
+            $node = $share->getNode();
592
+
593
+            // Try to get the path
594
+            if ($path !== '') {
595
+                try {
596
+                    $node = $node->get($path);
597
+                } catch (NotFoundException $e) {
598
+                    $this->emitAccessShareHook($share, 404, 'Share not found');
599
+                    return new NotFoundResponse();
600
+                }
601
+            }
602
+
603
+            $originalSharePath = $userFolder->getRelativePath($node->getPath());
604
+
605
+            if ($node instanceof \OCP\Files\File) {
606
+                // Single file download
607
+                $this->singleFileDownloaded($share, $share->getNode());
608
+            } else {
609
+                try {
610
+                    if (!empty($files_list)) {
611
+                        $this->fileListDownloaded($share, $files_list, $node);
612
+                    } else {
613
+                        // The folder is downloaded
614
+                        $this->singleFileDownloaded($share, $share->getNode());
615
+                    }
616
+                } catch (NotFoundException $e) {
617
+                    return new NotFoundResponse();
618
+                }
619
+            }
620
+        }
621
+
622
+        /* FIXME: We should do this all nicely in OCP */
623
+        OC_Util::tearDownFS();
624
+        OC_Util::setupFS($share->getShareOwner());
625
+
626
+        /**
627
+         * this sets a cookie to be able to recognize the start of the download
628
+         * the content must not be longer than 32 characters and must only contain
629
+         * alphanumeric characters
630
+         */
631
+        if (!empty($downloadStartSecret)
632
+            && !isset($downloadStartSecret[32])
633
+            && preg_match('!^[a-zA-Z0-9]+$!', $downloadStartSecret) === 1) {
634
+
635
+            // FIXME: set on the response once we use an actual app framework response
636
+            setcookie('ocDownloadStarted', $downloadStartSecret, time() + 20, '/');
637
+        }
638
+
639
+        $this->emitAccessShareHook($share);
640
+
641
+        $server_params = [ 'head' => $this->request->getMethod() === 'HEAD' ];
642
+
643
+        /**
644
+         * Http range requests support
645
+         */
646
+        if (isset($_SERVER['HTTP_RANGE'])) {
647
+            $server_params['range'] = $this->request->getHeader('Range');
648
+        }
649
+
650
+        // download selected files
651
+        if (!is_null($files) && $files !== '') {
652
+            // FIXME: The exit is required here because otherwise the AppFramework is trying to add headers as well
653
+            // after dispatching the request which results in a "Cannot modify header information" notice.
654
+            OC_Files::get($originalSharePath, $files_list, $server_params);
655
+            exit();
656
+        } else {
657
+            // FIXME: The exit is required here because otherwise the AppFramework is trying to add headers as well
658
+            // after dispatching the request which results in a "Cannot modify header information" notice.
659
+            OC_Files::get(dirname($originalSharePath), basename($originalSharePath), $server_params);
660
+            exit();
661
+        }
662
+    }
663
+
664
+    /**
665
+     * create activity for every downloaded file
666
+     *
667
+     * @param Share\IShare $share
668
+     * @param array $files_list
669
+     * @param \OCP\Files\Folder $node
670
+     * @throws NotFoundException when trying to download a folder or multiple files of a "hide download" share
671
+     */
672
+    protected function fileListDownloaded(Share\IShare $share, array $files_list, \OCP\Files\Folder $node) {
673
+        if ($share->getHideDownload() && count($files_list) > 1) {
674
+            throw new NotFoundException('Downloading more than 1 file');
675
+        }
676
+
677
+        foreach ($files_list as $file) {
678
+            $subNode = $node->get($file);
679
+            $this->singleFileDownloaded($share, $subNode);
680
+        }
681
+    }
682
+
683
+    /**
684
+     * create activity if a single file was downloaded from a link share
685
+     *
686
+     * @param Share\IShare $share
687
+     * @throws NotFoundException when trying to download a folder of a "hide download" share
688
+     */
689
+    protected function singleFileDownloaded(Share\IShare $share, \OCP\Files\Node $node) {
690
+        if ($share->getHideDownload() && $node instanceof Folder) {
691
+            throw new NotFoundException('Downloading a folder');
692
+        }
693
+
694
+        $fileId = $node->getId();
695
+
696
+        $userFolder = $this->rootFolder->getUserFolder($share->getSharedBy());
697
+        $userNodeList = $userFolder->getById($fileId);
698
+        $userNode = $userNodeList[0];
699
+        $ownerFolder = $this->rootFolder->getUserFolder($share->getShareOwner());
700
+        $userPath = $userFolder->getRelativePath($userNode->getPath());
701
+        $ownerPath = $ownerFolder->getRelativePath($node->getPath());
702
+
703
+        $parameters = [$userPath];
704
+
705
+        if ($share->getShareType() === IShare::TYPE_EMAIL) {
706
+            if ($node instanceof \OCP\Files\File) {
707
+                $subject = Downloads::SUBJECT_SHARED_FILE_BY_EMAIL_DOWNLOADED;
708
+            } else {
709
+                $subject = Downloads::SUBJECT_SHARED_FOLDER_BY_EMAIL_DOWNLOADED;
710
+            }
711
+            $parameters[] = $share->getSharedWith();
712
+        } else {
713
+            if ($node instanceof \OCP\Files\File) {
714
+                $subject = Downloads::SUBJECT_PUBLIC_SHARED_FILE_DOWNLOADED;
715
+            } else {
716
+                $subject = Downloads::SUBJECT_PUBLIC_SHARED_FOLDER_DOWNLOADED;
717
+            }
718
+        }
719
+
720
+        $this->publishActivity($subject, $parameters, $share->getSharedBy(), $fileId, $userPath);
721
+
722
+        if ($share->getShareOwner() !== $share->getSharedBy()) {
723
+            $parameters[0] = $ownerPath;
724
+            $this->publishActivity($subject, $parameters, $share->getShareOwner(), $fileId, $ownerPath);
725
+        }
726
+    }
727
+
728
+    /**
729
+     * publish activity
730
+     *
731
+     * @param string $subject
732
+     * @param array $parameters
733
+     * @param string $affectedUser
734
+     * @param int $fileId
735
+     * @param string $filePath
736
+     */
737
+    protected function publishActivity($subject,
738
+                                        array $parameters,
739
+                                        $affectedUser,
740
+                                        $fileId,
741
+                                        $filePath) {
742
+        $event = $this->activityManager->generateEvent();
743
+        $event->setApp('files_sharing')
744
+            ->setType('public_links')
745
+            ->setSubject($subject, $parameters)
746
+            ->setAffectedUser($affectedUser)
747
+            ->setObject('files', $fileId, $filePath);
748
+        $this->activityManager->publish($event);
749
+    }
750 750
 }
Please login to merge, or discard this patch.
apps/provisioning_api/composer/composer/autoload_classmap.php 1 patch
Spacing   +12 added lines, -12 removed lines patch added patch discarded remove patch
@@ -6,16 +6,16 @@
 block discarded – undo
6 6
 $baseDir = $vendorDir;
7 7
 
8 8
 return array(
9
-    'Composer\\InstalledVersions' => $vendorDir . '/composer/InstalledVersions.php',
10
-    'OCA\\Provisioning_API\\AppInfo\\Application' => $baseDir . '/../lib/AppInfo/Application.php',
11
-    'OCA\\Provisioning_API\\Capabilities' => $baseDir . '/../lib/Capabilities.php',
12
-    'OCA\\Provisioning_API\\Controller\\AUserData' => $baseDir . '/../lib/Controller/AUserData.php',
13
-    'OCA\\Provisioning_API\\Controller\\AppConfigController' => $baseDir . '/../lib/Controller/AppConfigController.php',
14
-    'OCA\\Provisioning_API\\Controller\\AppsController' => $baseDir . '/../lib/Controller/AppsController.php',
15
-    'OCA\\Provisioning_API\\Controller\\GroupsController' => $baseDir . '/../lib/Controller/GroupsController.php',
16
-    'OCA\\Provisioning_API\\Controller\\UsersController' => $baseDir . '/../lib/Controller/UsersController.php',
17
-    'OCA\\Provisioning_API\\FederatedShareProviderFactory' => $baseDir . '/../lib/FederatedShareProviderFactory.php',
18
-    'OCA\\Provisioning_API\\Listener\\UserDeletedListener' => $baseDir . '/../lib/Listener/UserDeletedListener.php',
19
-    'OCA\\Provisioning_API\\Middleware\\Exceptions\\NotSubAdminException' => $baseDir . '/../lib/Middleware/Exceptions/NotSubAdminException.php',
20
-    'OCA\\Provisioning_API\\Middleware\\ProvisioningApiMiddleware' => $baseDir . '/../lib/Middleware/ProvisioningApiMiddleware.php',
9
+    'Composer\\InstalledVersions' => $vendorDir.'/composer/InstalledVersions.php',
10
+    'OCA\\Provisioning_API\\AppInfo\\Application' => $baseDir.'/../lib/AppInfo/Application.php',
11
+    'OCA\\Provisioning_API\\Capabilities' => $baseDir.'/../lib/Capabilities.php',
12
+    'OCA\\Provisioning_API\\Controller\\AUserData' => $baseDir.'/../lib/Controller/AUserData.php',
13
+    'OCA\\Provisioning_API\\Controller\\AppConfigController' => $baseDir.'/../lib/Controller/AppConfigController.php',
14
+    'OCA\\Provisioning_API\\Controller\\AppsController' => $baseDir.'/../lib/Controller/AppsController.php',
15
+    'OCA\\Provisioning_API\\Controller\\GroupsController' => $baseDir.'/../lib/Controller/GroupsController.php',
16
+    'OCA\\Provisioning_API\\Controller\\UsersController' => $baseDir.'/../lib/Controller/UsersController.php',
17
+    'OCA\\Provisioning_API\\FederatedShareProviderFactory' => $baseDir.'/../lib/FederatedShareProviderFactory.php',
18
+    'OCA\\Provisioning_API\\Listener\\UserDeletedListener' => $baseDir.'/../lib/Listener/UserDeletedListener.php',
19
+    'OCA\\Provisioning_API\\Middleware\\Exceptions\\NotSubAdminException' => $baseDir.'/../lib/Middleware/Exceptions/NotSubAdminException.php',
20
+    'OCA\\Provisioning_API\\Middleware\\ProvisioningApiMiddleware' => $baseDir.'/../lib/Middleware/ProvisioningApiMiddleware.php',
21 21
 );
Please login to merge, or discard this patch.
apps/provisioning_api/composer/composer/autoload_static.php 1 patch
Spacing   +19 added lines, -19 removed lines patch added patch discarded remove patch
@@ -6,38 +6,38 @@
 block discarded – undo
6 6
 
7 7
 class ComposerStaticInitProvisioning_API
8 8
 {
9
-    public static $prefixLengthsPsr4 = array (
9
+    public static $prefixLengthsPsr4 = array(
10 10
         'O' => 
11
-        array (
11
+        array(
12 12
             'OCA\\Provisioning_API\\' => 21,
13 13
         ),
14 14
     );
15 15
 
16
-    public static $prefixDirsPsr4 = array (
16
+    public static $prefixDirsPsr4 = array(
17 17
         'OCA\\Provisioning_API\\' => 
18
-        array (
19
-            0 => __DIR__ . '/..' . '/../lib',
18
+        array(
19
+            0 => __DIR__.'/..'.'/../lib',
20 20
         ),
21 21
     );
22 22
 
23
-    public static $classMap = array (
24
-        'Composer\\InstalledVersions' => __DIR__ . '/..' . '/composer/InstalledVersions.php',
25
-        'OCA\\Provisioning_API\\AppInfo\\Application' => __DIR__ . '/..' . '/../lib/AppInfo/Application.php',
26
-        'OCA\\Provisioning_API\\Capabilities' => __DIR__ . '/..' . '/../lib/Capabilities.php',
27
-        'OCA\\Provisioning_API\\Controller\\AUserData' => __DIR__ . '/..' . '/../lib/Controller/AUserData.php',
28
-        'OCA\\Provisioning_API\\Controller\\AppConfigController' => __DIR__ . '/..' . '/../lib/Controller/AppConfigController.php',
29
-        'OCA\\Provisioning_API\\Controller\\AppsController' => __DIR__ . '/..' . '/../lib/Controller/AppsController.php',
30
-        'OCA\\Provisioning_API\\Controller\\GroupsController' => __DIR__ . '/..' . '/../lib/Controller/GroupsController.php',
31
-        'OCA\\Provisioning_API\\Controller\\UsersController' => __DIR__ . '/..' . '/../lib/Controller/UsersController.php',
32
-        'OCA\\Provisioning_API\\FederatedShareProviderFactory' => __DIR__ . '/..' . '/../lib/FederatedShareProviderFactory.php',
33
-        'OCA\\Provisioning_API\\Listener\\UserDeletedListener' => __DIR__ . '/..' . '/../lib/Listener/UserDeletedListener.php',
34
-        'OCA\\Provisioning_API\\Middleware\\Exceptions\\NotSubAdminException' => __DIR__ . '/..' . '/../lib/Middleware/Exceptions/NotSubAdminException.php',
35
-        'OCA\\Provisioning_API\\Middleware\\ProvisioningApiMiddleware' => __DIR__ . '/..' . '/../lib/Middleware/ProvisioningApiMiddleware.php',
23
+    public static $classMap = array(
24
+        'Composer\\InstalledVersions' => __DIR__.'/..'.'/composer/InstalledVersions.php',
25
+        'OCA\\Provisioning_API\\AppInfo\\Application' => __DIR__.'/..'.'/../lib/AppInfo/Application.php',
26
+        'OCA\\Provisioning_API\\Capabilities' => __DIR__.'/..'.'/../lib/Capabilities.php',
27
+        'OCA\\Provisioning_API\\Controller\\AUserData' => __DIR__.'/..'.'/../lib/Controller/AUserData.php',
28
+        'OCA\\Provisioning_API\\Controller\\AppConfigController' => __DIR__.'/..'.'/../lib/Controller/AppConfigController.php',
29
+        'OCA\\Provisioning_API\\Controller\\AppsController' => __DIR__.'/..'.'/../lib/Controller/AppsController.php',
30
+        'OCA\\Provisioning_API\\Controller\\GroupsController' => __DIR__.'/..'.'/../lib/Controller/GroupsController.php',
31
+        'OCA\\Provisioning_API\\Controller\\UsersController' => __DIR__.'/..'.'/../lib/Controller/UsersController.php',
32
+        'OCA\\Provisioning_API\\FederatedShareProviderFactory' => __DIR__.'/..'.'/../lib/FederatedShareProviderFactory.php',
33
+        'OCA\\Provisioning_API\\Listener\\UserDeletedListener' => __DIR__.'/..'.'/../lib/Listener/UserDeletedListener.php',
34
+        'OCA\\Provisioning_API\\Middleware\\Exceptions\\NotSubAdminException' => __DIR__.'/..'.'/../lib/Middleware/Exceptions/NotSubAdminException.php',
35
+        'OCA\\Provisioning_API\\Middleware\\ProvisioningApiMiddleware' => __DIR__.'/..'.'/../lib/Middleware/ProvisioningApiMiddleware.php',
36 36
     );
37 37
 
38 38
     public static function getInitializer(ClassLoader $loader)
39 39
     {
40
-        return \Closure::bind(function () use ($loader) {
40
+        return \Closure::bind(function() use ($loader) {
41 41
             $loader->prefixLengthsPsr4 = ComposerStaticInitProvisioning_API::$prefixLengthsPsr4;
42 42
             $loader->prefixDirsPsr4 = ComposerStaticInitProvisioning_API::$prefixDirsPsr4;
43 43
             $loader->classMap = ComposerStaticInitProvisioning_API::$classMap;
Please login to merge, or discard this patch.
apps/provisioning_api/lib/Capabilities.php 1 patch
Indentation   +30 added lines, -30 removed lines patch added patch discarded remove patch
@@ -29,34 +29,34 @@
 block discarded – undo
29 29
 
30 30
 class Capabilities implements ICapability {
31 31
 
32
-	/** @var IAppManager */
33
-	private $appManager;
34
-
35
-	public function __construct(IAppManager $appManager) {
36
-		$this->appManager = $appManager;
37
-	}
38
-
39
-	/**
40
-	 * Function an app uses to return the capabilities
41
-	 *
42
-	 * @return array Array containing the apps capabilities
43
-	 */
44
-	public function getCapabilities() {
45
-		$federationScopesEnabled = false;
46
-
47
-		$federatedFileSharingEnabled = $this->appManager->isEnabledForUser('federatedfilesharing');
48
-		if ($federatedFileSharingEnabled) {
49
-			/** @var FederatedShareProvider $shareProvider */
50
-			$shareProvider = \OC::$server->query(FederatedShareProvider::class);
51
-			$federationScopesEnabled = $shareProvider->isLookupServerUploadEnabled();
52
-		}
53
-
54
-		return [
55
-			'provisioning_api' => [
56
-				'version' => $this->appManager->getAppVersion('provisioning_api'),
57
-				'AccountPropertyScopesVersion' => 2,
58
-				'AccountPropertyScopesFederationEnabled' => $federationScopesEnabled,
59
-			]
60
-		];
61
-	}
32
+    /** @var IAppManager */
33
+    private $appManager;
34
+
35
+    public function __construct(IAppManager $appManager) {
36
+        $this->appManager = $appManager;
37
+    }
38
+
39
+    /**
40
+     * Function an app uses to return the capabilities
41
+     *
42
+     * @return array Array containing the apps capabilities
43
+     */
44
+    public function getCapabilities() {
45
+        $federationScopesEnabled = false;
46
+
47
+        $federatedFileSharingEnabled = $this->appManager->isEnabledForUser('federatedfilesharing');
48
+        if ($federatedFileSharingEnabled) {
49
+            /** @var FederatedShareProvider $shareProvider */
50
+            $shareProvider = \OC::$server->query(FederatedShareProvider::class);
51
+            $federationScopesEnabled = $shareProvider->isLookupServerUploadEnabled();
52
+        }
53
+
54
+        return [
55
+            'provisioning_api' => [
56
+                'version' => $this->appManager->getAppVersion('provisioning_api'),
57
+                'AccountPropertyScopesVersion' => 2,
58
+                'AccountPropertyScopesFederationEnabled' => $federationScopesEnabled,
59
+            ]
60
+        ];
61
+    }
62 62
 }
Please login to merge, or discard this patch.