Completed
Push — master ( 8e884b...bea04d )
by Joas
12:13 queued 11:33
created
lib/private/Mail/Message.php 1 patch
Indentation   +202 added lines, -202 removed lines patch added patch discarded remove patch
@@ -33,234 +33,234 @@
 block discarded – undo
33 33
  * @package OC\Mail
34 34
  */
35 35
 class Message implements IMessage {
36
-	/** @var Swift_Message */
37
-	private $swiftMessage;
36
+    /** @var Swift_Message */
37
+    private $swiftMessage;
38 38
 
39
-	/**
40
-	 * @param Swift_Message $swiftMessage
41
-	 */
42
-	public function __construct(Swift_Message $swiftMessage) {
43
-		$this->swiftMessage = $swiftMessage;
44
-	}
39
+    /**
40
+     * @param Swift_Message $swiftMessage
41
+     */
42
+    public function __construct(Swift_Message $swiftMessage) {
43
+        $this->swiftMessage = $swiftMessage;
44
+    }
45 45
 
46
-	/**
47
-	 * SwiftMailer does currently not work with IDN domains, this function therefore converts the domains
48
-	 * FIXME: Remove this once SwiftMailer supports IDN
49
-	 *
50
-	 * @param array $addresses Array of mail addresses, key will get converted
51
-	 * @return array Converted addresses if `idn_to_ascii` exists
52
-	 */
53
-	protected function convertAddresses($addresses) {
54
-		if (!function_exists('idn_to_ascii')) {
55
-			return $addresses;
56
-		}
46
+    /**
47
+     * SwiftMailer does currently not work with IDN domains, this function therefore converts the domains
48
+     * FIXME: Remove this once SwiftMailer supports IDN
49
+     *
50
+     * @param array $addresses Array of mail addresses, key will get converted
51
+     * @return array Converted addresses if `idn_to_ascii` exists
52
+     */
53
+    protected function convertAddresses($addresses) {
54
+        if (!function_exists('idn_to_ascii')) {
55
+            return $addresses;
56
+        }
57 57
 
58
-		$convertedAddresses = array();
58
+        $convertedAddresses = array();
59 59
 
60
-		foreach($addresses as $email => $readableName) {
61
-			if(!is_numeric($email)) {
62
-				list($name, $domain) = explode('@', $email, 2);
63
-				$domain = idn_to_ascii($domain, 0, INTL_IDNA_VARIANT_UTS46);
64
-				$convertedAddresses[$name.'@'.$domain] = $readableName;
65
-			} else {
66
-				list($name, $domain) = explode('@', $readableName, 2);
67
-				$domain = idn_to_ascii($domain, 0, INTL_IDNA_VARIANT_UTS46);
68
-				$convertedAddresses[$email] = $name.'@'.$domain;
69
-			}
70
-		}
60
+        foreach($addresses as $email => $readableName) {
61
+            if(!is_numeric($email)) {
62
+                list($name, $domain) = explode('@', $email, 2);
63
+                $domain = idn_to_ascii($domain, 0, INTL_IDNA_VARIANT_UTS46);
64
+                $convertedAddresses[$name.'@'.$domain] = $readableName;
65
+            } else {
66
+                list($name, $domain) = explode('@', $readableName, 2);
67
+                $domain = idn_to_ascii($domain, 0, INTL_IDNA_VARIANT_UTS46);
68
+                $convertedAddresses[$email] = $name.'@'.$domain;
69
+            }
70
+        }
71 71
 
72
-		return $convertedAddresses;
73
-	}
72
+        return $convertedAddresses;
73
+    }
74 74
 
75
-	/**
76
-	 * Set the from address of this message.
77
-	 *
78
-	 * If no "From" address is used \OC\Mail\Mailer will use mail_from_address and mail_domain from config.php
79
-	 *
80
-	 * @param array $addresses Example: array('[email protected]', '[email protected]' => 'A name')
81
-	 * @return $this
82
-	 */
83
-	public function setFrom(array $addresses) {
84
-		$addresses = $this->convertAddresses($addresses);
75
+    /**
76
+     * Set the from address of this message.
77
+     *
78
+     * If no "From" address is used \OC\Mail\Mailer will use mail_from_address and mail_domain from config.php
79
+     *
80
+     * @param array $addresses Example: array('[email protected]', '[email protected]' => 'A name')
81
+     * @return $this
82
+     */
83
+    public function setFrom(array $addresses) {
84
+        $addresses = $this->convertAddresses($addresses);
85 85
 
86
-		$this->swiftMessage->setFrom($addresses);
87
-		return $this;
88
-	}
86
+        $this->swiftMessage->setFrom($addresses);
87
+        return $this;
88
+    }
89 89
 
90
-	/**
91
-	 * Get the from address of this message.
92
-	 *
93
-	 * @return array
94
-	 */
95
-	public function getFrom() {
96
-		return $this->swiftMessage->getFrom();
97
-	}
90
+    /**
91
+     * Get the from address of this message.
92
+     *
93
+     * @return array
94
+     */
95
+    public function getFrom() {
96
+        return $this->swiftMessage->getFrom();
97
+    }
98 98
 
99
-	/**
100
-	 * Set the Reply-To address of this message
101
-	 *
102
-	 * @param array $addresses
103
-	 * @return $this
104
-	 */
105
-	public function setReplyTo(array $addresses) {
106
-		$addresses = $this->convertAddresses($addresses);
99
+    /**
100
+     * Set the Reply-To address of this message
101
+     *
102
+     * @param array $addresses
103
+     * @return $this
104
+     */
105
+    public function setReplyTo(array $addresses) {
106
+        $addresses = $this->convertAddresses($addresses);
107 107
 
108
-		$this->swiftMessage->setReplyTo($addresses);
109
-		return $this;
110
-	}
108
+        $this->swiftMessage->setReplyTo($addresses);
109
+        return $this;
110
+    }
111 111
 
112
-	/**
113
-	 * Returns the Reply-To address of this message
114
-	 *
115
-	 * @return array
116
-	 */
117
-	public function getReplyTo() {
118
-		return $this->swiftMessage->getReplyTo();
119
-	}
112
+    /**
113
+     * Returns the Reply-To address of this message
114
+     *
115
+     * @return array
116
+     */
117
+    public function getReplyTo() {
118
+        return $this->swiftMessage->getReplyTo();
119
+    }
120 120
 
121
-	/**
122
-	 * Set the to addresses of this message.
123
-	 *
124
-	 * @param array $recipients Example: array('[email protected]', '[email protected]' => 'A name')
125
-	 * @return $this
126
-	 */
127
-	public function setTo(array $recipients) {
128
-		$recipients = $this->convertAddresses($recipients);
121
+    /**
122
+     * Set the to addresses of this message.
123
+     *
124
+     * @param array $recipients Example: array('[email protected]', '[email protected]' => 'A name')
125
+     * @return $this
126
+     */
127
+    public function setTo(array $recipients) {
128
+        $recipients = $this->convertAddresses($recipients);
129 129
 
130
-		$this->swiftMessage->setTo($recipients);
131
-		return $this;
132
-	}
130
+        $this->swiftMessage->setTo($recipients);
131
+        return $this;
132
+    }
133 133
 
134
-	/**
135
-	 * Get the to address of this message.
136
-	 *
137
-	 * @return array
138
-	 */
139
-	public function getTo() {
140
-		return $this->swiftMessage->getTo();
141
-	}
134
+    /**
135
+     * Get the to address of this message.
136
+     *
137
+     * @return array
138
+     */
139
+    public function getTo() {
140
+        return $this->swiftMessage->getTo();
141
+    }
142 142
 
143
-	/**
144
-	 * Set the CC recipients of this message.
145
-	 *
146
-	 * @param array $recipients Example: array('[email protected]', '[email protected]' => 'A name')
147
-	 * @return $this
148
-	 */
149
-	public function setCc(array $recipients) {
150
-		$recipients = $this->convertAddresses($recipients);
143
+    /**
144
+     * Set the CC recipients of this message.
145
+     *
146
+     * @param array $recipients Example: array('[email protected]', '[email protected]' => 'A name')
147
+     * @return $this
148
+     */
149
+    public function setCc(array $recipients) {
150
+        $recipients = $this->convertAddresses($recipients);
151 151
 
152
-		$this->swiftMessage->setCc($recipients);
153
-		return $this;
154
-	}
152
+        $this->swiftMessage->setCc($recipients);
153
+        return $this;
154
+    }
155 155
 
156
-	/**
157
-	 * Get the cc address of this message.
158
-	 *
159
-	 * @return array
160
-	 */
161
-	public function getCc() {
162
-		return $this->swiftMessage->getCc();
163
-	}
156
+    /**
157
+     * Get the cc address of this message.
158
+     *
159
+     * @return array
160
+     */
161
+    public function getCc() {
162
+        return $this->swiftMessage->getCc();
163
+    }
164 164
 
165
-	/**
166
-	 * Set the BCC recipients of this message.
167
-	 *
168
-	 * @param array $recipients Example: array('[email protected]', '[email protected]' => 'A name')
169
-	 * @return $this
170
-	 */
171
-	public function setBcc(array $recipients) {
172
-		$recipients = $this->convertAddresses($recipients);
165
+    /**
166
+     * Set the BCC recipients of this message.
167
+     *
168
+     * @param array $recipients Example: array('[email protected]', '[email protected]' => 'A name')
169
+     * @return $this
170
+     */
171
+    public function setBcc(array $recipients) {
172
+        $recipients = $this->convertAddresses($recipients);
173 173
 
174
-		$this->swiftMessage->setBcc($recipients);
175
-		return $this;
176
-	}
174
+        $this->swiftMessage->setBcc($recipients);
175
+        return $this;
176
+    }
177 177
 
178
-	/**
179
-	 * Get the Bcc address of this message.
180
-	 *
181
-	 * @return array
182
-	 */
183
-	public function getBcc() {
184
-		return $this->swiftMessage->getBcc();
185
-	}
178
+    /**
179
+     * Get the Bcc address of this message.
180
+     *
181
+     * @return array
182
+     */
183
+    public function getBcc() {
184
+        return $this->swiftMessage->getBcc();
185
+    }
186 186
 
187
-	/**
188
-	 * Set the subject of this message.
189
-	 *
190
-	 * @param $subject
191
-	 * @return $this
192
-	 */
193
-	public function setSubject($subject) {
194
-		$this->swiftMessage->setSubject($subject);
195
-		return $this;
196
-	}
187
+    /**
188
+     * Set the subject of this message.
189
+     *
190
+     * @param $subject
191
+     * @return $this
192
+     */
193
+    public function setSubject($subject) {
194
+        $this->swiftMessage->setSubject($subject);
195
+        return $this;
196
+    }
197 197
 
198
-	/**
199
-	 * Get the from subject of this message.
200
-	 *
201
-	 * @return string
202
-	 */
203
-	public function getSubject() {
204
-		return $this->swiftMessage->getSubject();
205
-	}
198
+    /**
199
+     * Get the from subject of this message.
200
+     *
201
+     * @return string
202
+     */
203
+    public function getSubject() {
204
+        return $this->swiftMessage->getSubject();
205
+    }
206 206
 
207
-	/**
208
-	 * Set the plain-text body of this message.
209
-	 *
210
-	 * @param string $body
211
-	 * @return $this
212
-	 */
213
-	public function setPlainBody($body) {
214
-		$this->swiftMessage->setBody($body);
215
-		return $this;
216
-	}
207
+    /**
208
+     * Set the plain-text body of this message.
209
+     *
210
+     * @param string $body
211
+     * @return $this
212
+     */
213
+    public function setPlainBody($body) {
214
+        $this->swiftMessage->setBody($body);
215
+        return $this;
216
+    }
217 217
 
218
-	/**
219
-	 * Get the plain body of this message.
220
-	 *
221
-	 * @return string
222
-	 */
223
-	public function getPlainBody() {
224
-		return $this->swiftMessage->getBody();
225
-	}
218
+    /**
219
+     * Get the plain body of this message.
220
+     *
221
+     * @return string
222
+     */
223
+    public function getPlainBody() {
224
+        return $this->swiftMessage->getBody();
225
+    }
226 226
 
227
-	/**
228
-	 * Set the HTML body of this message. Consider also sending a plain-text body instead of only an HTML one.
229
-	 *
230
-	 * @param string $body
231
-	 * @return $this
232
-	 */
233
-	public function setHtmlBody($body) {
234
-		$this->swiftMessage->addPart($body, 'text/html');
235
-		return $this;
236
-	}
227
+    /**
228
+     * Set the HTML body of this message. Consider also sending a plain-text body instead of only an HTML one.
229
+     *
230
+     * @param string $body
231
+     * @return $this
232
+     */
233
+    public function setHtmlBody($body) {
234
+        $this->swiftMessage->addPart($body, 'text/html');
235
+        return $this;
236
+    }
237 237
 
238
-	/**
239
-	 * Get's the underlying SwiftMessage
240
-	 * @return Swift_Message
241
-	 */
242
-	public function getSwiftMessage() {
243
-		return $this->swiftMessage;
244
-	}
238
+    /**
239
+     * Get's the underlying SwiftMessage
240
+     * @return Swift_Message
241
+     */
242
+    public function getSwiftMessage() {
243
+        return $this->swiftMessage;
244
+    }
245 245
 
246
-	/**
247
-	 * @param string $body
248
-	 * @param string $contentType
249
-	 * @return $this
250
-	 */
251
-	public function setBody($body, $contentType) {
252
-		$this->swiftMessage->setBody($body, $contentType);
253
-		return $this;
254
-	}
246
+    /**
247
+     * @param string $body
248
+     * @param string $contentType
249
+     * @return $this
250
+     */
251
+    public function setBody($body, $contentType) {
252
+        $this->swiftMessage->setBody($body, $contentType);
253
+        return $this;
254
+    }
255 255
 
256
-	/**
257
-	 * @param IEMailTemplate $emailTemplate
258
-	 * @return $this
259
-	 */
260
-	public function useTemplate(IEMailTemplate $emailTemplate) {
261
-		$this->setSubject($emailTemplate->renderSubject());
262
-		$this->setPlainBody($emailTemplate->renderText());
263
-		$this->setHtmlBody($emailTemplate->renderHtml());
264
-		return $this;
265
-	}
256
+    /**
257
+     * @param IEMailTemplate $emailTemplate
258
+     * @return $this
259
+     */
260
+    public function useTemplate(IEMailTemplate $emailTemplate) {
261
+        $this->setSubject($emailTemplate->renderSubject());
262
+        $this->setPlainBody($emailTemplate->renderText());
263
+        $this->setHtmlBody($emailTemplate->renderHtml());
264
+        return $this;
265
+    }
266 266
 }
Please login to merge, or discard this patch.
core/Controller/LostController.php 1 patch
Indentation   +309 added lines, -309 removed lines patch added patch discarded remove patch
@@ -55,313 +55,313 @@
 block discarded – undo
55 55
  */
56 56
 class LostController extends Controller {
57 57
 
58
-	/** @var IURLGenerator */
59
-	protected $urlGenerator;
60
-	/** @var IUserManager */
61
-	protected $userManager;
62
-	/** @var Defaults */
63
-	protected $defaults;
64
-	/** @var IL10N */
65
-	protected $l10n;
66
-	/** @var string */
67
-	protected $from;
68
-	/** @var IManager */
69
-	protected $encryptionManager;
70
-	/** @var IConfig */
71
-	protected $config;
72
-	/** @var ISecureRandom */
73
-	protected $secureRandom;
74
-	/** @var IMailer */
75
-	protected $mailer;
76
-	/** @var ITimeFactory */
77
-	protected $timeFactory;
78
-	/** @var ICrypto */
79
-	protected $crypto;
80
-
81
-	/**
82
-	 * @param string $appName
83
-	 * @param IRequest $request
84
-	 * @param IURLGenerator $urlGenerator
85
-	 * @param IUserManager $userManager
86
-	 * @param Defaults $defaults
87
-	 * @param IL10N $l10n
88
-	 * @param IConfig $config
89
-	 * @param ISecureRandom $secureRandom
90
-	 * @param string $defaultMailAddress
91
-	 * @param IManager $encryptionManager
92
-	 * @param IMailer $mailer
93
-	 * @param ITimeFactory $timeFactory
94
-	 * @param ICrypto $crypto
95
-	 */
96
-	public function __construct($appName,
97
-								IRequest $request,
98
-								IURLGenerator $urlGenerator,
99
-								IUserManager $userManager,
100
-								Defaults $defaults,
101
-								IL10N $l10n,
102
-								IConfig $config,
103
-								ISecureRandom $secureRandom,
104
-								$defaultMailAddress,
105
-								IManager $encryptionManager,
106
-								IMailer $mailer,
107
-								ITimeFactory $timeFactory,
108
-								ICrypto $crypto) {
109
-		parent::__construct($appName, $request);
110
-		$this->urlGenerator = $urlGenerator;
111
-		$this->userManager = $userManager;
112
-		$this->defaults = $defaults;
113
-		$this->l10n = $l10n;
114
-		$this->secureRandom = $secureRandom;
115
-		$this->from = $defaultMailAddress;
116
-		$this->encryptionManager = $encryptionManager;
117
-		$this->config = $config;
118
-		$this->mailer = $mailer;
119
-		$this->timeFactory = $timeFactory;
120
-		$this->crypto = $crypto;
121
-	}
122
-
123
-	/**
124
-	 * Someone wants to reset their password:
125
-	 *
126
-	 * @PublicPage
127
-	 * @NoCSRFRequired
128
-	 *
129
-	 * @param string $token
130
-	 * @param string $userId
131
-	 * @return TemplateResponse
132
-	 */
133
-	public function resetform($token, $userId) {
134
-		if ($this->config->getSystemValue('lost_password_link', '') !== '') {
135
-			return new TemplateResponse('core', 'error', [
136
-					'errors' => [['error' => $this->l10n->t('Password reset is disabled')]]
137
-				],
138
-				'guest'
139
-			);
140
-		}
141
-
142
-		try {
143
-			$this->checkPasswordResetToken($token, $userId);
144
-		} catch (\Exception $e) {
145
-			return new TemplateResponse(
146
-				'core', 'error', [
147
-					"errors" => array(array("error" => $e->getMessage()))
148
-				],
149
-				'guest'
150
-			);
151
-		}
152
-
153
-		return new TemplateResponse(
154
-			'core',
155
-			'lostpassword/resetpassword',
156
-			array(
157
-				'link' => $this->urlGenerator->linkToRouteAbsolute('core.lost.setPassword', array('userId' => $userId, 'token' => $token)),
158
-			),
159
-			'guest'
160
-		);
161
-	}
162
-
163
-	/**
164
-	 * @param string $token
165
-	 * @param string $userId
166
-	 * @throws \Exception
167
-	 */
168
-	protected function checkPasswordResetToken($token, $userId) {
169
-		$user = $this->userManager->get($userId);
170
-		if($user === null || !$user->isEnabled()) {
171
-			throw new \Exception($this->l10n->t('Couldn\'t reset password because the token is invalid'));
172
-		}
173
-
174
-		try {
175
-			$encryptedToken = $this->config->getUserValue($userId, 'core', 'lostpassword', null);
176
-			$mailAddress = !is_null($user->getEMailAddress()) ? $user->getEMailAddress() : '';
177
-			$decryptedToken = $this->crypto->decrypt($encryptedToken, $mailAddress.$this->config->getSystemValue('secret'));
178
-		} catch (\Exception $e) {
179
-			throw new \Exception($this->l10n->t('Couldn\'t reset password because the token is invalid'));
180
-		}
181
-
182
-		$splittedToken = explode(':', $decryptedToken);
183
-		if(count($splittedToken) !== 2) {
184
-			throw new \Exception($this->l10n->t('Couldn\'t reset password because the token is invalid'));
185
-		}
186
-
187
-		if ($splittedToken[0] < ($this->timeFactory->getTime() - 60*60*12) ||
188
-			$user->getLastLogin() > $splittedToken[0]) {
189
-			throw new \Exception($this->l10n->t('Couldn\'t reset password because the token is expired'));
190
-		}
191
-
192
-		if (!hash_equals($splittedToken[1], $token)) {
193
-			throw new \Exception($this->l10n->t('Couldn\'t reset password because the token is invalid'));
194
-		}
195
-	}
196
-
197
-	/**
198
-	 * @param $message
199
-	 * @param array $additional
200
-	 * @return array
201
-	 */
202
-	private function error($message, array $additional=array()) {
203
-		return array_merge(array('status' => 'error', 'msg' => $message), $additional);
204
-	}
205
-
206
-	/**
207
-	 * @return array
208
-	 */
209
-	private function success() {
210
-		return array('status'=>'success');
211
-	}
212
-
213
-	/**
214
-	 * @PublicPage
215
-	 * @BruteForceProtection(action=passwordResetEmail)
216
-	 * @AnonRateThrottle(limit=10, period=300)
217
-	 *
218
-	 * @param string $user
219
-	 * @return JSONResponse
220
-	 */
221
-	public function email($user){
222
-		if ($this->config->getSystemValue('lost_password_link', '') !== '') {
223
-			return new JSONResponse($this->error($this->l10n->t('Password reset is disabled')));
224
-		}
225
-
226
-		// FIXME: use HTTP error codes
227
-		try {
228
-			$this->sendEmail($user);
229
-		} catch (\Exception $e){
230
-			$response = new JSONResponse($this->error($e->getMessage()));
231
-			$response->throttle();
232
-			return $response;
233
-		}
234
-
235
-		$response = new JSONResponse($this->success());
236
-		$response->throttle();
237
-		return $response;
238
-	}
239
-
240
-	/**
241
-	 * @PublicPage
242
-	 * @param string $token
243
-	 * @param string $userId
244
-	 * @param string $password
245
-	 * @param boolean $proceed
246
-	 * @return array
247
-	 */
248
-	public function setPassword($token, $userId, $password, $proceed) {
249
-		if ($this->config->getSystemValue('lost_password_link', '') !== '') {
250
-			return $this->error($this->l10n->t('Password reset is disabled'));
251
-		}
252
-
253
-		if ($this->encryptionManager->isEnabled() && !$proceed) {
254
-			return $this->error('', array('encryption' => true));
255
-		}
256
-
257
-		try {
258
-			$this->checkPasswordResetToken($token, $userId);
259
-			$user = $this->userManager->get($userId);
260
-
261
-			\OC_Hook::emit('\OC\Core\LostPassword\Controller\LostController', 'pre_passwordReset', array('uid' => $userId, 'password' => $password));
262
-
263
-			if (!$user->setPassword($password)) {
264
-				throw new \Exception();
265
-			}
266
-
267
-			\OC_Hook::emit('\OC\Core\LostPassword\Controller\LostController', 'post_passwordReset', array('uid' => $userId, 'password' => $password));
268
-
269
-			$this->config->deleteUserValue($userId, 'core', 'lostpassword');
270
-			@\OC::$server->getUserSession()->unsetMagicInCookie();
271
-		} catch (\Exception $e){
272
-			return $this->error($e->getMessage());
273
-		}
274
-
275
-		return $this->success();
276
-	}
277
-
278
-	/**
279
-	 * @param string $input
280
-	 * @throws \Exception
281
-	 */
282
-	protected function sendEmail($input) {
283
-		$user = $this->findUserByIdOrMail($input);
284
-		$email = $user->getEMailAddress();
285
-
286
-		if (empty($email)) {
287
-			throw new \Exception(
288
-				$this->l10n->t('Could not send reset email because there is no email address for this username. Please contact your administrator.')
289
-			);
290
-		}
291
-
292
-		// Generate the token. It is stored encrypted in the database with the
293
-		// secret being the users' email address appended with the system secret.
294
-		// This makes the token automatically invalidate once the user changes
295
-		// their email address.
296
-		$token = $this->secureRandom->generate(
297
-			21,
298
-			ISecureRandom::CHAR_DIGITS.
299
-			ISecureRandom::CHAR_LOWER.
300
-			ISecureRandom::CHAR_UPPER
301
-		);
302
-		$tokenValue = $this->timeFactory->getTime() .':'. $token;
303
-		$encryptedValue = $this->crypto->encrypt($tokenValue, $email . $this->config->getSystemValue('secret'));
304
-		$this->config->setUserValue($user->getUID(), 'core', 'lostpassword', $encryptedValue);
305
-
306
-		$link = $this->urlGenerator->linkToRouteAbsolute('core.lost.resetform', array('userId' => $user->getUID(), 'token' => $token));
307
-
308
-		$emailTemplate = $this->mailer->createEMailTemplate('core.ResetPassword', [
309
-			'link' => $link,
310
-		]);
311
-
312
-		$emailTemplate->setSubject($this->l10n->t('%s password reset', [$this->defaults->getName()]));
313
-		$emailTemplate->addHeader();
314
-		$emailTemplate->addHeading($this->l10n->t('Password reset'));
315
-
316
-		$emailTemplate->addBodyText(
317
-			$this->l10n->t('Click the following button to reset your password. If you have not requested the password reset, then ignore this email.'),
318
-			$this->l10n->t('Click the following link to reset your password. If you have not requested the password reset, then ignore this email.')
319
-		);
320
-
321
-		$emailTemplate->addBodyButton(
322
-			$this->l10n->t('Reset your password'),
323
-			$link,
324
-			false
325
-		);
326
-		$emailTemplate->addFooter();
327
-
328
-		try {
329
-			$message = $this->mailer->createMessage();
330
-			$message->setTo([$email => $user->getUID()]);
331
-			$message->setFrom([$this->from => $this->defaults->getName()]);
332
-			$message->useTemplate($emailTemplate);
333
-			$this->mailer->send($message);
334
-		} catch (\Exception $e) {
335
-			throw new \Exception($this->l10n->t(
336
-				'Couldn\'t send reset email. Please contact your administrator.'
337
-			));
338
-		}
339
-	}
340
-
341
-	/**
342
-	 * @param string $input
343
-	 * @return IUser
344
-	 * @throws \InvalidArgumentException
345
-	 */
346
-	protected function findUserByIdOrMail($input) {
347
-		$user = $this->userManager->get($input);
348
-		if ($user instanceof IUser) {
349
-			if (!$user->isEnabled()) {
350
-				throw new \InvalidArgumentException($this->l10n->t('Couldn\'t send reset email. Please make sure your username is correct.'));
351
-			}
352
-
353
-			return $user;
354
-		}
355
-		$users = $this->userManager->getByEmail($input);
356
-		if (count($users) === 1) {
357
-			$user = $users[0];
358
-			if (!$user->isEnabled()) {
359
-				throw new \InvalidArgumentException($this->l10n->t('Couldn\'t send reset email. Please make sure your username is correct.'));
360
-			}
361
-
362
-			return $user;
363
-		}
364
-
365
-		throw new \InvalidArgumentException($this->l10n->t('Couldn\'t send reset email. Please make sure your username is correct.'));
366
-	}
58
+    /** @var IURLGenerator */
59
+    protected $urlGenerator;
60
+    /** @var IUserManager */
61
+    protected $userManager;
62
+    /** @var Defaults */
63
+    protected $defaults;
64
+    /** @var IL10N */
65
+    protected $l10n;
66
+    /** @var string */
67
+    protected $from;
68
+    /** @var IManager */
69
+    protected $encryptionManager;
70
+    /** @var IConfig */
71
+    protected $config;
72
+    /** @var ISecureRandom */
73
+    protected $secureRandom;
74
+    /** @var IMailer */
75
+    protected $mailer;
76
+    /** @var ITimeFactory */
77
+    protected $timeFactory;
78
+    /** @var ICrypto */
79
+    protected $crypto;
80
+
81
+    /**
82
+     * @param string $appName
83
+     * @param IRequest $request
84
+     * @param IURLGenerator $urlGenerator
85
+     * @param IUserManager $userManager
86
+     * @param Defaults $defaults
87
+     * @param IL10N $l10n
88
+     * @param IConfig $config
89
+     * @param ISecureRandom $secureRandom
90
+     * @param string $defaultMailAddress
91
+     * @param IManager $encryptionManager
92
+     * @param IMailer $mailer
93
+     * @param ITimeFactory $timeFactory
94
+     * @param ICrypto $crypto
95
+     */
96
+    public function __construct($appName,
97
+                                IRequest $request,
98
+                                IURLGenerator $urlGenerator,
99
+                                IUserManager $userManager,
100
+                                Defaults $defaults,
101
+                                IL10N $l10n,
102
+                                IConfig $config,
103
+                                ISecureRandom $secureRandom,
104
+                                $defaultMailAddress,
105
+                                IManager $encryptionManager,
106
+                                IMailer $mailer,
107
+                                ITimeFactory $timeFactory,
108
+                                ICrypto $crypto) {
109
+        parent::__construct($appName, $request);
110
+        $this->urlGenerator = $urlGenerator;
111
+        $this->userManager = $userManager;
112
+        $this->defaults = $defaults;
113
+        $this->l10n = $l10n;
114
+        $this->secureRandom = $secureRandom;
115
+        $this->from = $defaultMailAddress;
116
+        $this->encryptionManager = $encryptionManager;
117
+        $this->config = $config;
118
+        $this->mailer = $mailer;
119
+        $this->timeFactory = $timeFactory;
120
+        $this->crypto = $crypto;
121
+    }
122
+
123
+    /**
124
+     * Someone wants to reset their password:
125
+     *
126
+     * @PublicPage
127
+     * @NoCSRFRequired
128
+     *
129
+     * @param string $token
130
+     * @param string $userId
131
+     * @return TemplateResponse
132
+     */
133
+    public function resetform($token, $userId) {
134
+        if ($this->config->getSystemValue('lost_password_link', '') !== '') {
135
+            return new TemplateResponse('core', 'error', [
136
+                    'errors' => [['error' => $this->l10n->t('Password reset is disabled')]]
137
+                ],
138
+                'guest'
139
+            );
140
+        }
141
+
142
+        try {
143
+            $this->checkPasswordResetToken($token, $userId);
144
+        } catch (\Exception $e) {
145
+            return new TemplateResponse(
146
+                'core', 'error', [
147
+                    "errors" => array(array("error" => $e->getMessage()))
148
+                ],
149
+                'guest'
150
+            );
151
+        }
152
+
153
+        return new TemplateResponse(
154
+            'core',
155
+            'lostpassword/resetpassword',
156
+            array(
157
+                'link' => $this->urlGenerator->linkToRouteAbsolute('core.lost.setPassword', array('userId' => $userId, 'token' => $token)),
158
+            ),
159
+            'guest'
160
+        );
161
+    }
162
+
163
+    /**
164
+     * @param string $token
165
+     * @param string $userId
166
+     * @throws \Exception
167
+     */
168
+    protected function checkPasswordResetToken($token, $userId) {
169
+        $user = $this->userManager->get($userId);
170
+        if($user === null || !$user->isEnabled()) {
171
+            throw new \Exception($this->l10n->t('Couldn\'t reset password because the token is invalid'));
172
+        }
173
+
174
+        try {
175
+            $encryptedToken = $this->config->getUserValue($userId, 'core', 'lostpassword', null);
176
+            $mailAddress = !is_null($user->getEMailAddress()) ? $user->getEMailAddress() : '';
177
+            $decryptedToken = $this->crypto->decrypt($encryptedToken, $mailAddress.$this->config->getSystemValue('secret'));
178
+        } catch (\Exception $e) {
179
+            throw new \Exception($this->l10n->t('Couldn\'t reset password because the token is invalid'));
180
+        }
181
+
182
+        $splittedToken = explode(':', $decryptedToken);
183
+        if(count($splittedToken) !== 2) {
184
+            throw new \Exception($this->l10n->t('Couldn\'t reset password because the token is invalid'));
185
+        }
186
+
187
+        if ($splittedToken[0] < ($this->timeFactory->getTime() - 60*60*12) ||
188
+            $user->getLastLogin() > $splittedToken[0]) {
189
+            throw new \Exception($this->l10n->t('Couldn\'t reset password because the token is expired'));
190
+        }
191
+
192
+        if (!hash_equals($splittedToken[1], $token)) {
193
+            throw new \Exception($this->l10n->t('Couldn\'t reset password because the token is invalid'));
194
+        }
195
+    }
196
+
197
+    /**
198
+     * @param $message
199
+     * @param array $additional
200
+     * @return array
201
+     */
202
+    private function error($message, array $additional=array()) {
203
+        return array_merge(array('status' => 'error', 'msg' => $message), $additional);
204
+    }
205
+
206
+    /**
207
+     * @return array
208
+     */
209
+    private function success() {
210
+        return array('status'=>'success');
211
+    }
212
+
213
+    /**
214
+     * @PublicPage
215
+     * @BruteForceProtection(action=passwordResetEmail)
216
+     * @AnonRateThrottle(limit=10, period=300)
217
+     *
218
+     * @param string $user
219
+     * @return JSONResponse
220
+     */
221
+    public function email($user){
222
+        if ($this->config->getSystemValue('lost_password_link', '') !== '') {
223
+            return new JSONResponse($this->error($this->l10n->t('Password reset is disabled')));
224
+        }
225
+
226
+        // FIXME: use HTTP error codes
227
+        try {
228
+            $this->sendEmail($user);
229
+        } catch (\Exception $e){
230
+            $response = new JSONResponse($this->error($e->getMessage()));
231
+            $response->throttle();
232
+            return $response;
233
+        }
234
+
235
+        $response = new JSONResponse($this->success());
236
+        $response->throttle();
237
+        return $response;
238
+    }
239
+
240
+    /**
241
+     * @PublicPage
242
+     * @param string $token
243
+     * @param string $userId
244
+     * @param string $password
245
+     * @param boolean $proceed
246
+     * @return array
247
+     */
248
+    public function setPassword($token, $userId, $password, $proceed) {
249
+        if ($this->config->getSystemValue('lost_password_link', '') !== '') {
250
+            return $this->error($this->l10n->t('Password reset is disabled'));
251
+        }
252
+
253
+        if ($this->encryptionManager->isEnabled() && !$proceed) {
254
+            return $this->error('', array('encryption' => true));
255
+        }
256
+
257
+        try {
258
+            $this->checkPasswordResetToken($token, $userId);
259
+            $user = $this->userManager->get($userId);
260
+
261
+            \OC_Hook::emit('\OC\Core\LostPassword\Controller\LostController', 'pre_passwordReset', array('uid' => $userId, 'password' => $password));
262
+
263
+            if (!$user->setPassword($password)) {
264
+                throw new \Exception();
265
+            }
266
+
267
+            \OC_Hook::emit('\OC\Core\LostPassword\Controller\LostController', 'post_passwordReset', array('uid' => $userId, 'password' => $password));
268
+
269
+            $this->config->deleteUserValue($userId, 'core', 'lostpassword');
270
+            @\OC::$server->getUserSession()->unsetMagicInCookie();
271
+        } catch (\Exception $e){
272
+            return $this->error($e->getMessage());
273
+        }
274
+
275
+        return $this->success();
276
+    }
277
+
278
+    /**
279
+     * @param string $input
280
+     * @throws \Exception
281
+     */
282
+    protected function sendEmail($input) {
283
+        $user = $this->findUserByIdOrMail($input);
284
+        $email = $user->getEMailAddress();
285
+
286
+        if (empty($email)) {
287
+            throw new \Exception(
288
+                $this->l10n->t('Could not send reset email because there is no email address for this username. Please contact your administrator.')
289
+            );
290
+        }
291
+
292
+        // Generate the token. It is stored encrypted in the database with the
293
+        // secret being the users' email address appended with the system secret.
294
+        // This makes the token automatically invalidate once the user changes
295
+        // their email address.
296
+        $token = $this->secureRandom->generate(
297
+            21,
298
+            ISecureRandom::CHAR_DIGITS.
299
+            ISecureRandom::CHAR_LOWER.
300
+            ISecureRandom::CHAR_UPPER
301
+        );
302
+        $tokenValue = $this->timeFactory->getTime() .':'. $token;
303
+        $encryptedValue = $this->crypto->encrypt($tokenValue, $email . $this->config->getSystemValue('secret'));
304
+        $this->config->setUserValue($user->getUID(), 'core', 'lostpassword', $encryptedValue);
305
+
306
+        $link = $this->urlGenerator->linkToRouteAbsolute('core.lost.resetform', array('userId' => $user->getUID(), 'token' => $token));
307
+
308
+        $emailTemplate = $this->mailer->createEMailTemplate('core.ResetPassword', [
309
+            'link' => $link,
310
+        ]);
311
+
312
+        $emailTemplate->setSubject($this->l10n->t('%s password reset', [$this->defaults->getName()]));
313
+        $emailTemplate->addHeader();
314
+        $emailTemplate->addHeading($this->l10n->t('Password reset'));
315
+
316
+        $emailTemplate->addBodyText(
317
+            $this->l10n->t('Click the following button to reset your password. If you have not requested the password reset, then ignore this email.'),
318
+            $this->l10n->t('Click the following link to reset your password. If you have not requested the password reset, then ignore this email.')
319
+        );
320
+
321
+        $emailTemplate->addBodyButton(
322
+            $this->l10n->t('Reset your password'),
323
+            $link,
324
+            false
325
+        );
326
+        $emailTemplate->addFooter();
327
+
328
+        try {
329
+            $message = $this->mailer->createMessage();
330
+            $message->setTo([$email => $user->getUID()]);
331
+            $message->setFrom([$this->from => $this->defaults->getName()]);
332
+            $message->useTemplate($emailTemplate);
333
+            $this->mailer->send($message);
334
+        } catch (\Exception $e) {
335
+            throw new \Exception($this->l10n->t(
336
+                'Couldn\'t send reset email. Please contact your administrator.'
337
+            ));
338
+        }
339
+    }
340
+
341
+    /**
342
+     * @param string $input
343
+     * @return IUser
344
+     * @throws \InvalidArgumentException
345
+     */
346
+    protected function findUserByIdOrMail($input) {
347
+        $user = $this->userManager->get($input);
348
+        if ($user instanceof IUser) {
349
+            if (!$user->isEnabled()) {
350
+                throw new \InvalidArgumentException($this->l10n->t('Couldn\'t send reset email. Please make sure your username is correct.'));
351
+            }
352
+
353
+            return $user;
354
+        }
355
+        $users = $this->userManager->getByEmail($input);
356
+        if (count($users) === 1) {
357
+            $user = $users[0];
358
+            if (!$user->isEnabled()) {
359
+                throw new \InvalidArgumentException($this->l10n->t('Couldn\'t send reset email. Please make sure your username is correct.'));
360
+            }
361
+
362
+            return $user;
363
+        }
364
+
365
+        throw new \InvalidArgumentException($this->l10n->t('Couldn\'t send reset email. Please make sure your username is correct.'));
366
+    }
367 367
 }
Please login to merge, or discard this patch.