Completed
Pull Request — master (#4336)
by Lukas
23:47 queued 09:54
created
lib/private/AppFramework/Utility/ControllerMethodReflector.php 3 patches
Doc Comments   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -37,7 +37,7 @@
 block discarded – undo
37 37
 	private $parameters = [];
38 38
 
39 39
 	/**
40
-	 * @param object $object an object or classname
40
+	 * @param \OCP\AppFramework\Controller $object an object or classname
41 41
 	 * @param string $method the method which we want to inspect
42 42
 	 */
43 43
 	public function reflect($object, $method){
Please login to merge, or discard this patch.
Indentation   +87 added lines, -87 removed lines patch added patch discarded remove patch
@@ -32,102 +32,102 @@
 block discarded – undo
32 32
  * Reads and parses annotations from doc comments
33 33
  */
34 34
 class ControllerMethodReflector implements IControllerMethodReflector {
35
-	public $annotations = [];
36
-	private $types = [];
37
-	private $parameters = [];
35
+    public $annotations = [];
36
+    private $types = [];
37
+    private $parameters = [];
38 38
 
39
-	/**
40
-	 * @param object $object an object or classname
41
-	 * @param string $method the method which we want to inspect
42
-	 */
43
-	public function reflect($object, $method){
44
-		$reflection = new \ReflectionMethod($object, $method);
45
-		$docs = $reflection->getDocComment();
39
+    /**
40
+     * @param object $object an object or classname
41
+     * @param string $method the method which we want to inspect
42
+     */
43
+    public function reflect($object, $method){
44
+        $reflection = new \ReflectionMethod($object, $method);
45
+        $docs = $reflection->getDocComment();
46 46
 
47
-		// extract everything prefixed by @ and first letter uppercase
48
-		preg_match_all('/^\h+\*\h+@(?P<annotation>[A-Z]\w+)((?P<parameter>.*))?$/m', $docs, $matches);
49
-		foreach($matches['annotation'] as $key => $annontation) {
50
-			$annotationValue = $matches['parameter'][$key];
51
-			if(isset($annotationValue[0]) && $annotationValue[0] === '(' && $annotationValue[strlen($annotationValue) - 1] === ')') {
52
-				$cutString = substr($annotationValue, 1, -1);
53
-				$cutString = str_replace(' ', '', $cutString);
54
-				$splittedArray = explode(',', $cutString);
55
-				foreach($splittedArray as $annotationValues) {
56
-					list($key, $value) = explode('=', $annotationValues);
57
-					$this->annotations[$annontation][$key] = $value;
58
-				}
59
-				continue;
60
-			}
47
+        // extract everything prefixed by @ and first letter uppercase
48
+        preg_match_all('/^\h+\*\h+@(?P<annotation>[A-Z]\w+)((?P<parameter>.*))?$/m', $docs, $matches);
49
+        foreach($matches['annotation'] as $key => $annontation) {
50
+            $annotationValue = $matches['parameter'][$key];
51
+            if(isset($annotationValue[0]) && $annotationValue[0] === '(' && $annotationValue[strlen($annotationValue) - 1] === ')') {
52
+                $cutString = substr($annotationValue, 1, -1);
53
+                $cutString = str_replace(' ', '', $cutString);
54
+                $splittedArray = explode(',', $cutString);
55
+                foreach($splittedArray as $annotationValues) {
56
+                    list($key, $value) = explode('=', $annotationValues);
57
+                    $this->annotations[$annontation][$key] = $value;
58
+                }
59
+                continue;
60
+            }
61 61
 
62
-			$this->annotations[$annontation] = [$annotationValue];
63
-		}
62
+            $this->annotations[$annontation] = [$annotationValue];
63
+        }
64 64
 
65
-		// extract type parameter information
66
-		preg_match_all('/@param\h+(?P<type>\w+)\h+\$(?P<var>\w+)/', $docs, $matches);
67
-		$this->types = array_combine($matches['var'], $matches['type']);
65
+        // extract type parameter information
66
+        preg_match_all('/@param\h+(?P<type>\w+)\h+\$(?P<var>\w+)/', $docs, $matches);
67
+        $this->types = array_combine($matches['var'], $matches['type']);
68 68
 
69
-		foreach ($reflection->getParameters() as $param) {
70
-			// extract type information from PHP 7 scalar types and prefer them
71
-			// over phpdoc annotations
72
-			if (method_exists($param, 'getType')) {
73
-				$type = $param->getType();
74
-				if ($type !== null) {
75
-					$this->types[$param->getName()] = (string) $type;
76
-				}
77
-			}
69
+        foreach ($reflection->getParameters() as $param) {
70
+            // extract type information from PHP 7 scalar types and prefer them
71
+            // over phpdoc annotations
72
+            if (method_exists($param, 'getType')) {
73
+                $type = $param->getType();
74
+                if ($type !== null) {
75
+                    $this->types[$param->getName()] = (string) $type;
76
+                }
77
+            }
78 78
 
79
-			if($param->isOptional()) {
80
-				$default = $param->getDefaultValue();
81
-			} else {
82
-				$default = null;
83
-			}
84
-			$this->parameters[$param->name] = $default;
85
-		}
86
-	}
79
+            if($param->isOptional()) {
80
+                $default = $param->getDefaultValue();
81
+            } else {
82
+                $default = null;
83
+            }
84
+            $this->parameters[$param->name] = $default;
85
+        }
86
+    }
87 87
 
88
-	/**
89
-	 * Inspects the PHPDoc parameters for types
90
-	 * @param string $parameter the parameter whose type comments should be
91
-	 * parsed
92
-	 * @return string|null type in the type parameters (@param int $something)
93
-	 * would return int or null if not existing
94
-	 */
95
-	public function getType($parameter) {
96
-		if(array_key_exists($parameter, $this->types)) {
97
-			return $this->types[$parameter];
98
-		} else {
99
-			return null;
100
-		}
101
-	}
88
+    /**
89
+     * Inspects the PHPDoc parameters for types
90
+     * @param string $parameter the parameter whose type comments should be
91
+     * parsed
92
+     * @return string|null type in the type parameters (@param int $something)
93
+     * would return int or null if not existing
94
+     */
95
+    public function getType($parameter) {
96
+        if(array_key_exists($parameter, $this->types)) {
97
+            return $this->types[$parameter];
98
+        } else {
99
+            return null;
100
+        }
101
+    }
102 102
 
103
-	/**
104
-	 * @return array the arguments of the method with key => default value
105
-	 */
106
-	public function getParameters() {
107
-		return $this->parameters;
108
-	}
103
+    /**
104
+     * @return array the arguments of the method with key => default value
105
+     */
106
+    public function getParameters() {
107
+        return $this->parameters;
108
+    }
109 109
 
110
-	/**
111
-	 * Check if a method contains an annotation
112
-	 * @param string $name the name of the annotation
113
-	 * @return bool true if the annotation is found
114
-	 */
115
-	public function hasAnnotation($name) {
116
-		return array_key_exists($name, $this->annotations);
117
-	}
110
+    /**
111
+     * Check if a method contains an annotation
112
+     * @param string $name the name of the annotation
113
+     * @return bool true if the annotation is found
114
+     */
115
+    public function hasAnnotation($name) {
116
+        return array_key_exists($name, $this->annotations);
117
+    }
118 118
 
119
-	/**
120
-	 * Get optional annotation parameter by key
121
-	 *
122
-	 * @param string $name the name of the annotation
123
-	 * @param string $key the string of the annotation
124
-	 * @return string
125
-	 */
126
-	public function getAnnotationParameter($name, $key) {
127
-		if(isset($this->annotations[$name][$key])) {
128
-			return $this->annotations[$name][$key];
129
-		}
119
+    /**
120
+     * Get optional annotation parameter by key
121
+     *
122
+     * @param string $name the name of the annotation
123
+     * @param string $key the string of the annotation
124
+     * @return string
125
+     */
126
+    public function getAnnotationParameter($name, $key) {
127
+        if(isset($this->annotations[$name][$key])) {
128
+            return $this->annotations[$name][$key];
129
+        }
130 130
 
131
-		return '';
132
-	}
131
+        return '';
132
+    }
133 133
 }
Please login to merge, or discard this patch.
Spacing   +7 added lines, -7 removed lines patch added patch discarded remove patch
@@ -40,19 +40,19 @@  discard block
 block discarded – undo
40 40
 	 * @param object $object an object or classname
41 41
 	 * @param string $method the method which we want to inspect
42 42
 	 */
43
-	public function reflect($object, $method){
43
+	public function reflect($object, $method) {
44 44
 		$reflection = new \ReflectionMethod($object, $method);
45 45
 		$docs = $reflection->getDocComment();
46 46
 
47 47
 		// extract everything prefixed by @ and first letter uppercase
48 48
 		preg_match_all('/^\h+\*\h+@(?P<annotation>[A-Z]\w+)((?P<parameter>.*))?$/m', $docs, $matches);
49
-		foreach($matches['annotation'] as $key => $annontation) {
49
+		foreach ($matches['annotation'] as $key => $annontation) {
50 50
 			$annotationValue = $matches['parameter'][$key];
51
-			if(isset($annotationValue[0]) && $annotationValue[0] === '(' && $annotationValue[strlen($annotationValue) - 1] === ')') {
51
+			if (isset($annotationValue[0]) && $annotationValue[0] === '(' && $annotationValue[strlen($annotationValue) - 1] === ')') {
52 52
 				$cutString = substr($annotationValue, 1, -1);
53 53
 				$cutString = str_replace(' ', '', $cutString);
54 54
 				$splittedArray = explode(',', $cutString);
55
-				foreach($splittedArray as $annotationValues) {
55
+				foreach ($splittedArray as $annotationValues) {
56 56
 					list($key, $value) = explode('=', $annotationValues);
57 57
 					$this->annotations[$annontation][$key] = $value;
58 58
 				}
@@ -76,7 +76,7 @@  discard block
 block discarded – undo
76 76
 				}
77 77
 			}
78 78
 
79
-			if($param->isOptional()) {
79
+			if ($param->isOptional()) {
80 80
 				$default = $param->getDefaultValue();
81 81
 			} else {
82 82
 				$default = null;
@@ -93,7 +93,7 @@  discard block
 block discarded – undo
93 93
 	 * would return int or null if not existing
94 94
 	 */
95 95
 	public function getType($parameter) {
96
-		if(array_key_exists($parameter, $this->types)) {
96
+		if (array_key_exists($parameter, $this->types)) {
97 97
 			return $this->types[$parameter];
98 98
 		} else {
99 99
 			return null;
@@ -124,7 +124,7 @@  discard block
 block discarded – undo
124 124
 	 * @return string
125 125
 	 */
126 126
 	public function getAnnotationParameter($name, $key) {
127
-		if(isset($this->annotations[$name][$key])) {
127
+		if (isset($this->annotations[$name][$key])) {
128 128
 			return $this->annotations[$name][$key];
129 129
 		}
130 130
 
Please login to merge, or discard this patch.
core/Controller/LostController.php 1 patch
Indentation   +237 added lines, -237 removed lines patch added patch discarded remove patch
@@ -55,268 +55,268 @@
 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;
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 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
-	}
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 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
-		try {
135
-			$this->checkPasswordResetToken($token, $userId);
136
-		} catch (\Exception $e) {
137
-			return new TemplateResponse(
138
-				'core', 'error', [
139
-					"errors" => array(array("error" => $e->getMessage()))
140
-				],
141
-				'guest'
142
-			);
143
-		}
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
+        try {
135
+            $this->checkPasswordResetToken($token, $userId);
136
+        } catch (\Exception $e) {
137
+            return new TemplateResponse(
138
+                'core', 'error', [
139
+                    "errors" => array(array("error" => $e->getMessage()))
140
+                ],
141
+                'guest'
142
+            );
143
+        }
144 144
 
145
-		return new TemplateResponse(
146
-			'core',
147
-			'lostpassword/resetpassword',
148
-			array(
149
-				'link' => $this->urlGenerator->linkToRouteAbsolute('core.lost.setPassword', array('userId' => $userId, 'token' => $token)),
150
-			),
151
-			'guest'
152
-		);
153
-	}
145
+        return new TemplateResponse(
146
+            'core',
147
+            'lostpassword/resetpassword',
148
+            array(
149
+                'link' => $this->urlGenerator->linkToRouteAbsolute('core.lost.setPassword', array('userId' => $userId, 'token' => $token)),
150
+            ),
151
+            'guest'
152
+        );
153
+    }
154 154
 
155
-	/**
156
-	 * @param string $token
157
-	 * @param string $userId
158
-	 * @throws \Exception
159
-	 */
160
-	protected function checkPasswordResetToken($token, $userId) {
161
-		$user = $this->userManager->get($userId);
162
-		if($user === null) {
163
-			throw new \Exception($this->l10n->t('Couldn\'t reset password because the token is invalid'));
164
-		}
155
+    /**
156
+     * @param string $token
157
+     * @param string $userId
158
+     * @throws \Exception
159
+     */
160
+    protected function checkPasswordResetToken($token, $userId) {
161
+        $user = $this->userManager->get($userId);
162
+        if($user === null) {
163
+            throw new \Exception($this->l10n->t('Couldn\'t reset password because the token is invalid'));
164
+        }
165 165
 
166
-		try {
167
-			$encryptedToken = $this->config->getUserValue($userId, 'core', 'lostpassword', null);
168
-			$mailAddress = !is_null($user->getEMailAddress()) ? $user->getEMailAddress() : '';
169
-			$decryptedToken = $this->crypto->decrypt($encryptedToken, $mailAddress.$this->config->getSystemValue('secret'));
170
-		} catch (\Exception $e) {
171
-			throw new \Exception($this->l10n->t('Couldn\'t reset password because the token is invalid'));
172
-		}
166
+        try {
167
+            $encryptedToken = $this->config->getUserValue($userId, 'core', 'lostpassword', null);
168
+            $mailAddress = !is_null($user->getEMailAddress()) ? $user->getEMailAddress() : '';
169
+            $decryptedToken = $this->crypto->decrypt($encryptedToken, $mailAddress.$this->config->getSystemValue('secret'));
170
+        } catch (\Exception $e) {
171
+            throw new \Exception($this->l10n->t('Couldn\'t reset password because the token is invalid'));
172
+        }
173 173
 
174
-		$splittedToken = explode(':', $decryptedToken);
175
-		if(count($splittedToken) !== 2) {
176
-			throw new \Exception($this->l10n->t('Couldn\'t reset password because the token is invalid'));
177
-		}
174
+        $splittedToken = explode(':', $decryptedToken);
175
+        if(count($splittedToken) !== 2) {
176
+            throw new \Exception($this->l10n->t('Couldn\'t reset password because the token is invalid'));
177
+        }
178 178
 
179
-		if ($splittedToken[0] < ($this->timeFactory->getTime() - 60*60*12) ||
180
-			$user->getLastLogin() > $splittedToken[0]) {
181
-			throw new \Exception($this->l10n->t('Couldn\'t reset password because the token is expired'));
182
-		}
179
+        if ($splittedToken[0] < ($this->timeFactory->getTime() - 60*60*12) ||
180
+            $user->getLastLogin() > $splittedToken[0]) {
181
+            throw new \Exception($this->l10n->t('Couldn\'t reset password because the token is expired'));
182
+        }
183 183
 
184
-		if (!hash_equals($splittedToken[1], $token)) {
185
-			throw new \Exception($this->l10n->t('Couldn\'t reset password because the token is invalid'));
186
-		}
187
-	}
184
+        if (!hash_equals($splittedToken[1], $token)) {
185
+            throw new \Exception($this->l10n->t('Couldn\'t reset password because the token is invalid'));
186
+        }
187
+    }
188 188
 
189
-	/**
190
-	 * @param $message
191
-	 * @param array $additional
192
-	 * @return array
193
-	 */
194
-	private function error($message, array $additional=array()) {
195
-		return array_merge(array('status' => 'error', 'msg' => $message), $additional);
196
-	}
189
+    /**
190
+     * @param $message
191
+     * @param array $additional
192
+     * @return array
193
+     */
194
+    private function error($message, array $additional=array()) {
195
+        return array_merge(array('status' => 'error', 'msg' => $message), $additional);
196
+    }
197 197
 
198
-	/**
199
-	 * @return array
200
-	 */
201
-	private function success() {
202
-		return array('status'=>'success');
203
-	}
198
+    /**
199
+     * @return array
200
+     */
201
+    private function success() {
202
+        return array('status'=>'success');
203
+    }
204 204
 
205
-	/**
206
-	 * @PublicPage
207
-	 * @BruteForceProtection(action=passwordResetEmail)
208
-	 *
209
-	 * @param string $user
210
-	 * @return array
211
-	 */
212
-	public function email($user){
213
-		// FIXME: use HTTP error codes
214
-		try {
215
-			$this->sendEmail($user);
216
-		} catch (\Exception $e){
217
-			return $this->error($e->getMessage());
218
-		}
205
+    /**
206
+     * @PublicPage
207
+     * @BruteForceProtection(action=passwordResetEmail)
208
+     *
209
+     * @param string $user
210
+     * @return array
211
+     */
212
+    public function email($user){
213
+        // FIXME: use HTTP error codes
214
+        try {
215
+            $this->sendEmail($user);
216
+        } catch (\Exception $e){
217
+            return $this->error($e->getMessage());
218
+        }
219 219
 
220
-		return $this->success();
221
-	}
220
+        return $this->success();
221
+    }
222 222
 
223
-	/**
224
-	 * @PublicPage
225
-	 * @param string $token
226
-	 * @param string $userId
227
-	 * @param string $password
228
-	 * @param boolean $proceed
229
-	 * @return array
230
-	 */
231
-	public function setPassword($token, $userId, $password, $proceed) {
232
-		if ($this->encryptionManager->isEnabled() && !$proceed) {
233
-			return $this->error('', array('encryption' => true));
234
-		}
223
+    /**
224
+     * @PublicPage
225
+     * @param string $token
226
+     * @param string $userId
227
+     * @param string $password
228
+     * @param boolean $proceed
229
+     * @return array
230
+     */
231
+    public function setPassword($token, $userId, $password, $proceed) {
232
+        if ($this->encryptionManager->isEnabled() && !$proceed) {
233
+            return $this->error('', array('encryption' => true));
234
+        }
235 235
 
236
-		try {
237
-			$this->checkPasswordResetToken($token, $userId);
238
-			$user = $this->userManager->get($userId);
236
+        try {
237
+            $this->checkPasswordResetToken($token, $userId);
238
+            $user = $this->userManager->get($userId);
239 239
 
240
-			\OC_Hook::emit('\OC\Core\LostPassword\Controller\LostController', 'pre_passwordReset', array('uid' => $userId, 'password' => $password));
240
+            \OC_Hook::emit('\OC\Core\LostPassword\Controller\LostController', 'pre_passwordReset', array('uid' => $userId, 'password' => $password));
241 241
 
242
-			if (!$user->setPassword($password)) {
243
-				throw new \Exception();
244
-			}
242
+            if (!$user->setPassword($password)) {
243
+                throw new \Exception();
244
+            }
245 245
 
246
-			\OC_Hook::emit('\OC\Core\LostPassword\Controller\LostController', 'post_passwordReset', array('uid' => $userId, 'password' => $password));
246
+            \OC_Hook::emit('\OC\Core\LostPassword\Controller\LostController', 'post_passwordReset', array('uid' => $userId, 'password' => $password));
247 247
 
248
-			$this->config->deleteUserValue($userId, 'core', 'lostpassword');
249
-			@\OC_User::unsetMagicInCookie();
250
-		} catch (\Exception $e){
251
-			return $this->error($e->getMessage());
252
-		}
248
+            $this->config->deleteUserValue($userId, 'core', 'lostpassword');
249
+            @\OC_User::unsetMagicInCookie();
250
+        } catch (\Exception $e){
251
+            return $this->error($e->getMessage());
252
+        }
253 253
 
254
-		return $this->success();
255
-	}
254
+        return $this->success();
255
+    }
256 256
 
257
-	/**
258
-	 * @param string $input
259
-	 * @throws \Exception
260
-	 */
261
-	protected function sendEmail($input) {
262
-		$user = $this->findUserByIdOrMail($input);
263
-		$email = $user->getEMailAddress();
257
+    /**
258
+     * @param string $input
259
+     * @throws \Exception
260
+     */
261
+    protected function sendEmail($input) {
262
+        $user = $this->findUserByIdOrMail($input);
263
+        $email = $user->getEMailAddress();
264 264
 
265
-		if (empty($email)) {
266
-			throw new \Exception(
267
-				$this->l10n->t('Could not send reset email because there is no email address for this username. Please contact your administrator.')
268
-			);
269
-		}
265
+        if (empty($email)) {
266
+            throw new \Exception(
267
+                $this->l10n->t('Could not send reset email because there is no email address for this username. Please contact your administrator.')
268
+            );
269
+        }
270 270
 
271
-		// Generate the token. It is stored encrypted in the database with the
272
-		// secret being the users' email address appended with the system secret.
273
-		// This makes the token automatically invalidate once the user changes
274
-		// their email address.
275
-		$token = $this->secureRandom->generate(
276
-			21,
277
-			ISecureRandom::CHAR_DIGITS.
278
-			ISecureRandom::CHAR_LOWER.
279
-			ISecureRandom::CHAR_UPPER
280
-		);
281
-		$tokenValue = $this->timeFactory->getTime() .':'. $token;
282
-		$encryptedValue = $this->crypto->encrypt($tokenValue, $email . $this->config->getSystemValue('secret'));
283
-		$this->config->setUserValue($user->getUID(), 'core', 'lostpassword', $encryptedValue);
271
+        // Generate the token. It is stored encrypted in the database with the
272
+        // secret being the users' email address appended with the system secret.
273
+        // This makes the token automatically invalidate once the user changes
274
+        // their email address.
275
+        $token = $this->secureRandom->generate(
276
+            21,
277
+            ISecureRandom::CHAR_DIGITS.
278
+            ISecureRandom::CHAR_LOWER.
279
+            ISecureRandom::CHAR_UPPER
280
+        );
281
+        $tokenValue = $this->timeFactory->getTime() .':'. $token;
282
+        $encryptedValue = $this->crypto->encrypt($tokenValue, $email . $this->config->getSystemValue('secret'));
283
+        $this->config->setUserValue($user->getUID(), 'core', 'lostpassword', $encryptedValue);
284 284
 
285
-		$link = $this->urlGenerator->linkToRouteAbsolute('core.lost.resetform', array('userId' => $user->getUID(), 'token' => $token));
285
+        $link = $this->urlGenerator->linkToRouteAbsolute('core.lost.resetform', array('userId' => $user->getUID(), 'token' => $token));
286 286
 
287
-		$tmpl = new \OC_Template('core', 'lostpassword/email');
288
-		$tmpl->assign('link', $link);
289
-		$msg = $tmpl->fetchPage();
287
+        $tmpl = new \OC_Template('core', 'lostpassword/email');
288
+        $tmpl->assign('link', $link);
289
+        $msg = $tmpl->fetchPage();
290 290
 
291
-		try {
292
-			$message = $this->mailer->createMessage();
293
-			$message->setTo([$email => $user->getUID()]);
294
-			$message->setSubject($this->l10n->t('%s password reset', [$this->defaults->getName()]));
295
-			$message->setPlainBody($msg);
296
-			$message->setFrom([$this->from => $this->defaults->getName()]);
297
-			$this->mailer->send($message);
298
-		} catch (\Exception $e) {
299
-			throw new \Exception($this->l10n->t(
300
-				'Couldn\'t send reset email. Please contact your administrator.'
301
-			));
302
-		}
303
-	}
291
+        try {
292
+            $message = $this->mailer->createMessage();
293
+            $message->setTo([$email => $user->getUID()]);
294
+            $message->setSubject($this->l10n->t('%s password reset', [$this->defaults->getName()]));
295
+            $message->setPlainBody($msg);
296
+            $message->setFrom([$this->from => $this->defaults->getName()]);
297
+            $this->mailer->send($message);
298
+        } catch (\Exception $e) {
299
+            throw new \Exception($this->l10n->t(
300
+                'Couldn\'t send reset email. Please contact your administrator.'
301
+            ));
302
+        }
303
+    }
304 304
 
305
-	/**
306
-	 * @param string $input
307
-	 * @return IUser
308
-	 * @throws \Exception
309
-	 */
310
-	protected function findUserByIdOrMail($input) {
311
-		$user = $this->userManager->get($input);
312
-		if ($user instanceof IUser) {
313
-			return $user;
314
-		}
315
-		$users = $this->userManager->getByEmail($input);
316
-		if (count($users) === 1) {
317
-			return $users[0];
318
-		}
305
+    /**
306
+     * @param string $input
307
+     * @return IUser
308
+     * @throws \Exception
309
+     */
310
+    protected function findUserByIdOrMail($input) {
311
+        $user = $this->userManager->get($input);
312
+        if ($user instanceof IUser) {
313
+            return $user;
314
+        }
315
+        $users = $this->userManager->getByEmail($input);
316
+        if (count($users) === 1) {
317
+            return $users[0];
318
+        }
319 319
 
320
-		throw new \InvalidArgumentException($this->l10n->t('Couldn\'t send reset email. Please make sure your username is correct.'));
321
-	}
320
+        throw new \InvalidArgumentException($this->l10n->t('Couldn\'t send reset email. Please make sure your username is correct.'));
321
+    }
322 322
 }
Please login to merge, or discard this patch.
apps/testing/appinfo/routes.php 1 patch
Indentation   +31 added lines, -31 removed lines patch added patch discarded remove patch
@@ -28,50 +28,50 @@
 block discarded – undo
28 28
 use OCP\AppFramework\App;
29 29
 
30 30
 $config = new Config(
31
-	\OC::$server->getConfig(),
32
-	\OC::$server->getRequest()
31
+    \OC::$server->getConfig(),
32
+    \OC::$server->getRequest()
33 33
 );
34 34
 
35 35
 $app = new App('testing');
36 36
 $app->registerRoutes(
37
-	$this,
38
-	[
39
-		'routes' => [
40
-			[
41
-				'name' => 'RateLimitTest#userAndAnonProtected',
42
-				'url' => '/userAndAnonProtected',
43
-				'verb' => 'GET',
44
-			],
45
-			[
46
-				'name' => 'RateLimitTest#onlyAnonProtected',
47
-				'url' => '/anonProtected',
48
-				'verb' => 'GET',
49
-			],
50
-		]
51
-	]
37
+    $this,
38
+    [
39
+        'routes' => [
40
+            [
41
+                'name' => 'RateLimitTest#userAndAnonProtected',
42
+                'url' => '/userAndAnonProtected',
43
+                'verb' => 'GET',
44
+            ],
45
+            [
46
+                'name' => 'RateLimitTest#onlyAnonProtected',
47
+                'url' => '/anonProtected',
48
+                'verb' => 'GET',
49
+            ],
50
+        ]
51
+    ]
52 52
 );
53 53
 
54 54
 API::register(
55
-	'post',
56
-	'/apps/testing/api/v1/app/{appid}/{configkey}',
57
-	[$config, 'setAppValue'],
58
-	'testing',
59
-	API::ADMIN_AUTH
55
+    'post',
56
+    '/apps/testing/api/v1/app/{appid}/{configkey}',
57
+    [$config, 'setAppValue'],
58
+    'testing',
59
+    API::ADMIN_AUTH
60 60
 );
61 61
 
62 62
 API::register(
63
-	'delete',
64
-	'/apps/testing/api/v1/app/{appid}/{configkey}',
65
-	[$config, 'deleteAppValue'],
66
-	'testing',
67
-	API::ADMIN_AUTH
63
+    'delete',
64
+    '/apps/testing/api/v1/app/{appid}/{configkey}',
65
+    [$config, 'deleteAppValue'],
66
+    'testing',
67
+    API::ADMIN_AUTH
68 68
 );
69 69
 
70 70
 $locking = new Provisioning(
71
-	\OC::$server->getLockingProvider(),
72
-	\OC::$server->getDatabaseConnection(),
73
-	\OC::$server->getConfig(),
74
-	\OC::$server->getRequest()
71
+    \OC::$server->getLockingProvider(),
72
+    \OC::$server->getDatabaseConnection(),
73
+    \OC::$server->getConfig(),
74
+    \OC::$server->getRequest()
75 75
 );
76 76
 API::register('get', '/apps/testing/api/v1/lockprovisioning', [$locking, 'isLockingEnabled'], 'files_lockprovisioning', API::ADMIN_AUTH);
77 77
 API::register('get', '/apps/testing/api/v1/lockprovisioning/{type}/{user}', [$locking, 'isLocked'], 'files_lockprovisioning', API::ADMIN_AUTH);
Please login to merge, or discard this patch.
apps/testing/lib/Controller/RateLimitTestController.php 1 patch
Indentation   +23 added lines, -23 removed lines patch added patch discarded remove patch
@@ -25,28 +25,28 @@
 block discarded – undo
25 25
 use OCP\AppFramework\Http\JSONResponse;
26 26
 
27 27
 class RateLimitTestController extends Controller {
28
-	/**
29
-	 * @PublicPage
30
-	 * @NoCSRFRequired
31
-	 *
32
-	 * @UserRateThrottle(limit=5, period=100)
33
-	 * @AnonRateThrottle(limit=1, period=100)
34
-	 *
35
-	 * @return JSONResponse
36
-	 */
37
-	public function userAndAnonProtected() {
38
-		return new JSONResponse();
39
-	}
28
+    /**
29
+     * @PublicPage
30
+     * @NoCSRFRequired
31
+     *
32
+     * @UserRateThrottle(limit=5, period=100)
33
+     * @AnonRateThrottle(limit=1, period=100)
34
+     *
35
+     * @return JSONResponse
36
+     */
37
+    public function userAndAnonProtected() {
38
+        return new JSONResponse();
39
+    }
40 40
 
41
-	/**
42
-	 * @PublicPage
43
-	 * @NoCSRFRequired
44
-	 *
45
-	 * @AnonRateThrottle(limit=1, period=10)
46
-	 *
47
-	 * @return JSONResponse
48
-	 */
49
-	public function onlyAnonProtected() {
50
-		return new JSONResponse();
51
-	}
41
+    /**
42
+     * @PublicPage
43
+     * @NoCSRFRequired
44
+     *
45
+     * @AnonRateThrottle(limit=1, period=10)
46
+     *
47
+     * @return JSONResponse
48
+     */
49
+    public function onlyAnonProtected() {
50
+        return new JSONResponse();
51
+    }
52 52
 }
Please login to merge, or discard this patch.
apps/files_sharing/lib/Controller/ShareController.php 1 patch
Indentation   +548 added lines, -548 removed lines patch added patch discarded remove patch
@@ -64,556 +64,556 @@
 block discarded – undo
64 64
  */
65 65
 class ShareController extends Controller {
66 66
 
67
-	/** @var IConfig */
68
-	protected $config;
69
-	/** @var IURLGenerator */
70
-	protected $urlGenerator;
71
-	/** @var IUserManager */
72
-	protected $userManager;
73
-	/** @var ILogger */
74
-	protected $logger;
75
-	/** @var \OCP\Activity\IManager */
76
-	protected $activityManager;
77
-	/** @var \OCP\Share\IManager */
78
-	protected $shareManager;
79
-	/** @var ISession */
80
-	protected $session;
81
-	/** @var IPreview */
82
-	protected $previewManager;
83
-	/** @var IRootFolder */
84
-	protected $rootFolder;
85
-	/** @var FederatedShareProvider */
86
-	protected $federatedShareProvider;
87
-	/** @var EventDispatcherInterface */
88
-	protected $eventDispatcher;
89
-	/** @var IL10N */
90
-	protected $l10n;
91
-	/** @var Defaults */
92
-	protected $defaults;
93
-
94
-	/**
95
-	 * @param string $appName
96
-	 * @param IRequest $request
97
-	 * @param IConfig $config
98
-	 * @param IURLGenerator $urlGenerator
99
-	 * @param IUserManager $userManager
100
-	 * @param ILogger $logger
101
-	 * @param \OCP\Activity\IManager $activityManager
102
-	 * @param \OCP\Share\IManager $shareManager
103
-	 * @param ISession $session
104
-	 * @param IPreview $previewManager
105
-	 * @param IRootFolder $rootFolder
106
-	 * @param FederatedShareProvider $federatedShareProvider
107
-	 * @param EventDispatcherInterface $eventDispatcher
108
-	 * @param IL10N $l10n
109
-	 * @param Defaults $defaults
110
-	 */
111
-	public function __construct($appName,
112
-								IRequest $request,
113
-								IConfig $config,
114
-								IURLGenerator $urlGenerator,
115
-								IUserManager $userManager,
116
-								ILogger $logger,
117
-								\OCP\Activity\IManager $activityManager,
118
-								\OCP\Share\IManager $shareManager,
119
-								ISession $session,
120
-								IPreview $previewManager,
121
-								IRootFolder $rootFolder,
122
-								FederatedShareProvider $federatedShareProvider,
123
-								EventDispatcherInterface $eventDispatcher,
124
-								IL10N $l10n,
125
-								Defaults $defaults) {
126
-		parent::__construct($appName, $request);
127
-
128
-		$this->config = $config;
129
-		$this->urlGenerator = $urlGenerator;
130
-		$this->userManager = $userManager;
131
-		$this->logger = $logger;
132
-		$this->activityManager = $activityManager;
133
-		$this->shareManager = $shareManager;
134
-		$this->session = $session;
135
-		$this->previewManager = $previewManager;
136
-		$this->rootFolder = $rootFolder;
137
-		$this->federatedShareProvider = $federatedShareProvider;
138
-		$this->eventDispatcher = $eventDispatcher;
139
-		$this->l10n = $l10n;
140
-		$this->defaults = $defaults;
141
-	}
142
-
143
-	/**
144
-	 * @PublicPage
145
-	 * @NoCSRFRequired
146
-	 *
147
-	 * @param string $token
148
-	 * @return TemplateResponse|RedirectResponse
149
-	 */
150
-	public function showAuthenticate($token) {
151
-		$share = $this->shareManager->getShareByToken($token);
152
-
153
-		if($this->linkShareAuth($share)) {
154
-			return new RedirectResponse($this->urlGenerator->linkToRoute('files_sharing.sharecontroller.showShare', array('token' => $token)));
155
-		}
156
-
157
-		return new TemplateResponse($this->appName, 'authenticate', array(), 'guest');
158
-	}
159
-
160
-	/**
161
-	 * @PublicPage
162
-	 * @UseSession
163
-	 * @BruteForceProtection(action=publicLinkAuth)
164
-	 *
165
-	 * Authenticates against password-protected shares
166
-	 * @param string $token
167
-	 * @param string $password
168
-	 * @return RedirectResponse|TemplateResponse|NotFoundResponse
169
-	 */
170
-	public function authenticate($token, $password = '') {
171
-
172
-		// Check whether share exists
173
-		try {
174
-			$share = $this->shareManager->getShareByToken($token);
175
-		} catch (ShareNotFound $e) {
176
-			return new NotFoundResponse();
177
-		}
178
-
179
-		$authenticate = $this->linkShareAuth($share, $password);
180
-
181
-		if($authenticate === true) {
182
-			return new RedirectResponse($this->urlGenerator->linkToRoute('files_sharing.sharecontroller.showShare', array('token' => $token)));
183
-		}
184
-
185
-		return new TemplateResponse($this->appName, 'authenticate', array('wrongpw' => true), 'guest');
186
-	}
187
-
188
-	/**
189
-	 * Authenticate a link item with the given password.
190
-	 * Or use the session if no password is provided.
191
-	 *
192
-	 * This is a modified version of Helper::authenticate
193
-	 * TODO: Try to merge back eventually with Helper::authenticate
194
-	 *
195
-	 * @param \OCP\Share\IShare $share
196
-	 * @param string|null $password
197
-	 * @return bool
198
-	 */
199
-	private function linkShareAuth(\OCP\Share\IShare $share, $password = null) {
200
-		if ($password !== null) {
201
-			if ($this->shareManager->checkPassword($share, $password)) {
202
-				$this->session->set('public_link_authenticated', (string)$share->getId());
203
-			} else {
204
-				$this->emitAccessShareHook($share, 403, 'Wrong password');
205
-				return false;
206
-			}
207
-		} else {
208
-			// not authenticated ?
209
-			if ( ! $this->session->exists('public_link_authenticated')
210
-				|| $this->session->get('public_link_authenticated') !== (string)$share->getId()) {
211
-				return false;
212
-			}
213
-		}
214
-		return true;
215
-	}
216
-
217
-	/**
218
-	 * throws hooks when a share is attempted to be accessed
219
-	 *
220
-	 * @param \OCP\Share\IShare|string $share the Share instance if available,
221
-	 * otherwise token
222
-	 * @param int $errorCode
223
-	 * @param string $errorMessage
224
-	 * @throws \OC\HintException
225
-	 * @throws \OC\ServerNotAvailableException
226
-	 */
227
-	protected function emitAccessShareHook($share, $errorCode = 200, $errorMessage = '') {
228
-		$itemType = $itemSource = $uidOwner = '';
229
-		$token = $share;
230
-		$exception = null;
231
-		if($share instanceof \OCP\Share\IShare) {
232
-			try {
233
-				$token = $share->getToken();
234
-				$uidOwner = $share->getSharedBy();
235
-				$itemType = $share->getNodeType();
236
-				$itemSource = $share->getNodeId();
237
-			} catch (\Exception $e) {
238
-				// we log what we know and pass on the exception afterwards
239
-				$exception = $e;
240
-			}
241
-		}
242
-		\OC_Hook::emit('OCP\Share', 'share_link_access', [
243
-			'itemType' => $itemType,
244
-			'itemSource' => $itemSource,
245
-			'uidOwner' => $uidOwner,
246
-			'token' => $token,
247
-			'errorCode' => $errorCode,
248
-			'errorMessage' => $errorMessage,
249
-		]);
250
-		if(!is_null($exception)) {
251
-			throw $exception;
252
-		}
253
-	}
254
-
255
-	/**
256
-	 * Validate the permissions of the share
257
-	 *
258
-	 * @param Share\IShare $share
259
-	 * @return bool
260
-	 */
261
-	private function validateShare(\OCP\Share\IShare $share) {
262
-		return $share->getNode()->isReadable() && $share->getNode()->isShareable();
263
-	}
264
-
265
-	/**
266
-	 * @PublicPage
267
-	 * @NoCSRFRequired
268
-	 *
269
-	 * @param string $token
270
-	 * @param string $path
271
-	 * @return TemplateResponse|RedirectResponse|NotFoundResponse
272
-	 * @throws NotFoundException
273
-	 * @throws \Exception
274
-	 */
275
-	public function showShare($token, $path = '') {
276
-		\OC_User::setIncognitoMode(true);
277
-
278
-		// Check whether share exists
279
-		try {
280
-			$share = $this->shareManager->getShareByToken($token);
281
-		} catch (ShareNotFound $e) {
282
-			$this->emitAccessShareHook($token, 404, 'Share not found');
283
-			return new NotFoundResponse();
284
-		}
285
-
286
-		// Share is password protected - check whether the user is permitted to access the share
287
-		if ($share->getPassword() !== null && !$this->linkShareAuth($share)) {
288
-			return new RedirectResponse($this->urlGenerator->linkToRoute('files_sharing.sharecontroller.authenticate',
289
-				array('token' => $token)));
290
-		}
291
-
292
-		if (!$this->validateShare($share)) {
293
-			throw new NotFoundException();
294
-		}
295
-		// We can't get the path of a file share
296
-		try {
297
-			if ($share->getNode() instanceof \OCP\Files\File && $path !== '') {
298
-				$this->emitAccessShareHook($share, 404, 'Share not found');
299
-				throw new NotFoundException();
300
-			}
301
-		} catch (\Exception $e) {
302
-			$this->emitAccessShareHook($share, 404, 'Share not found');
303
-			throw $e;
304
-		}
305
-
306
-		$shareTmpl = [];
307
-		$shareTmpl['displayName'] = $this->userManager->get($share->getShareOwner())->getDisplayName();
308
-		$shareTmpl['owner'] = $share->getShareOwner();
309
-		$shareTmpl['filename'] = $share->getNode()->getName();
310
-		$shareTmpl['directory_path'] = $share->getTarget();
311
-		$shareTmpl['mimetype'] = $share->getNode()->getMimetype();
312
-		$shareTmpl['previewSupported'] = $this->previewManager->isMimeSupported($share->getNode()->getMimetype());
313
-		$shareTmpl['dirToken'] = $token;
314
-		$shareTmpl['sharingToken'] = $token;
315
-		$shareTmpl['server2serversharing'] = $this->federatedShareProvider->isOutgoingServer2serverShareEnabled();
316
-		$shareTmpl['protected'] = $share->getPassword() !== null ? 'true' : 'false';
317
-		$shareTmpl['dir'] = '';
318
-		$shareTmpl['nonHumanFileSize'] = $share->getNode()->getSize();
319
-		$shareTmpl['fileSize'] = \OCP\Util::humanFileSize($share->getNode()->getSize());
320
-
321
-		// Show file list
322
-		$hideFileList = false;
323
-		if ($share->getNode() instanceof \OCP\Files\Folder) {
324
-			/** @var \OCP\Files\Folder $rootFolder */
325
-			$rootFolder = $share->getNode();
326
-
327
-			try {
328
-				$folderNode = $rootFolder->get($path);
329
-			} catch (\OCP\Files\NotFoundException $e) {
330
-				$this->emitAccessShareHook($share, 404, 'Share not found');
331
-				throw new NotFoundException();
332
-			}
333
-
334
-			$shareTmpl['dir'] = $rootFolder->getRelativePath($folderNode->getPath());
335
-
336
-			/*
67
+    /** @var IConfig */
68
+    protected $config;
69
+    /** @var IURLGenerator */
70
+    protected $urlGenerator;
71
+    /** @var IUserManager */
72
+    protected $userManager;
73
+    /** @var ILogger */
74
+    protected $logger;
75
+    /** @var \OCP\Activity\IManager */
76
+    protected $activityManager;
77
+    /** @var \OCP\Share\IManager */
78
+    protected $shareManager;
79
+    /** @var ISession */
80
+    protected $session;
81
+    /** @var IPreview */
82
+    protected $previewManager;
83
+    /** @var IRootFolder */
84
+    protected $rootFolder;
85
+    /** @var FederatedShareProvider */
86
+    protected $federatedShareProvider;
87
+    /** @var EventDispatcherInterface */
88
+    protected $eventDispatcher;
89
+    /** @var IL10N */
90
+    protected $l10n;
91
+    /** @var Defaults */
92
+    protected $defaults;
93
+
94
+    /**
95
+     * @param string $appName
96
+     * @param IRequest $request
97
+     * @param IConfig $config
98
+     * @param IURLGenerator $urlGenerator
99
+     * @param IUserManager $userManager
100
+     * @param ILogger $logger
101
+     * @param \OCP\Activity\IManager $activityManager
102
+     * @param \OCP\Share\IManager $shareManager
103
+     * @param ISession $session
104
+     * @param IPreview $previewManager
105
+     * @param IRootFolder $rootFolder
106
+     * @param FederatedShareProvider $federatedShareProvider
107
+     * @param EventDispatcherInterface $eventDispatcher
108
+     * @param IL10N $l10n
109
+     * @param Defaults $defaults
110
+     */
111
+    public function __construct($appName,
112
+                                IRequest $request,
113
+                                IConfig $config,
114
+                                IURLGenerator $urlGenerator,
115
+                                IUserManager $userManager,
116
+                                ILogger $logger,
117
+                                \OCP\Activity\IManager $activityManager,
118
+                                \OCP\Share\IManager $shareManager,
119
+                                ISession $session,
120
+                                IPreview $previewManager,
121
+                                IRootFolder $rootFolder,
122
+                                FederatedShareProvider $federatedShareProvider,
123
+                                EventDispatcherInterface $eventDispatcher,
124
+                                IL10N $l10n,
125
+                                Defaults $defaults) {
126
+        parent::__construct($appName, $request);
127
+
128
+        $this->config = $config;
129
+        $this->urlGenerator = $urlGenerator;
130
+        $this->userManager = $userManager;
131
+        $this->logger = $logger;
132
+        $this->activityManager = $activityManager;
133
+        $this->shareManager = $shareManager;
134
+        $this->session = $session;
135
+        $this->previewManager = $previewManager;
136
+        $this->rootFolder = $rootFolder;
137
+        $this->federatedShareProvider = $federatedShareProvider;
138
+        $this->eventDispatcher = $eventDispatcher;
139
+        $this->l10n = $l10n;
140
+        $this->defaults = $defaults;
141
+    }
142
+
143
+    /**
144
+     * @PublicPage
145
+     * @NoCSRFRequired
146
+     *
147
+     * @param string $token
148
+     * @return TemplateResponse|RedirectResponse
149
+     */
150
+    public function showAuthenticate($token) {
151
+        $share = $this->shareManager->getShareByToken($token);
152
+
153
+        if($this->linkShareAuth($share)) {
154
+            return new RedirectResponse($this->urlGenerator->linkToRoute('files_sharing.sharecontroller.showShare', array('token' => $token)));
155
+        }
156
+
157
+        return new TemplateResponse($this->appName, 'authenticate', array(), 'guest');
158
+    }
159
+
160
+    /**
161
+     * @PublicPage
162
+     * @UseSession
163
+     * @BruteForceProtection(action=publicLinkAuth)
164
+     *
165
+     * Authenticates against password-protected shares
166
+     * @param string $token
167
+     * @param string $password
168
+     * @return RedirectResponse|TemplateResponse|NotFoundResponse
169
+     */
170
+    public function authenticate($token, $password = '') {
171
+
172
+        // Check whether share exists
173
+        try {
174
+            $share = $this->shareManager->getShareByToken($token);
175
+        } catch (ShareNotFound $e) {
176
+            return new NotFoundResponse();
177
+        }
178
+
179
+        $authenticate = $this->linkShareAuth($share, $password);
180
+
181
+        if($authenticate === true) {
182
+            return new RedirectResponse($this->urlGenerator->linkToRoute('files_sharing.sharecontroller.showShare', array('token' => $token)));
183
+        }
184
+
185
+        return new TemplateResponse($this->appName, 'authenticate', array('wrongpw' => true), 'guest');
186
+    }
187
+
188
+    /**
189
+     * Authenticate a link item with the given password.
190
+     * Or use the session if no password is provided.
191
+     *
192
+     * This is a modified version of Helper::authenticate
193
+     * TODO: Try to merge back eventually with Helper::authenticate
194
+     *
195
+     * @param \OCP\Share\IShare $share
196
+     * @param string|null $password
197
+     * @return bool
198
+     */
199
+    private function linkShareAuth(\OCP\Share\IShare $share, $password = null) {
200
+        if ($password !== null) {
201
+            if ($this->shareManager->checkPassword($share, $password)) {
202
+                $this->session->set('public_link_authenticated', (string)$share->getId());
203
+            } else {
204
+                $this->emitAccessShareHook($share, 403, 'Wrong password');
205
+                return false;
206
+            }
207
+        } else {
208
+            // not authenticated ?
209
+            if ( ! $this->session->exists('public_link_authenticated')
210
+                || $this->session->get('public_link_authenticated') !== (string)$share->getId()) {
211
+                return false;
212
+            }
213
+        }
214
+        return true;
215
+    }
216
+
217
+    /**
218
+     * throws hooks when a share is attempted to be accessed
219
+     *
220
+     * @param \OCP\Share\IShare|string $share the Share instance if available,
221
+     * otherwise token
222
+     * @param int $errorCode
223
+     * @param string $errorMessage
224
+     * @throws \OC\HintException
225
+     * @throws \OC\ServerNotAvailableException
226
+     */
227
+    protected function emitAccessShareHook($share, $errorCode = 200, $errorMessage = '') {
228
+        $itemType = $itemSource = $uidOwner = '';
229
+        $token = $share;
230
+        $exception = null;
231
+        if($share instanceof \OCP\Share\IShare) {
232
+            try {
233
+                $token = $share->getToken();
234
+                $uidOwner = $share->getSharedBy();
235
+                $itemType = $share->getNodeType();
236
+                $itemSource = $share->getNodeId();
237
+            } catch (\Exception $e) {
238
+                // we log what we know and pass on the exception afterwards
239
+                $exception = $e;
240
+            }
241
+        }
242
+        \OC_Hook::emit('OCP\Share', 'share_link_access', [
243
+            'itemType' => $itemType,
244
+            'itemSource' => $itemSource,
245
+            'uidOwner' => $uidOwner,
246
+            'token' => $token,
247
+            'errorCode' => $errorCode,
248
+            'errorMessage' => $errorMessage,
249
+        ]);
250
+        if(!is_null($exception)) {
251
+            throw $exception;
252
+        }
253
+    }
254
+
255
+    /**
256
+     * Validate the permissions of the share
257
+     *
258
+     * @param Share\IShare $share
259
+     * @return bool
260
+     */
261
+    private function validateShare(\OCP\Share\IShare $share) {
262
+        return $share->getNode()->isReadable() && $share->getNode()->isShareable();
263
+    }
264
+
265
+    /**
266
+     * @PublicPage
267
+     * @NoCSRFRequired
268
+     *
269
+     * @param string $token
270
+     * @param string $path
271
+     * @return TemplateResponse|RedirectResponse|NotFoundResponse
272
+     * @throws NotFoundException
273
+     * @throws \Exception
274
+     */
275
+    public function showShare($token, $path = '') {
276
+        \OC_User::setIncognitoMode(true);
277
+
278
+        // Check whether share exists
279
+        try {
280
+            $share = $this->shareManager->getShareByToken($token);
281
+        } catch (ShareNotFound $e) {
282
+            $this->emitAccessShareHook($token, 404, 'Share not found');
283
+            return new NotFoundResponse();
284
+        }
285
+
286
+        // Share is password protected - check whether the user is permitted to access the share
287
+        if ($share->getPassword() !== null && !$this->linkShareAuth($share)) {
288
+            return new RedirectResponse($this->urlGenerator->linkToRoute('files_sharing.sharecontroller.authenticate',
289
+                array('token' => $token)));
290
+        }
291
+
292
+        if (!$this->validateShare($share)) {
293
+            throw new NotFoundException();
294
+        }
295
+        // We can't get the path of a file share
296
+        try {
297
+            if ($share->getNode() instanceof \OCP\Files\File && $path !== '') {
298
+                $this->emitAccessShareHook($share, 404, 'Share not found');
299
+                throw new NotFoundException();
300
+            }
301
+        } catch (\Exception $e) {
302
+            $this->emitAccessShareHook($share, 404, 'Share not found');
303
+            throw $e;
304
+        }
305
+
306
+        $shareTmpl = [];
307
+        $shareTmpl['displayName'] = $this->userManager->get($share->getShareOwner())->getDisplayName();
308
+        $shareTmpl['owner'] = $share->getShareOwner();
309
+        $shareTmpl['filename'] = $share->getNode()->getName();
310
+        $shareTmpl['directory_path'] = $share->getTarget();
311
+        $shareTmpl['mimetype'] = $share->getNode()->getMimetype();
312
+        $shareTmpl['previewSupported'] = $this->previewManager->isMimeSupported($share->getNode()->getMimetype());
313
+        $shareTmpl['dirToken'] = $token;
314
+        $shareTmpl['sharingToken'] = $token;
315
+        $shareTmpl['server2serversharing'] = $this->federatedShareProvider->isOutgoingServer2serverShareEnabled();
316
+        $shareTmpl['protected'] = $share->getPassword() !== null ? 'true' : 'false';
317
+        $shareTmpl['dir'] = '';
318
+        $shareTmpl['nonHumanFileSize'] = $share->getNode()->getSize();
319
+        $shareTmpl['fileSize'] = \OCP\Util::humanFileSize($share->getNode()->getSize());
320
+
321
+        // Show file list
322
+        $hideFileList = false;
323
+        if ($share->getNode() instanceof \OCP\Files\Folder) {
324
+            /** @var \OCP\Files\Folder $rootFolder */
325
+            $rootFolder = $share->getNode();
326
+
327
+            try {
328
+                $folderNode = $rootFolder->get($path);
329
+            } catch (\OCP\Files\NotFoundException $e) {
330
+                $this->emitAccessShareHook($share, 404, 'Share not found');
331
+                throw new NotFoundException();
332
+            }
333
+
334
+            $shareTmpl['dir'] = $rootFolder->getRelativePath($folderNode->getPath());
335
+
336
+            /*
337 337
 			 * The OC_Util methods require a view. This just uses the node API
338 338
 			 */
339
-			$freeSpace = $share->getNode()->getStorage()->free_space($share->getNode()->getInternalPath());
340
-			if ($freeSpace < \OCP\Files\FileInfo::SPACE_UNLIMITED) {
341
-				$freeSpace = max($freeSpace, 0);
342
-			} else {
343
-				$freeSpace = (INF > 0) ? INF: PHP_INT_MAX; // work around https://bugs.php.net/bug.php?id=69188
344
-			}
345
-
346
-			$hideFileList = $share->getPermissions() & \OCP\Constants::PERMISSION_READ ? false : true;
347
-			$maxUploadFilesize = $freeSpace;
348
-
349
-			$folder = new Template('files', 'list', '');
350
-			$folder->assign('dir', $rootFolder->getRelativePath($folderNode->getPath()));
351
-			$folder->assign('dirToken', $token);
352
-			$folder->assign('permissions', \OCP\Constants::PERMISSION_READ);
353
-			$folder->assign('isPublic', true);
354
-			$folder->assign('hideFileList', $hideFileList);
355
-			$folder->assign('publicUploadEnabled', 'no');
356
-			$folder->assign('uploadMaxFilesize', $maxUploadFilesize);
357
-			$folder->assign('uploadMaxHumanFilesize', \OCP\Util::humanFileSize($maxUploadFilesize));
358
-			$folder->assign('freeSpace', $freeSpace);
359
-			$folder->assign('usedSpacePercent', 0);
360
-			$folder->assign('trash', false);
361
-			$shareTmpl['folder'] = $folder->fetchPage();
362
-		}
363
-
364
-		$shareTmpl['hideFileList'] = $hideFileList;
365
-		$shareTmpl['shareOwner'] = $this->userManager->get($share->getShareOwner())->getDisplayName();
366
-		$shareTmpl['downloadURL'] = $this->urlGenerator->linkToRouteAbsolute('files_sharing.sharecontroller.downloadShare', ['token' => $token]);
367
-		$shareTmpl['shareUrl'] = $this->urlGenerator->linkToRouteAbsolute('files_sharing.sharecontroller.showShare', ['token' => $token]);
368
-		$shareTmpl['maxSizeAnimateGif'] = $this->config->getSystemValue('max_filesize_animated_gifs_public_sharing', 10);
369
-		$shareTmpl['previewEnabled'] = $this->config->getSystemValue('enable_previews', true);
370
-		$shareTmpl['previewMaxX'] = $this->config->getSystemValue('preview_max_x', 1024);
371
-		$shareTmpl['previewMaxY'] = $this->config->getSystemValue('preview_max_y', 1024);
372
-		$shareTmpl['disclaimer'] = $this->config->getAppValue('core', 'shareapi_public_link_disclaimertext', null);
373
-		if ($shareTmpl['previewSupported']) {
374
-			$shareTmpl['previewImage'] = $this->urlGenerator->linkToRouteAbsolute( 'files_sharing.PublicPreview.getPreview',
375
-				['x' => 200, 'y' => 200, 'file' => $shareTmpl['directory_path'], 't' => $shareTmpl['dirToken']]);
376
-		} else {
377
-			$shareTmpl['previewImage'] = $this->urlGenerator->getAbsoluteURL($this->urlGenerator->imagePath('core', 'favicon-fb.png'));
378
-		}
379
-
380
-		// Load files we need
381
-		\OCP\Util::addScript('files', 'file-upload');
382
-		\OCP\Util::addStyle('files_sharing', 'publicView');
383
-		\OCP\Util::addScript('files_sharing', 'public');
384
-		\OCP\Util::addScript('files', 'fileactions');
385
-		\OCP\Util::addScript('files', 'fileactionsmenu');
386
-		\OCP\Util::addScript('files', 'jquery.fileupload');
387
-		\OCP\Util::addScript('files_sharing', 'files_drop');
388
-
389
-		if (isset($shareTmpl['folder'])) {
390
-			// JS required for folders
391
-			\OCP\Util::addStyle('files', 'merged');
392
-			\OCP\Util::addScript('files', 'filesummary');
393
-			\OCP\Util::addScript('files', 'breadcrumb');
394
-			\OCP\Util::addScript('files', 'fileinfomodel');
395
-			\OCP\Util::addScript('files', 'newfilemenu');
396
-			\OCP\Util::addScript('files', 'files');
397
-			\OCP\Util::addScript('files', 'filelist');
398
-			\OCP\Util::addScript('files', 'keyboardshortcuts');
399
-		}
400
-
401
-		// OpenGraph Support: http://ogp.me/
402
-		\OCP\Util::addHeader('meta', ['property' => "og:title", 'content' => $this->defaults->getName() . ' - ' . $this->defaults->getSlogan()]);
403
-		\OCP\Util::addHeader('meta', ['property' => "og:description", 'content' => $this->l10n->t('%s is publicly shared', [$shareTmpl['filename']])]);
404
-		\OCP\Util::addHeader('meta', ['property' => "og:site_name", 'content' => $this->defaults->getName()]);
405
-		\OCP\Util::addHeader('meta', ['property' => "og:url", 'content' => $shareTmpl['shareUrl']]);
406
-		\OCP\Util::addHeader('meta', ['property' => "og:type", 'content' => "object"]);
407
-		\OCP\Util::addHeader('meta', ['property' => "og:image", 'content' => $shareTmpl['previewImage']]);
408
-
409
-		$this->eventDispatcher->dispatch('OCA\Files_Sharing::loadAdditionalScripts');
410
-
411
-		$csp = new \OCP\AppFramework\Http\ContentSecurityPolicy();
412
-		$csp->addAllowedFrameDomain('\'self\'');
413
-		$response = new TemplateResponse($this->appName, 'public', $shareTmpl, 'base');
414
-		$response->setContentSecurityPolicy($csp);
415
-
416
-		$this->emitAccessShareHook($share);
417
-
418
-		return $response;
419
-	}
420
-
421
-	/**
422
-	 * @PublicPage
423
-	 * @NoCSRFRequired
424
-	 *
425
-	 * @param string $token
426
-	 * @param string $files
427
-	 * @param string $path
428
-	 * @param string $downloadStartSecret
429
-	 * @return void|\OCP\AppFramework\Http\Response
430
-	 * @throws NotFoundException
431
-	 */
432
-	public function downloadShare($token, $files = null, $path = '', $downloadStartSecret = '') {
433
-		\OC_User::setIncognitoMode(true);
434
-
435
-		$share = $this->shareManager->getShareByToken($token);
436
-
437
-		if(!($share->getPermissions() & \OCP\Constants::PERMISSION_READ)) {
438
-			return new \OCP\AppFramework\Http\DataResponse('Share is read-only');
439
-		}
440
-
441
-		// Share is password protected - check whether the user is permitted to access the share
442
-		if ($share->getPassword() !== null && !$this->linkShareAuth($share)) {
443
-			return new RedirectResponse($this->urlGenerator->linkToRoute('files_sharing.sharecontroller.authenticate',
444
-				['token' => $token]));
445
-		}
446
-
447
-		$files_list = null;
448
-		if (!is_null($files)) { // download selected files
449
-			$files_list = json_decode($files);
450
-			// in case we get only a single file
451
-			if ($files_list === null) {
452
-				$files_list = [$files];
453
-			}
454
-		}
455
-
456
-		$userFolder = $this->rootFolder->getUserFolder($share->getShareOwner());
457
-		$originalSharePath = $userFolder->getRelativePath($share->getNode()->getPath());
458
-
459
-		if (!$this->validateShare($share)) {
460
-			throw new NotFoundException();
461
-		}
462
-
463
-		// Single file share
464
-		if ($share->getNode() instanceof \OCP\Files\File) {
465
-			// Single file download
466
-			$this->singleFileDownloaded($share, $share->getNode());
467
-		}
468
-		// Directory share
469
-		else {
470
-			/** @var \OCP\Files\Folder $node */
471
-			$node = $share->getNode();
472
-
473
-			// Try to get the path
474
-			if ($path !== '') {
475
-				try {
476
-					$node = $node->get($path);
477
-				} catch (NotFoundException $e) {
478
-					$this->emitAccessShareHook($share, 404, 'Share not found');
479
-					return new NotFoundResponse();
480
-				}
481
-			}
482
-
483
-			$originalSharePath = $userFolder->getRelativePath($node->getPath());
484
-
485
-			if ($node instanceof \OCP\Files\File) {
486
-				// Single file download
487
-				$this->singleFileDownloaded($share, $share->getNode());
488
-			} else if (!empty($files_list)) {
489
-				$this->fileListDownloaded($share, $files_list, $node);
490
-			} else {
491
-				// The folder is downloaded
492
-				$this->singleFileDownloaded($share, $share->getNode());
493
-			}
494
-		}
495
-
496
-		/* FIXME: We should do this all nicely in OCP */
497
-		OC_Util::tearDownFS();
498
-		OC_Util::setupFS($share->getShareOwner());
499
-
500
-		/**
501
-		 * this sets a cookie to be able to recognize the start of the download
502
-		 * the content must not be longer than 32 characters and must only contain
503
-		 * alphanumeric characters
504
-		 */
505
-		if (!empty($downloadStartSecret)
506
-			&& !isset($downloadStartSecret[32])
507
-			&& preg_match('!^[a-zA-Z0-9]+$!', $downloadStartSecret) === 1) {
508
-
509
-			// FIXME: set on the response once we use an actual app framework response
510
-			setcookie('ocDownloadStarted', $downloadStartSecret, time() + 20, '/');
511
-		}
512
-
513
-		$this->emitAccessShareHook($share);
514
-
515
-		$server_params = array( 'head' => $this->request->getMethod() == 'HEAD' );
516
-
517
-		/**
518
-		 * Http range requests support
519
-		 */
520
-		if (isset($_SERVER['HTTP_RANGE'])) {
521
-			$server_params['range'] = $this->request->getHeader('Range');
522
-		}
523
-
524
-		// download selected files
525
-		if (!is_null($files) && $files !== '') {
526
-			// FIXME: The exit is required here because otherwise the AppFramework is trying to add headers as well
527
-			// after dispatching the request which results in a "Cannot modify header information" notice.
528
-			OC_Files::get($originalSharePath, $files_list, $server_params);
529
-			exit();
530
-		} else {
531
-			// FIXME: The exit is required here because otherwise the AppFramework is trying to add headers as well
532
-			// after dispatching the request which results in a "Cannot modify header information" notice.
533
-			OC_Files::get(dirname($originalSharePath), basename($originalSharePath), $server_params);
534
-			exit();
535
-		}
536
-	}
537
-
538
-	/**
539
-	 * create activity for every downloaded file
540
-	 *
541
-	 * @param Share\IShare $share
542
-	 * @param array $files_list
543
-	 * @param \OCP\Files\Folder $node
544
-	 */
545
-	protected function fileListDownloaded(Share\IShare $share, array $files_list, \OCP\Files\Folder $node) {
546
-		foreach ($files_list as $file) {
547
-			$subNode = $node->get($file);
548
-			$this->singleFileDownloaded($share, $subNode);
549
-		}
550
-
551
-	}
552
-
553
-	/**
554
-	 * create activity if a single file was downloaded from a link share
555
-	 *
556
-	 * @param Share\IShare $share
557
-	 */
558
-	protected function singleFileDownloaded(Share\IShare $share, \OCP\Files\Node $node) {
559
-
560
-		$fileId = $node->getId();
561
-
562
-		$userFolder = $this->rootFolder->getUserFolder($share->getSharedBy());
563
-		$userNodeList = $userFolder->getById($fileId);
564
-		$userNode = $userNodeList[0];
565
-		$ownerFolder = $this->rootFolder->getUserFolder($share->getShareOwner());
566
-		$userPath = $userFolder->getRelativePath($userNode->getPath());
567
-		$ownerPath = $ownerFolder->getRelativePath($node->getPath());
568
-
569
-		$parameters = [$userPath];
570
-
571
-		if ($share->getShareType() === \OCP\Share::SHARE_TYPE_EMAIL) {
572
-			if ($node instanceof \OCP\Files\File) {
573
-				$subject = Downloads::SUBJECT_SHARED_FILE_BY_EMAIL_DOWNLOADED;
574
-			} else {
575
-				$subject = Downloads::SUBJECT_SHARED_FOLDER_BY_EMAIL_DOWNLOADED;
576
-			}
577
-			$parameters[] = $share->getSharedWith();
578
-		} else {
579
-			if ($node instanceof \OCP\Files\File) {
580
-				$subject = Downloads::SUBJECT_PUBLIC_SHARED_FILE_DOWNLOADED;
581
-			} else {
582
-				$subject = Downloads::SUBJECT_PUBLIC_SHARED_FOLDER_DOWNLOADED;
583
-			}
584
-		}
585
-
586
-		$this->publishActivity($subject, $parameters, $share->getSharedBy(), $fileId, $userPath);
587
-
588
-		if ($share->getShareOwner() !== $share->getSharedBy()) {
589
-			$parameters[0] = $ownerPath;
590
-			$this->publishActivity($subject, $parameters, $share->getShareOwner(), $fileId, $ownerPath);
591
-		}
592
-	}
593
-
594
-	/**
595
-	 * publish activity
596
-	 *
597
-	 * @param string $subject
598
-	 * @param array $parameters
599
-	 * @param string $affectedUser
600
-	 * @param int $fileId
601
-	 * @param string $filePath
602
-	 */
603
-	protected function publishActivity($subject,
604
-										array $parameters,
605
-										$affectedUser,
606
-										$fileId,
607
-										$filePath) {
608
-
609
-		$event = $this->activityManager->generateEvent();
610
-		$event->setApp('files_sharing')
611
-			->setType('public_links')
612
-			->setSubject($subject, $parameters)
613
-			->setAffectedUser($affectedUser)
614
-			->setObject('files', $fileId, $filePath);
615
-		$this->activityManager->publish($event);
616
-	}
339
+            $freeSpace = $share->getNode()->getStorage()->free_space($share->getNode()->getInternalPath());
340
+            if ($freeSpace < \OCP\Files\FileInfo::SPACE_UNLIMITED) {
341
+                $freeSpace = max($freeSpace, 0);
342
+            } else {
343
+                $freeSpace = (INF > 0) ? INF: PHP_INT_MAX; // work around https://bugs.php.net/bug.php?id=69188
344
+            }
345
+
346
+            $hideFileList = $share->getPermissions() & \OCP\Constants::PERMISSION_READ ? false : true;
347
+            $maxUploadFilesize = $freeSpace;
348
+
349
+            $folder = new Template('files', 'list', '');
350
+            $folder->assign('dir', $rootFolder->getRelativePath($folderNode->getPath()));
351
+            $folder->assign('dirToken', $token);
352
+            $folder->assign('permissions', \OCP\Constants::PERMISSION_READ);
353
+            $folder->assign('isPublic', true);
354
+            $folder->assign('hideFileList', $hideFileList);
355
+            $folder->assign('publicUploadEnabled', 'no');
356
+            $folder->assign('uploadMaxFilesize', $maxUploadFilesize);
357
+            $folder->assign('uploadMaxHumanFilesize', \OCP\Util::humanFileSize($maxUploadFilesize));
358
+            $folder->assign('freeSpace', $freeSpace);
359
+            $folder->assign('usedSpacePercent', 0);
360
+            $folder->assign('trash', false);
361
+            $shareTmpl['folder'] = $folder->fetchPage();
362
+        }
363
+
364
+        $shareTmpl['hideFileList'] = $hideFileList;
365
+        $shareTmpl['shareOwner'] = $this->userManager->get($share->getShareOwner())->getDisplayName();
366
+        $shareTmpl['downloadURL'] = $this->urlGenerator->linkToRouteAbsolute('files_sharing.sharecontroller.downloadShare', ['token' => $token]);
367
+        $shareTmpl['shareUrl'] = $this->urlGenerator->linkToRouteAbsolute('files_sharing.sharecontroller.showShare', ['token' => $token]);
368
+        $shareTmpl['maxSizeAnimateGif'] = $this->config->getSystemValue('max_filesize_animated_gifs_public_sharing', 10);
369
+        $shareTmpl['previewEnabled'] = $this->config->getSystemValue('enable_previews', true);
370
+        $shareTmpl['previewMaxX'] = $this->config->getSystemValue('preview_max_x', 1024);
371
+        $shareTmpl['previewMaxY'] = $this->config->getSystemValue('preview_max_y', 1024);
372
+        $shareTmpl['disclaimer'] = $this->config->getAppValue('core', 'shareapi_public_link_disclaimertext', null);
373
+        if ($shareTmpl['previewSupported']) {
374
+            $shareTmpl['previewImage'] = $this->urlGenerator->linkToRouteAbsolute( 'files_sharing.PublicPreview.getPreview',
375
+                ['x' => 200, 'y' => 200, 'file' => $shareTmpl['directory_path'], 't' => $shareTmpl['dirToken']]);
376
+        } else {
377
+            $shareTmpl['previewImage'] = $this->urlGenerator->getAbsoluteURL($this->urlGenerator->imagePath('core', 'favicon-fb.png'));
378
+        }
379
+
380
+        // Load files we need
381
+        \OCP\Util::addScript('files', 'file-upload');
382
+        \OCP\Util::addStyle('files_sharing', 'publicView');
383
+        \OCP\Util::addScript('files_sharing', 'public');
384
+        \OCP\Util::addScript('files', 'fileactions');
385
+        \OCP\Util::addScript('files', 'fileactionsmenu');
386
+        \OCP\Util::addScript('files', 'jquery.fileupload');
387
+        \OCP\Util::addScript('files_sharing', 'files_drop');
388
+
389
+        if (isset($shareTmpl['folder'])) {
390
+            // JS required for folders
391
+            \OCP\Util::addStyle('files', 'merged');
392
+            \OCP\Util::addScript('files', 'filesummary');
393
+            \OCP\Util::addScript('files', 'breadcrumb');
394
+            \OCP\Util::addScript('files', 'fileinfomodel');
395
+            \OCP\Util::addScript('files', 'newfilemenu');
396
+            \OCP\Util::addScript('files', 'files');
397
+            \OCP\Util::addScript('files', 'filelist');
398
+            \OCP\Util::addScript('files', 'keyboardshortcuts');
399
+        }
400
+
401
+        // OpenGraph Support: http://ogp.me/
402
+        \OCP\Util::addHeader('meta', ['property' => "og:title", 'content' => $this->defaults->getName() . ' - ' . $this->defaults->getSlogan()]);
403
+        \OCP\Util::addHeader('meta', ['property' => "og:description", 'content' => $this->l10n->t('%s is publicly shared', [$shareTmpl['filename']])]);
404
+        \OCP\Util::addHeader('meta', ['property' => "og:site_name", 'content' => $this->defaults->getName()]);
405
+        \OCP\Util::addHeader('meta', ['property' => "og:url", 'content' => $shareTmpl['shareUrl']]);
406
+        \OCP\Util::addHeader('meta', ['property' => "og:type", 'content' => "object"]);
407
+        \OCP\Util::addHeader('meta', ['property' => "og:image", 'content' => $shareTmpl['previewImage']]);
408
+
409
+        $this->eventDispatcher->dispatch('OCA\Files_Sharing::loadAdditionalScripts');
410
+
411
+        $csp = new \OCP\AppFramework\Http\ContentSecurityPolicy();
412
+        $csp->addAllowedFrameDomain('\'self\'');
413
+        $response = new TemplateResponse($this->appName, 'public', $shareTmpl, 'base');
414
+        $response->setContentSecurityPolicy($csp);
415
+
416
+        $this->emitAccessShareHook($share);
417
+
418
+        return $response;
419
+    }
420
+
421
+    /**
422
+     * @PublicPage
423
+     * @NoCSRFRequired
424
+     *
425
+     * @param string $token
426
+     * @param string $files
427
+     * @param string $path
428
+     * @param string $downloadStartSecret
429
+     * @return void|\OCP\AppFramework\Http\Response
430
+     * @throws NotFoundException
431
+     */
432
+    public function downloadShare($token, $files = null, $path = '', $downloadStartSecret = '') {
433
+        \OC_User::setIncognitoMode(true);
434
+
435
+        $share = $this->shareManager->getShareByToken($token);
436
+
437
+        if(!($share->getPermissions() & \OCP\Constants::PERMISSION_READ)) {
438
+            return new \OCP\AppFramework\Http\DataResponse('Share is read-only');
439
+        }
440
+
441
+        // Share is password protected - check whether the user is permitted to access the share
442
+        if ($share->getPassword() !== null && !$this->linkShareAuth($share)) {
443
+            return new RedirectResponse($this->urlGenerator->linkToRoute('files_sharing.sharecontroller.authenticate',
444
+                ['token' => $token]));
445
+        }
446
+
447
+        $files_list = null;
448
+        if (!is_null($files)) { // download selected files
449
+            $files_list = json_decode($files);
450
+            // in case we get only a single file
451
+            if ($files_list === null) {
452
+                $files_list = [$files];
453
+            }
454
+        }
455
+
456
+        $userFolder = $this->rootFolder->getUserFolder($share->getShareOwner());
457
+        $originalSharePath = $userFolder->getRelativePath($share->getNode()->getPath());
458
+
459
+        if (!$this->validateShare($share)) {
460
+            throw new NotFoundException();
461
+        }
462
+
463
+        // Single file share
464
+        if ($share->getNode() instanceof \OCP\Files\File) {
465
+            // Single file download
466
+            $this->singleFileDownloaded($share, $share->getNode());
467
+        }
468
+        // Directory share
469
+        else {
470
+            /** @var \OCP\Files\Folder $node */
471
+            $node = $share->getNode();
472
+
473
+            // Try to get the path
474
+            if ($path !== '') {
475
+                try {
476
+                    $node = $node->get($path);
477
+                } catch (NotFoundException $e) {
478
+                    $this->emitAccessShareHook($share, 404, 'Share not found');
479
+                    return new NotFoundResponse();
480
+                }
481
+            }
482
+
483
+            $originalSharePath = $userFolder->getRelativePath($node->getPath());
484
+
485
+            if ($node instanceof \OCP\Files\File) {
486
+                // Single file download
487
+                $this->singleFileDownloaded($share, $share->getNode());
488
+            } else if (!empty($files_list)) {
489
+                $this->fileListDownloaded($share, $files_list, $node);
490
+            } else {
491
+                // The folder is downloaded
492
+                $this->singleFileDownloaded($share, $share->getNode());
493
+            }
494
+        }
495
+
496
+        /* FIXME: We should do this all nicely in OCP */
497
+        OC_Util::tearDownFS();
498
+        OC_Util::setupFS($share->getShareOwner());
499
+
500
+        /**
501
+         * this sets a cookie to be able to recognize the start of the download
502
+         * the content must not be longer than 32 characters and must only contain
503
+         * alphanumeric characters
504
+         */
505
+        if (!empty($downloadStartSecret)
506
+            && !isset($downloadStartSecret[32])
507
+            && preg_match('!^[a-zA-Z0-9]+$!', $downloadStartSecret) === 1) {
508
+
509
+            // FIXME: set on the response once we use an actual app framework response
510
+            setcookie('ocDownloadStarted', $downloadStartSecret, time() + 20, '/');
511
+        }
512
+
513
+        $this->emitAccessShareHook($share);
514
+
515
+        $server_params = array( 'head' => $this->request->getMethod() == 'HEAD' );
516
+
517
+        /**
518
+         * Http range requests support
519
+         */
520
+        if (isset($_SERVER['HTTP_RANGE'])) {
521
+            $server_params['range'] = $this->request->getHeader('Range');
522
+        }
523
+
524
+        // download selected files
525
+        if (!is_null($files) && $files !== '') {
526
+            // FIXME: The exit is required here because otherwise the AppFramework is trying to add headers as well
527
+            // after dispatching the request which results in a "Cannot modify header information" notice.
528
+            OC_Files::get($originalSharePath, $files_list, $server_params);
529
+            exit();
530
+        } else {
531
+            // FIXME: The exit is required here because otherwise the AppFramework is trying to add headers as well
532
+            // after dispatching the request which results in a "Cannot modify header information" notice.
533
+            OC_Files::get(dirname($originalSharePath), basename($originalSharePath), $server_params);
534
+            exit();
535
+        }
536
+    }
537
+
538
+    /**
539
+     * create activity for every downloaded file
540
+     *
541
+     * @param Share\IShare $share
542
+     * @param array $files_list
543
+     * @param \OCP\Files\Folder $node
544
+     */
545
+    protected function fileListDownloaded(Share\IShare $share, array $files_list, \OCP\Files\Folder $node) {
546
+        foreach ($files_list as $file) {
547
+            $subNode = $node->get($file);
548
+            $this->singleFileDownloaded($share, $subNode);
549
+        }
550
+
551
+    }
552
+
553
+    /**
554
+     * create activity if a single file was downloaded from a link share
555
+     *
556
+     * @param Share\IShare $share
557
+     */
558
+    protected function singleFileDownloaded(Share\IShare $share, \OCP\Files\Node $node) {
559
+
560
+        $fileId = $node->getId();
561
+
562
+        $userFolder = $this->rootFolder->getUserFolder($share->getSharedBy());
563
+        $userNodeList = $userFolder->getById($fileId);
564
+        $userNode = $userNodeList[0];
565
+        $ownerFolder = $this->rootFolder->getUserFolder($share->getShareOwner());
566
+        $userPath = $userFolder->getRelativePath($userNode->getPath());
567
+        $ownerPath = $ownerFolder->getRelativePath($node->getPath());
568
+
569
+        $parameters = [$userPath];
570
+
571
+        if ($share->getShareType() === \OCP\Share::SHARE_TYPE_EMAIL) {
572
+            if ($node instanceof \OCP\Files\File) {
573
+                $subject = Downloads::SUBJECT_SHARED_FILE_BY_EMAIL_DOWNLOADED;
574
+            } else {
575
+                $subject = Downloads::SUBJECT_SHARED_FOLDER_BY_EMAIL_DOWNLOADED;
576
+            }
577
+            $parameters[] = $share->getSharedWith();
578
+        } else {
579
+            if ($node instanceof \OCP\Files\File) {
580
+                $subject = Downloads::SUBJECT_PUBLIC_SHARED_FILE_DOWNLOADED;
581
+            } else {
582
+                $subject = Downloads::SUBJECT_PUBLIC_SHARED_FOLDER_DOWNLOADED;
583
+            }
584
+        }
585
+
586
+        $this->publishActivity($subject, $parameters, $share->getSharedBy(), $fileId, $userPath);
587
+
588
+        if ($share->getShareOwner() !== $share->getSharedBy()) {
589
+            $parameters[0] = $ownerPath;
590
+            $this->publishActivity($subject, $parameters, $share->getShareOwner(), $fileId, $ownerPath);
591
+        }
592
+    }
593
+
594
+    /**
595
+     * publish activity
596
+     *
597
+     * @param string $subject
598
+     * @param array $parameters
599
+     * @param string $affectedUser
600
+     * @param int $fileId
601
+     * @param string $filePath
602
+     */
603
+    protected function publishActivity($subject,
604
+                                        array $parameters,
605
+                                        $affectedUser,
606
+                                        $fileId,
607
+                                        $filePath) {
608
+
609
+        $event = $this->activityManager->generateEvent();
610
+        $event->setApp('files_sharing')
611
+            ->setType('public_links')
612
+            ->setSubject($subject, $parameters)
613
+            ->setAffectedUser($affectedUser)
614
+            ->setObject('files', $fileId, $filePath);
615
+        $this->activityManager->publish($event);
616
+    }
617 617
 
618 618
 
619 619
 }
Please login to merge, or discard this patch.
apps/federatedfilesharing/lib/Controller/MountPublicLinkController.php 1 patch
Indentation   +278 added lines, -278 removed lines patch added patch discarded remove patch
@@ -54,283 +54,283 @@
 block discarded – undo
54 54
  */
55 55
 class MountPublicLinkController extends Controller {
56 56
 
57
-	/** @var FederatedShareProvider */
58
-	private $federatedShareProvider;
59
-
60
-	/** @var AddressHandler */
61
-	private $addressHandler;
62
-
63
-	/** @var IManager  */
64
-	private $shareManager;
65
-
66
-	/** @var  ISession */
67
-	private $session;
68
-
69
-	/** @var IL10N */
70
-	private $l;
71
-
72
-	/** @var IUserSession */
73
-	private $userSession;
74
-
75
-	/** @var IClientService */
76
-	private $clientService;
77
-
78
-	/** @var ICloudIdManager  */
79
-	private $cloudIdManager;
80
-
81
-	/**
82
-	 * MountPublicLinkController constructor.
83
-	 *
84
-	 * @param string $appName
85
-	 * @param IRequest $request
86
-	 * @param FederatedShareProvider $federatedShareProvider
87
-	 * @param IManager $shareManager
88
-	 * @param AddressHandler $addressHandler
89
-	 * @param ISession $session
90
-	 * @param IL10N $l
91
-	 * @param IUserSession $userSession
92
-	 * @param IClientService $clientService
93
-	 * @param ICloudIdManager $cloudIdManager
94
-	 */
95
-	public function __construct($appName,
96
-								IRequest $request,
97
-								FederatedShareProvider $federatedShareProvider,
98
-								IManager $shareManager,
99
-								AddressHandler $addressHandler,
100
-								ISession $session,
101
-								IL10N $l,
102
-								IUserSession $userSession,
103
-								IClientService $clientService,
104
-								ICloudIdManager $cloudIdManager
105
-	) {
106
-		parent::__construct($appName, $request);
107
-
108
-		$this->federatedShareProvider = $federatedShareProvider;
109
-		$this->shareManager = $shareManager;
110
-		$this->addressHandler = $addressHandler;
111
-		$this->session = $session;
112
-		$this->l = $l;
113
-		$this->userSession = $userSession;
114
-		$this->clientService = $clientService;
115
-		$this->cloudIdManager = $cloudIdManager;
116
-	}
117
-
118
-	/**
119
-	 * send federated share to a user of a public link
120
-	 *
121
-	 * @NoCSRFRequired
122
-	 * @PublicPage
123
-	 * @BruteForceProtection(action=publicLink2FederatedShare)
124
-	 *
125
-	 * @param string $shareWith
126
-	 * @param string $token
127
-	 * @param string $password
128
-	 * @return JSONResponse
129
-	 */
130
-	public function createFederatedShare($shareWith, $token, $password = '') {
131
-
132
-		if (!$this->federatedShareProvider->isOutgoingServer2serverShareEnabled()) {
133
-			return new JSONResponse(
134
-				['message' => 'This server doesn\'t support outgoing federated shares'],
135
-				Http::STATUS_BAD_REQUEST
136
-			);
137
-		}
138
-
139
-		try {
140
-			list(, $server) = $this->addressHandler->splitUserRemote($shareWith);
141
-			$share = $this->shareManager->getShareByToken($token);
142
-		} catch (HintException $e) {
143
-			return new JSONResponse(['message' => $e->getHint()], Http::STATUS_BAD_REQUEST);
144
-		}
145
-
146
-		// make sure that user is authenticated in case of a password protected link
147
-		$storedPassword = $share->getPassword();
148
-		$authenticated = $this->session->get('public_link_authenticated') === $share->getId() ||
149
-			$this->shareManager->checkPassword($share, $password);
150
-		if (!empty($storedPassword) && !$authenticated ) {
151
-			return new JSONResponse(
152
-				['message' => 'No permission to access the share'],
153
-				Http::STATUS_BAD_REQUEST
154
-			);
155
-		}
156
-
157
-		$share->setSharedWith($shareWith);
158
-
159
-		try {
160
-			$this->federatedShareProvider->create($share);
161
-		} catch (\Exception $e) {
162
-			return new JSONResponse(['message' => $e->getMessage()], Http::STATUS_BAD_REQUEST);
163
-		}
164
-
165
-		return new JSONResponse(['remoteUrl' => $server]);
166
-	}
167
-
168
-	/**
169
-	 * ask other server to get a federated share
170
-	 *
171
-	 * @NoAdminRequired
172
-	 *
173
-	 * @param string $token
174
-	 * @param string $remote
175
-	 * @param string $password
176
-	 * @param string $owner (only for legacy reasons, can be removed with legacyMountPublicLink())
177
-	 * @param string $ownerDisplayName (only for legacy reasons, can be removed with legacyMountPublicLink())
178
-	 * @param string $name (only for legacy reasons, can be removed with legacyMountPublicLink())
179
-	 * @return JSONResponse
180
-	 */
181
-	public function askForFederatedShare($token, $remote, $password = '', $owner = '', $ownerDisplayName = '', $name = '') {
182
-		// check if server admin allows to mount public links from other servers
183
-		if ($this->federatedShareProvider->isIncomingServer2serverShareEnabled() === false) {
184
-			return new JSONResponse(['message' => $this->l->t('Server to server sharing is not enabled on this server')], Http::STATUS_BAD_REQUEST);
185
-		}
186
-
187
-		$cloudId = $this->cloudIdManager->getCloudId($this->userSession->getUser()->getUID(), $this->addressHandler->generateRemoteURL());
188
-
189
-		$httpClient = $this->clientService->newClient();
190
-
191
-		try {
192
-			$response = $httpClient->post($remote . '/index.php/apps/federatedfilesharing/createFederatedShare',
193
-				[
194
-					'body' =>
195
-						[
196
-							'token' => $token,
197
-							'shareWith' => rtrim($cloudId->getId(), '/'),
198
-							'password' => $password
199
-						],
200
-					'connect_timeout' => 10,
201
-				]
202
-			);
203
-		} catch (\Exception $e) {
204
-			if (empty($password)) {
205
-				$message = $this->l->t("Couldn't establish a federated share.");
206
-			} else {
207
-				$message = $this->l->t("Couldn't establish a federated share, maybe the password was wrong.");
208
-			}
209
-			return new JSONResponse(['message' => $message], Http::STATUS_BAD_REQUEST);
210
-		}
211
-
212
-		$body = $response->getBody();
213
-		$result = json_decode($body, true);
214
-
215
-		if (is_array($result) && isset($result['remoteUrl'])) {
216
-			return new JSONResponse(['message' => $this->l->t('Federated Share request was successful, you will receive a invitation. Check your notifications.')]);
217
-		}
218
-
219
-		// if we doesn't get the expected response we assume that we try to add
220
-		// a federated share from a Nextcloud <= 9 server
221
-		return $this->legacyMountPublicLink($token, $remote, $password, $name, $owner, $ownerDisplayName);
222
-	}
223
-
224
-	/**
225
-	 * Allow Nextcloud to mount a public link directly
226
-	 *
227
-	 * This code was copied from the apps/files_sharing/ajax/external.php with
228
-	 * minimal changes, just to guarantee backward compatibility
229
-	 *
230
-	 * ToDo: Remove this method once Nextcloud 9 reaches end of life
231
-	 *
232
-	 * @param string $token
233
-	 * @param string $remote
234
-	 * @param string $password
235
-	 * @param string $name
236
-	 * @param string $owner
237
-	 * @param string $ownerDisplayName
238
-	 * @return JSONResponse
239
-	 */
240
-	private function legacyMountPublicLink($token, $remote, $password, $name, $owner, $ownerDisplayName) {
241
-
242
-		// Check for invalid name
243
-		if (!Util::isValidFileName($name)) {
244
-			return new JSONResponse(['message' => $this->l->t('The mountpoint name contains invalid characters.')], Http::STATUS_BAD_REQUEST);
245
-		}
246
-		$currentUser = $this->userSession->getUser()->getUID();
247
-		$currentServer = $this->addressHandler->generateRemoteURL();
248
-		if (Helper::isSameUserOnSameServer($owner, $remote, $currentUser, $currentServer)) {
249
-			return new JSONResponse(['message' => $this->l->t('Not allowed to create a federated share with the owner.')], Http::STATUS_BAD_REQUEST);
250
-		}
251
-		$externalManager = new Manager(
252
-			\OC::$server->getDatabaseConnection(),
253
-			Filesystem::getMountManager(),
254
-			Filesystem::getLoader(),
255
-			\OC::$server->getHTTPClientService(),
256
-			\OC::$server->getNotificationManager(),
257
-			\OC::$server->query(\OCP\OCS\IDiscoveryService::class),
258
-			\OC::$server->getUserSession()->getUser()->getUID()
259
-		);
260
-
261
-		// check for ssl cert
262
-
263
-		if (strpos($remote, 'https') === 0) {
264
-			try {
265
-				$client = $this->clientService->newClient();
266
-				$client->get($remote, [
267
-					'timeout' => 10,
268
-					'connect_timeout' => 10,
269
-				])->getBody();
270
-			} catch (\Exception $e) {
271
-				return new JSONResponse(['message' => $this->l->t('Invalid or untrusted SSL certificate')], Http::STATUS_BAD_REQUEST);
272
-			}
273
-		}
274
-		$mount = $externalManager->addShare($remote, $token, $password, $name, $ownerDisplayName, true);
275
-		/**
276
-		 * @var \OCA\Files_Sharing\External\Storage $storage
277
-		 */
278
-		$storage = $mount->getStorage();
279
-		try {
280
-			// check if storage exists
281
-			$storage->checkStorageAvailability();
282
-		} catch (StorageInvalidException $e) {
283
-			// note: checkStorageAvailability will already remove the invalid share
284
-			Util::writeLog(
285
-				'federatedfilesharing',
286
-				'Invalid remote storage: ' . get_class($e) . ': ' . $e->getMessage(),
287
-				Util::DEBUG
288
-			);
289
-			return new JSONResponse(['message' => $this->l->t('Could not authenticate to remote share, password might be wrong')], Http::STATUS_BAD_REQUEST);
290
-		} catch (\Exception $e) {
291
-			Util::writeLog(
292
-				'federatedfilesharing',
293
-				'Invalid remote storage: ' . get_class($e) . ': ' . $e->getMessage(),
294
-				Util::DEBUG
295
-			);
296
-			$externalManager->removeShare($mount->getMountPoint());
297
-			return new JSONResponse(['message' => $this->l->t('Storage not valid')], Http::STATUS_BAD_REQUEST);
298
-		}
299
-		$result = $storage->file_exists('');
300
-		if ($result) {
301
-			try {
302
-				$storage->getScanner()->scanAll();
303
-				return new JSONResponse(
304
-					[
305
-						'message' => $this->l->t('Federated Share successfully added'),
306
-						'legacyMount' => '1'
307
-					]
308
-				);
309
-			} catch (StorageInvalidException $e) {
310
-				Util::writeLog(
311
-					'federatedfilesharing',
312
-					'Invalid remote storage: ' . get_class($e) . ': ' . $e->getMessage(),
313
-					Util::DEBUG
314
-				);
315
-				return new JSONResponse(['message' => $this->l->t('Storage not valid')], Http::STATUS_BAD_REQUEST);
316
-			} catch (\Exception $e) {
317
-				Util::writeLog(
318
-					'federatedfilesharing',
319
-					'Invalid remote storage: ' . get_class($e) . ': ' . $e->getMessage(),
320
-					Util::DEBUG
321
-				);
322
-				return new JSONResponse(['message' => $this->l->t('Couldn\'t add remote share')], Http::STATUS_BAD_REQUEST);
323
-			}
324
-		} else {
325
-			$externalManager->removeShare($mount->getMountPoint());
326
-			Util::writeLog(
327
-				'federatedfilesharing',
328
-				'Couldn\'t add remote share',
329
-				Util::DEBUG
330
-			);
331
-			return new JSONResponse(['message' => $this->l->t('Couldn\'t add remote share')], Http::STATUS_BAD_REQUEST);
332
-		}
333
-
334
-	}
57
+    /** @var FederatedShareProvider */
58
+    private $federatedShareProvider;
59
+
60
+    /** @var AddressHandler */
61
+    private $addressHandler;
62
+
63
+    /** @var IManager  */
64
+    private $shareManager;
65
+
66
+    /** @var  ISession */
67
+    private $session;
68
+
69
+    /** @var IL10N */
70
+    private $l;
71
+
72
+    /** @var IUserSession */
73
+    private $userSession;
74
+
75
+    /** @var IClientService */
76
+    private $clientService;
77
+
78
+    /** @var ICloudIdManager  */
79
+    private $cloudIdManager;
80
+
81
+    /**
82
+     * MountPublicLinkController constructor.
83
+     *
84
+     * @param string $appName
85
+     * @param IRequest $request
86
+     * @param FederatedShareProvider $federatedShareProvider
87
+     * @param IManager $shareManager
88
+     * @param AddressHandler $addressHandler
89
+     * @param ISession $session
90
+     * @param IL10N $l
91
+     * @param IUserSession $userSession
92
+     * @param IClientService $clientService
93
+     * @param ICloudIdManager $cloudIdManager
94
+     */
95
+    public function __construct($appName,
96
+                                IRequest $request,
97
+                                FederatedShareProvider $federatedShareProvider,
98
+                                IManager $shareManager,
99
+                                AddressHandler $addressHandler,
100
+                                ISession $session,
101
+                                IL10N $l,
102
+                                IUserSession $userSession,
103
+                                IClientService $clientService,
104
+                                ICloudIdManager $cloudIdManager
105
+    ) {
106
+        parent::__construct($appName, $request);
107
+
108
+        $this->federatedShareProvider = $federatedShareProvider;
109
+        $this->shareManager = $shareManager;
110
+        $this->addressHandler = $addressHandler;
111
+        $this->session = $session;
112
+        $this->l = $l;
113
+        $this->userSession = $userSession;
114
+        $this->clientService = $clientService;
115
+        $this->cloudIdManager = $cloudIdManager;
116
+    }
117
+
118
+    /**
119
+     * send federated share to a user of a public link
120
+     *
121
+     * @NoCSRFRequired
122
+     * @PublicPage
123
+     * @BruteForceProtection(action=publicLink2FederatedShare)
124
+     *
125
+     * @param string $shareWith
126
+     * @param string $token
127
+     * @param string $password
128
+     * @return JSONResponse
129
+     */
130
+    public function createFederatedShare($shareWith, $token, $password = '') {
131
+
132
+        if (!$this->federatedShareProvider->isOutgoingServer2serverShareEnabled()) {
133
+            return new JSONResponse(
134
+                ['message' => 'This server doesn\'t support outgoing federated shares'],
135
+                Http::STATUS_BAD_REQUEST
136
+            );
137
+        }
138
+
139
+        try {
140
+            list(, $server) = $this->addressHandler->splitUserRemote($shareWith);
141
+            $share = $this->shareManager->getShareByToken($token);
142
+        } catch (HintException $e) {
143
+            return new JSONResponse(['message' => $e->getHint()], Http::STATUS_BAD_REQUEST);
144
+        }
145
+
146
+        // make sure that user is authenticated in case of a password protected link
147
+        $storedPassword = $share->getPassword();
148
+        $authenticated = $this->session->get('public_link_authenticated') === $share->getId() ||
149
+            $this->shareManager->checkPassword($share, $password);
150
+        if (!empty($storedPassword) && !$authenticated ) {
151
+            return new JSONResponse(
152
+                ['message' => 'No permission to access the share'],
153
+                Http::STATUS_BAD_REQUEST
154
+            );
155
+        }
156
+
157
+        $share->setSharedWith($shareWith);
158
+
159
+        try {
160
+            $this->federatedShareProvider->create($share);
161
+        } catch (\Exception $e) {
162
+            return new JSONResponse(['message' => $e->getMessage()], Http::STATUS_BAD_REQUEST);
163
+        }
164
+
165
+        return new JSONResponse(['remoteUrl' => $server]);
166
+    }
167
+
168
+    /**
169
+     * ask other server to get a federated share
170
+     *
171
+     * @NoAdminRequired
172
+     *
173
+     * @param string $token
174
+     * @param string $remote
175
+     * @param string $password
176
+     * @param string $owner (only for legacy reasons, can be removed with legacyMountPublicLink())
177
+     * @param string $ownerDisplayName (only for legacy reasons, can be removed with legacyMountPublicLink())
178
+     * @param string $name (only for legacy reasons, can be removed with legacyMountPublicLink())
179
+     * @return JSONResponse
180
+     */
181
+    public function askForFederatedShare($token, $remote, $password = '', $owner = '', $ownerDisplayName = '', $name = '') {
182
+        // check if server admin allows to mount public links from other servers
183
+        if ($this->federatedShareProvider->isIncomingServer2serverShareEnabled() === false) {
184
+            return new JSONResponse(['message' => $this->l->t('Server to server sharing is not enabled on this server')], Http::STATUS_BAD_REQUEST);
185
+        }
186
+
187
+        $cloudId = $this->cloudIdManager->getCloudId($this->userSession->getUser()->getUID(), $this->addressHandler->generateRemoteURL());
188
+
189
+        $httpClient = $this->clientService->newClient();
190
+
191
+        try {
192
+            $response = $httpClient->post($remote . '/index.php/apps/federatedfilesharing/createFederatedShare',
193
+                [
194
+                    'body' =>
195
+                        [
196
+                            'token' => $token,
197
+                            'shareWith' => rtrim($cloudId->getId(), '/'),
198
+                            'password' => $password
199
+                        ],
200
+                    'connect_timeout' => 10,
201
+                ]
202
+            );
203
+        } catch (\Exception $e) {
204
+            if (empty($password)) {
205
+                $message = $this->l->t("Couldn't establish a federated share.");
206
+            } else {
207
+                $message = $this->l->t("Couldn't establish a federated share, maybe the password was wrong.");
208
+            }
209
+            return new JSONResponse(['message' => $message], Http::STATUS_BAD_REQUEST);
210
+        }
211
+
212
+        $body = $response->getBody();
213
+        $result = json_decode($body, true);
214
+
215
+        if (is_array($result) && isset($result['remoteUrl'])) {
216
+            return new JSONResponse(['message' => $this->l->t('Federated Share request was successful, you will receive a invitation. Check your notifications.')]);
217
+        }
218
+
219
+        // if we doesn't get the expected response we assume that we try to add
220
+        // a federated share from a Nextcloud <= 9 server
221
+        return $this->legacyMountPublicLink($token, $remote, $password, $name, $owner, $ownerDisplayName);
222
+    }
223
+
224
+    /**
225
+     * Allow Nextcloud to mount a public link directly
226
+     *
227
+     * This code was copied from the apps/files_sharing/ajax/external.php with
228
+     * minimal changes, just to guarantee backward compatibility
229
+     *
230
+     * ToDo: Remove this method once Nextcloud 9 reaches end of life
231
+     *
232
+     * @param string $token
233
+     * @param string $remote
234
+     * @param string $password
235
+     * @param string $name
236
+     * @param string $owner
237
+     * @param string $ownerDisplayName
238
+     * @return JSONResponse
239
+     */
240
+    private function legacyMountPublicLink($token, $remote, $password, $name, $owner, $ownerDisplayName) {
241
+
242
+        // Check for invalid name
243
+        if (!Util::isValidFileName($name)) {
244
+            return new JSONResponse(['message' => $this->l->t('The mountpoint name contains invalid characters.')], Http::STATUS_BAD_REQUEST);
245
+        }
246
+        $currentUser = $this->userSession->getUser()->getUID();
247
+        $currentServer = $this->addressHandler->generateRemoteURL();
248
+        if (Helper::isSameUserOnSameServer($owner, $remote, $currentUser, $currentServer)) {
249
+            return new JSONResponse(['message' => $this->l->t('Not allowed to create a federated share with the owner.')], Http::STATUS_BAD_REQUEST);
250
+        }
251
+        $externalManager = new Manager(
252
+            \OC::$server->getDatabaseConnection(),
253
+            Filesystem::getMountManager(),
254
+            Filesystem::getLoader(),
255
+            \OC::$server->getHTTPClientService(),
256
+            \OC::$server->getNotificationManager(),
257
+            \OC::$server->query(\OCP\OCS\IDiscoveryService::class),
258
+            \OC::$server->getUserSession()->getUser()->getUID()
259
+        );
260
+
261
+        // check for ssl cert
262
+
263
+        if (strpos($remote, 'https') === 0) {
264
+            try {
265
+                $client = $this->clientService->newClient();
266
+                $client->get($remote, [
267
+                    'timeout' => 10,
268
+                    'connect_timeout' => 10,
269
+                ])->getBody();
270
+            } catch (\Exception $e) {
271
+                return new JSONResponse(['message' => $this->l->t('Invalid or untrusted SSL certificate')], Http::STATUS_BAD_REQUEST);
272
+            }
273
+        }
274
+        $mount = $externalManager->addShare($remote, $token, $password, $name, $ownerDisplayName, true);
275
+        /**
276
+         * @var \OCA\Files_Sharing\External\Storage $storage
277
+         */
278
+        $storage = $mount->getStorage();
279
+        try {
280
+            // check if storage exists
281
+            $storage->checkStorageAvailability();
282
+        } catch (StorageInvalidException $e) {
283
+            // note: checkStorageAvailability will already remove the invalid share
284
+            Util::writeLog(
285
+                'federatedfilesharing',
286
+                'Invalid remote storage: ' . get_class($e) . ': ' . $e->getMessage(),
287
+                Util::DEBUG
288
+            );
289
+            return new JSONResponse(['message' => $this->l->t('Could not authenticate to remote share, password might be wrong')], Http::STATUS_BAD_REQUEST);
290
+        } catch (\Exception $e) {
291
+            Util::writeLog(
292
+                'federatedfilesharing',
293
+                'Invalid remote storage: ' . get_class($e) . ': ' . $e->getMessage(),
294
+                Util::DEBUG
295
+            );
296
+            $externalManager->removeShare($mount->getMountPoint());
297
+            return new JSONResponse(['message' => $this->l->t('Storage not valid')], Http::STATUS_BAD_REQUEST);
298
+        }
299
+        $result = $storage->file_exists('');
300
+        if ($result) {
301
+            try {
302
+                $storage->getScanner()->scanAll();
303
+                return new JSONResponse(
304
+                    [
305
+                        'message' => $this->l->t('Federated Share successfully added'),
306
+                        'legacyMount' => '1'
307
+                    ]
308
+                );
309
+            } catch (StorageInvalidException $e) {
310
+                Util::writeLog(
311
+                    'federatedfilesharing',
312
+                    'Invalid remote storage: ' . get_class($e) . ': ' . $e->getMessage(),
313
+                    Util::DEBUG
314
+                );
315
+                return new JSONResponse(['message' => $this->l->t('Storage not valid')], Http::STATUS_BAD_REQUEST);
316
+            } catch (\Exception $e) {
317
+                Util::writeLog(
318
+                    'federatedfilesharing',
319
+                    'Invalid remote storage: ' . get_class($e) . ': ' . $e->getMessage(),
320
+                    Util::DEBUG
321
+                );
322
+                return new JSONResponse(['message' => $this->l->t('Couldn\'t add remote share')], Http::STATUS_BAD_REQUEST);
323
+            }
324
+        } else {
325
+            $externalManager->removeShare($mount->getMountPoint());
326
+            Util::writeLog(
327
+                'federatedfilesharing',
328
+                'Couldn\'t add remote share',
329
+                Util::DEBUG
330
+            );
331
+            return new JSONResponse(['message' => $this->l->t('Couldn\'t add remote share')], Http::STATUS_BAD_REQUEST);
332
+        }
333
+
334
+    }
335 335
 
336 336
 }
Please login to merge, or discard this patch.
lib/private/Security/RateLimiting/Limiter.php 2 patches
Indentation   +67 added lines, -67 removed lines patch added patch discarded remove patch
@@ -30,77 +30,77 @@
 block discarded – undo
30 30
 use OCP\IUserSession;
31 31
 
32 32
 class Limiter {
33
-	/** @var IBackend */
34
-	private $backend;
35
-	/** @var ITimeFactory */
36
-	private $timeFactory;
33
+    /** @var IBackend */
34
+    private $backend;
35
+    /** @var ITimeFactory */
36
+    private $timeFactory;
37 37
 
38
-	/**
39
-	 * @param IUserSession $userSession
40
-	 * @param IRequest $request
41
-	 * @param ITimeFactory $timeFactory
42
-	 * @param IBackend $backend
43
-	 */
44
-	public function __construct(IUserSession $userSession,
45
-								IRequest $request,
46
-								ITimeFactory $timeFactory,
47
-								IBackend $backend) {
48
-		$this->backend = $backend;
49
-		$this->timeFactory = $timeFactory;
50
-	}
38
+    /**
39
+     * @param IUserSession $userSession
40
+     * @param IRequest $request
41
+     * @param ITimeFactory $timeFactory
42
+     * @param IBackend $backend
43
+     */
44
+    public function __construct(IUserSession $userSession,
45
+                                IRequest $request,
46
+                                ITimeFactory $timeFactory,
47
+                                IBackend $backend) {
48
+        $this->backend = $backend;
49
+        $this->timeFactory = $timeFactory;
50
+    }
51 51
 
52
-	/**
53
-	 * @param string $methodIdentifier
54
-	 * @param string $userIdentifier
55
-	 * @param int $period
56
-	 * @param int $limit
57
-	 * @throws RateLimitExceededException
58
-	 */
59
-	private function register($methodIdentifier,
60
-							  $userIdentifier,
61
-							  $period,
62
-							  $limit) {
63
-		$existingAttempts = $this->backend->getAttempts($methodIdentifier, $userIdentifier, (int)$period);
64
-		if ($existingAttempts >= (int)$limit) {
65
-			throw new RateLimitExceededException();
66
-		}
52
+    /**
53
+     * @param string $methodIdentifier
54
+     * @param string $userIdentifier
55
+     * @param int $period
56
+     * @param int $limit
57
+     * @throws RateLimitExceededException
58
+     */
59
+    private function register($methodIdentifier,
60
+                                $userIdentifier,
61
+                                $period,
62
+                                $limit) {
63
+        $existingAttempts = $this->backend->getAttempts($methodIdentifier, $userIdentifier, (int)$period);
64
+        if ($existingAttempts >= (int)$limit) {
65
+            throw new RateLimitExceededException();
66
+        }
67 67
 
68
-		$this->backend->registerAttempt($methodIdentifier, $userIdentifier, $this->timeFactory->getTime());
69
-	}
68
+        $this->backend->registerAttempt($methodIdentifier, $userIdentifier, $this->timeFactory->getTime());
69
+    }
70 70
 
71
-	/**
72
-	 * Registers attempt for an anonymous request
73
-	 *
74
-	 * @param string $identifier
75
-	 * @param int $anonLimit
76
-	 * @param int $anonPeriod
77
-	 * @param string $ip
78
-	 * @throws RateLimitExceededException
79
-	 */
80
-	public function registerAnonRequest($identifier,
81
-										$anonLimit,
82
-										$anonPeriod,
83
-										$ip) {
84
-		$ipSubnet = (new IpAddress($ip))->getSubnet();
71
+    /**
72
+     * Registers attempt for an anonymous request
73
+     *
74
+     * @param string $identifier
75
+     * @param int $anonLimit
76
+     * @param int $anonPeriod
77
+     * @param string $ip
78
+     * @throws RateLimitExceededException
79
+     */
80
+    public function registerAnonRequest($identifier,
81
+                                        $anonLimit,
82
+                                        $anonPeriod,
83
+                                        $ip) {
84
+        $ipSubnet = (new IpAddress($ip))->getSubnet();
85 85
 
86
-		$anonHashIdentifier = hash('sha512', 'anon::' . $identifier . $ipSubnet);
87
-		$this->register($identifier, $anonHashIdentifier, $anonPeriod, $anonLimit);
88
-	}
86
+        $anonHashIdentifier = hash('sha512', 'anon::' . $identifier . $ipSubnet);
87
+        $this->register($identifier, $anonHashIdentifier, $anonPeriod, $anonLimit);
88
+    }
89 89
 
90
-	/**
91
-	 * Registers attempt for an authenticated request
92
-	 *
93
-	 * @param string $identifier
94
-	 * @param int $userLimit
95
-	 * @param int $userPeriod
96
-	 * @param IUser $user
97
-	 * @throws RateLimitExceededException
98
-	 */
99
-	public function registerUserRequest($identifier,
100
-										$userLimit,
101
-										$userPeriod,
102
-										IUser $user) {
103
-		$userHashIdentifier = hash('sha512', 'user::' . $identifier . $user->getUID());
104
-		$this->register($identifier, $userHashIdentifier, $userPeriod, $userLimit);
105
-	}
90
+    /**
91
+     * Registers attempt for an authenticated request
92
+     *
93
+     * @param string $identifier
94
+     * @param int $userLimit
95
+     * @param int $userPeriod
96
+     * @param IUser $user
97
+     * @throws RateLimitExceededException
98
+     */
99
+    public function registerUserRequest($identifier,
100
+                                        $userLimit,
101
+                                        $userPeriod,
102
+                                        IUser $user) {
103
+        $userHashIdentifier = hash('sha512', 'user::' . $identifier . $user->getUID());
104
+        $this->register($identifier, $userHashIdentifier, $userPeriod, $userLimit);
105
+    }
106 106
 }
Please login to merge, or discard this patch.
Spacing   +4 added lines, -4 removed lines patch added patch discarded remove patch
@@ -60,8 +60,8 @@  discard block
 block discarded – undo
60 60
 							  $userIdentifier,
61 61
 							  $period,
62 62
 							  $limit) {
63
-		$existingAttempts = $this->backend->getAttempts($methodIdentifier, $userIdentifier, (int)$period);
64
-		if ($existingAttempts >= (int)$limit) {
63
+		$existingAttempts = $this->backend->getAttempts($methodIdentifier, $userIdentifier, (int) $period);
64
+		if ($existingAttempts >= (int) $limit) {
65 65
 			throw new RateLimitExceededException();
66 66
 		}
67 67
 
@@ -83,7 +83,7 @@  discard block
 block discarded – undo
83 83
 										$ip) {
84 84
 		$ipSubnet = (new IpAddress($ip))->getSubnet();
85 85
 
86
-		$anonHashIdentifier = hash('sha512', 'anon::' . $identifier . $ipSubnet);
86
+		$anonHashIdentifier = hash('sha512', 'anon::'.$identifier.$ipSubnet);
87 87
 		$this->register($identifier, $anonHashIdentifier, $anonPeriod, $anonLimit);
88 88
 	}
89 89
 
@@ -100,7 +100,7 @@  discard block
 block discarded – undo
100 100
 										$userLimit,
101 101
 										$userPeriod,
102 102
 										IUser $user) {
103
-		$userHashIdentifier = hash('sha512', 'user::' . $identifier . $user->getUID());
103
+		$userHashIdentifier = hash('sha512', 'user::'.$identifier.$user->getUID());
104 104
 		$this->register($identifier, $userHashIdentifier, $userPeriod, $userLimit);
105 105
 	}
106 106
 }
Please login to merge, or discard this patch.
lib/private/Security/RateLimiting/Exception/RateLimitExceededException.php 1 patch
Indentation   +3 added lines, -3 removed lines patch added patch discarded remove patch
@@ -25,7 +25,7 @@
 block discarded – undo
25 25
 use OCP\AppFramework\Http;
26 26
 
27 27
 class RateLimitExceededException extends SecurityException {
28
-	public function __construct() {
29
-		parent::__construct('Rate limit exceeded', Http::STATUS_TOO_MANY_REQUESTS);
30
-	}
28
+    public function __construct() {
29
+        parent::__construct('Rate limit exceeded', Http::STATUS_TOO_MANY_REQUESTS);
30
+    }
31 31
 }
Please login to merge, or discard this patch.
lib/private/Security/Normalizer/IpAddress.php 1 patch
Indentation   +70 added lines, -70 removed lines patch added patch discarded remove patch
@@ -28,79 +28,79 @@
 block discarded – undo
28 28
  * @package OC\Security\Normalizer
29 29
  */
30 30
 class IpAddress {
31
-	/** @var string */
32
-	private $ip;
31
+    /** @var string */
32
+    private $ip;
33 33
 
34
-	/**
35
-	 * @param string $ip IP to normalized
36
-	 */
37
-	public function __construct($ip) {
38
-		$this->ip = $ip;
39
-	}
34
+    /**
35
+     * @param string $ip IP to normalized
36
+     */
37
+    public function __construct($ip) {
38
+        $this->ip = $ip;
39
+    }
40 40
 
41
-	/**
42
-	 * Return the given subnet for an IPv4 address and mask bits
43
-	 *
44
-	 * @param string $ip
45
-	 * @param int $maskBits
46
-	 * @return string
47
-	 */
48
-	private function getIPv4Subnet($ip,
49
-								   $maskBits = 32) {
50
-		$binary = \inet_pton($ip);
51
-		for ($i = 32; $i > $maskBits; $i -= 8) {
52
-			$j = \intdiv($i, 8) - 1;
53
-			$k = (int) \min(8, $i - $maskBits);
54
-			$mask = (0xff - ((pow(2, $k)) - 1));
55
-			$int = \unpack('C', $binary[$j]);
56
-			$binary[$j] = \pack('C', $int[1] & $mask);
57
-		}
58
-		return \inet_ntop($binary).'/'.$maskBits;
59
-	}
41
+    /**
42
+     * Return the given subnet for an IPv4 address and mask bits
43
+     *
44
+     * @param string $ip
45
+     * @param int $maskBits
46
+     * @return string
47
+     */
48
+    private function getIPv4Subnet($ip,
49
+                                    $maskBits = 32) {
50
+        $binary = \inet_pton($ip);
51
+        for ($i = 32; $i > $maskBits; $i -= 8) {
52
+            $j = \intdiv($i, 8) - 1;
53
+            $k = (int) \min(8, $i - $maskBits);
54
+            $mask = (0xff - ((pow(2, $k)) - 1));
55
+            $int = \unpack('C', $binary[$j]);
56
+            $binary[$j] = \pack('C', $int[1] & $mask);
57
+        }
58
+        return \inet_ntop($binary).'/'.$maskBits;
59
+    }
60 60
 
61
-	/**
62
-	 * Return the given subnet for an IPv6 address and mask bits
63
-	 *
64
-	 * @param string $ip
65
-	 * @param int $maskBits
66
-	 * @return string
67
-	 */
68
-	private function getIPv6Subnet($ip, $maskBits = 48) {
69
-		$binary = \inet_pton($ip);
70
-		for ($i = 128; $i > $maskBits; $i -= 8) {
71
-			$j = \intdiv($i, 8) - 1;
72
-			$k = (int) \min(8, $i - $maskBits);
73
-			$mask = (0xff - ((pow(2, $k)) - 1));
74
-			$int = \unpack('C', $binary[$j]);
75
-			$binary[$j] = \pack('C', $int[1] & $mask);
76
-		}
77
-		return \inet_ntop($binary).'/'.$maskBits;
78
-	}
61
+    /**
62
+     * Return the given subnet for an IPv6 address and mask bits
63
+     *
64
+     * @param string $ip
65
+     * @param int $maskBits
66
+     * @return string
67
+     */
68
+    private function getIPv6Subnet($ip, $maskBits = 48) {
69
+        $binary = \inet_pton($ip);
70
+        for ($i = 128; $i > $maskBits; $i -= 8) {
71
+            $j = \intdiv($i, 8) - 1;
72
+            $k = (int) \min(8, $i - $maskBits);
73
+            $mask = (0xff - ((pow(2, $k)) - 1));
74
+            $int = \unpack('C', $binary[$j]);
75
+            $binary[$j] = \pack('C', $int[1] & $mask);
76
+        }
77
+        return \inet_ntop($binary).'/'.$maskBits;
78
+    }
79 79
 
80
-	/**
81
-	 * Gets either the /32 (IPv4) or the /128 (IPv6) subnet of an IP address
82
-	 *
83
-	 * @return string
84
-	 */
85
-	public function getSubnet() {
86
-		if (\preg_match('/^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$/', $this->ip)) {
87
-			return $this->getIPv4Subnet(
88
-				$this->ip,
89
-				32
90
-			);
91
-		}
92
-		return $this->getIPv6Subnet(
93
-			$this->ip,
94
-			128
95
-		);
96
-	}
80
+    /**
81
+     * Gets either the /32 (IPv4) or the /128 (IPv6) subnet of an IP address
82
+     *
83
+     * @return string
84
+     */
85
+    public function getSubnet() {
86
+        if (\preg_match('/^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$/', $this->ip)) {
87
+            return $this->getIPv4Subnet(
88
+                $this->ip,
89
+                32
90
+            );
91
+        }
92
+        return $this->getIPv6Subnet(
93
+            $this->ip,
94
+            128
95
+        );
96
+    }
97 97
 
98
-	/**
99
-	 * Returns the specified IP address
100
-	 *
101
-	 * @return string
102
-	 */
103
-	public function __toString() {
104
-		return $this->ip;
105
-	}
98
+    /**
99
+     * Returns the specified IP address
100
+     *
101
+     * @return string
102
+     */
103
+    public function __toString() {
104
+        return $this->ip;
105
+    }
106 106
 }
Please login to merge, or discard this patch.