Completed
Push — master ( 68735c...ea470f )
by Björn
11:25
created

Helper::authenticate()   B

Complexity

Conditions 6
Paths 5

Size

Total Lines 19
Code Lines 12

Duplication

Lines 7
Ratio 36.84 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 6
eloc 12
c 1
b 0
f 0
nc 5
nop 2
dl 7
loc 19
rs 8.8571
1
<?php
2
/**
3
 * @author Bart Visscher <[email protected]>
4
 * @author Björn Schießle <[email protected]>
5
 * @author Joas Schilling <[email protected]>
6
 * @author Jörn Friedrich Dreyer <[email protected]>
7
 * @author Lukas Reschke <[email protected]>
8
 * @author Morris Jobke <[email protected]>
9
 * @author Robin Appelman <[email protected]>
10
 * @author Roeland Jago Douma <[email protected]>
11
 * @author Vincent Petry <[email protected]>
12
 *
13
 * @copyright Copyright (c) 2016, ownCloud, Inc.
14
 * @license AGPL-3.0
15
 *
16
 * This code is free software: you can redistribute it and/or modify
17
 * it under the terms of the GNU Affero General Public License, version 3,
18
 * as published by the Free Software Foundation.
19
 *
20
 * This program is distributed in the hope that it will be useful,
21
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23
 * GNU Affero General Public License for more details.
24
 *
25
 * You should have received a copy of the GNU Affero General Public License, version 3,
26
 * along with this program.  If not, see <http://www.gnu.org/licenses/>
27
 *
28
 */
29
namespace OCA\Files_Sharing;
30
31
use OC\Files\Filesystem;
32
use OC\Files\View;
33
use OCP\Files\NotFoundException;
34
use OCP\Share\Exceptions\ShareNotFound;
35
use OCP\User;
36
37
class Helper {
38
39
	public static function registerHooks() {
40
		\OCP\Util::connectHook('OC_Filesystem', 'post_rename', '\OCA\Files_Sharing\Updater', 'renameHook');
41
		\OCP\Util::connectHook('OC_Filesystem', 'post_delete', '\OCA\Files_Sharing\Hooks', 'unshareChildren');
42
		\OCP\Util::connectHook('OC_Appconfig', 'post_set_value', '\OCA\Files_Sharing\Maintainer', 'configChangeHook');
43
44
		\OCP\Util::connectHook('OC_User', 'post_deleteUser', '\OCA\Files_Sharing\Hooks', 'deleteUser');
45
	}
46
47
	/**
48
	 * Sets up the filesystem and user for public sharing
49
	 * @param string $token string share token
50
	 * @param string $relativePath optional path relative to the share
51
	 * @param string $password optional password
52
	 * @return array
53
	 */
54
	public static function setupFromToken($token, $relativePath = null, $password = null) {
55
		\OC_User::setIncognitoMode(true);
56
57
		$shareManager = \OC::$server->getShareManager();
58
59
		try {
60
			$share = $shareManager->getShareByToken($token);
61
		} catch (ShareNotFound $e) {
62
			\OC_Response::setStatus(404);
63
			\OCP\Util::writeLog('core-preview', 'Passed token parameter is not valid', \OCP\Util::DEBUG);
64
			exit;
65
		}
66
67
		\OCP\JSON::checkUserExists($share->getShareOwner());
0 ignored issues
show
Deprecated Code introduced by
The method OCP\JSON::checkUserExists() has been deprecated with message: 8.1.0 Use a AppFramework JSONResponse instead

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
68
		\OC_Util::tearDownFS();
69
		\OC_Util::setupFS($share->getShareOwner());
70
71
72
		try {
73
			$path = Filesystem::getPath($share->getNodeId());
74
		} catch (NotFoundException $e) {
75
			\OCP\Util::writeLog('share', 'could not resolve linkItem', \OCP\Util::DEBUG);
76
			\OC_Response::setStatus(404);
77
			\OCP\JSON::error(array('success' => false));
0 ignored issues
show
Deprecated Code introduced by
The method OCP\JSON::error() has been deprecated with message: 8.1.0 Use a AppFramework JSONResponse instead

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
78
			exit();
79
		}
80
81
		if ($share->getShareType() === \OCP\Share::SHARE_TYPE_LINK && $share->getPassword() !== null) {
82
			if (!self::authenticate($share, $password)) {
83
				\OC_Response::setStatus(403);
84
				\OCP\JSON::error(array('success' => false));
0 ignored issues
show
Deprecated Code introduced by
The method OCP\JSON::error() has been deprecated with message: 8.1.0 Use a AppFramework JSONResponse instead

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
85
				exit();
86
			}
87
		}
88
89
		$basePath = $path;
90
91
		if ($relativePath !== null && Filesystem::isReadable($basePath . $relativePath)) {
92
			$path .= Filesystem::normalizePath($relativePath);
93
		}
94
95
		return array(
96
			'share' => $share,
97
			'basePath' => $basePath,
98
			'realPath' => $path
99
		);
100
	}
101
102
	/**
103
	 * Authenticate link item with the given password
104
	 * or with the session if no password was given.
105
	 * @param \OCP\Share\IShare $share
106
	 * @param string $password optional password
107
	 *
108
	 * @return boolean true if authorized, false otherwise
109
	 */
110
	public static function authenticate($share, $password = null) {
111
		$shareManager = \OC::$server->getShareManager();
112
113
		if ($password !== null) {
114
			if ($share->getShareType() === \OCP\Share::SHARE_TYPE_LINK) {
115
				if ($shareManager->checkPassword($share, $password)) {
116
					\OC::$server->getSession()->set('public_link_authenticated', (string)$share->getId());
117
					return true;
118
				}
119
			}
120 View Code Duplication
		} else {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
121
			// not authenticated ?
122
			if (\OC::$server->getSession()->exists('public_link_authenticated')
123
				&& \OC::$server->getSession()->get('public_link_authenticated') !== (string)$share->getId()) {
124
				return true;
125
			}
126
		}
127
		return false;
128
	}
129
130
	public static function getSharesFromItem($target) {
131
		$result = array();
132
		$owner = Filesystem::getOwner($target);
133
		Filesystem::initMountPoints($owner);
134
		$info = Filesystem::getFileInfo($target);
135
		$ownerView = new View('/'.$owner.'/files');
136
		if ( $owner != User::getUser() ) {
0 ignored issues
show
Deprecated Code introduced by
The method OCP\User::getUser() has been deprecated with message: 8.0.0 Use \OC::$server->getUserSession()->getUser()->getUID()

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
137
			$path = $ownerView->getPath($info['fileid']);
138
		} else {
139
			$path = $target;
140
		}
141
142
143
		$ids = array();
144
		while ($path !== dirname($path)) {
145
			$info = $ownerView->getFileInfo($path);
146
			if ($info instanceof \OC\Files\FileInfo) {
147
				$ids[] = $info['fileid'];
148
			} else {
149
				\OCP\Util::writeLog('sharing', 'No fileinfo available for: ' . $path, \OCP\Util::WARN);
150
			}
151
			$path = dirname($path);
152
		}
153
154
		if (!empty($ids)) {
155
156
			$idList = array_chunk($ids, 99, true);
157
158
			foreach ($idList as $subList) {
159
				$statement = "SELECT `share_with`, `share_type`, `file_target` FROM `*PREFIX*share` WHERE `file_source` IN (" . implode(',', $subList) . ") AND `share_type` IN (0, 1, 2)";
160
				$query = \OCP\DB::prepare($statement);
0 ignored issues
show
Deprecated Code introduced by
The method OCP\DB::prepare() has been deprecated with message: 8.1.0 use prepare() of \OCP\IDBConnection - \OC::$server->getDatabaseConnection()

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
161
				$r = $query->execute();
162
				$result = array_merge($result, $r->fetchAll());
163
			}
164
		}
165
166
		return $result;
167
	}
168
169
	/**
170
	 * get the UID of the owner of the file and the path to the file relative to
171
	 * owners files folder
172
	 *
173
	 * @param $filename
174
	 * @return array
175
	 * @throws \OC\User\NoUserException
176
	 */
177 View Code Duplication
	public static function getUidAndFilename($filename) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
178
		$uid = Filesystem::getOwner($filename);
179
		$userManager = \OC::$server->getUserManager();
180
		// if the user with the UID doesn't exists, e.g. because the UID points
181
		// to a remote user with a federated cloud ID we use the current logged-in
182
		// user. We need a valid local user to create the share
183
		if (!$userManager->userExists($uid)) {
184
			$uid = User::getUser();
0 ignored issues
show
Deprecated Code introduced by
The method OCP\User::getUser() has been deprecated with message: 8.0.0 Use \OC::$server->getUserSession()->getUser()->getUID()

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
185
		}
186
		Filesystem::initMountPoints($uid);
187
		if ( $uid != User::getUser() ) {
0 ignored issues
show
Deprecated Code introduced by
The method OCP\User::getUser() has been deprecated with message: 8.0.0 Use \OC::$server->getUserSession()->getUser()->getUID()

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
188
			$info = Filesystem::getFileInfo($filename);
189
			$ownerView = new View('/'.$uid.'/files');
190
			try {
191
				$filename = $ownerView->getPath($info['fileid']);
192
			} catch (NotFoundException $e) {
193
				$filename = null;
194
			}
195
		}
196
		return [$uid, $filename];
197
	}
198
199
	/**
200
	 * Format a path to be relative to the /user/files/ directory
201
	 * @param string $path the absolute path
202
	 * @return string e.g. turns '/admin/files/test.txt' into 'test.txt'
203
	 */
204
	public static function stripUserFilesPath($path) {
205
		$trimmed = ltrim($path, '/');
206
		$split = explode('/', $trimmed);
207
208
		// it is not a file relative to data/user/files
209
		if (count($split) < 3 || $split[1] !== 'files') {
210
			return false;
211
		}
212
213
		$sliced = array_slice($split, 2);
214
		$relPath = implode('/', $sliced);
215
216
		return $relPath;
217
	}
218
219
	/**
220
	 * check if file name already exists and generate unique target
221
	 *
222
	 * @param string $path
223
	 * @param array $excludeList
224
	 * @param View $view
225
	 * @return string $path
226
	 */
227
	public static function generateUniqueTarget($path, $excludeList, $view) {
228
		$pathinfo = pathinfo($path);
229
		$ext = (isset($pathinfo['extension'])) ? '.'.$pathinfo['extension'] : '';
230
		$name = $pathinfo['filename'];
231
		$dir = $pathinfo['dirname'];
232
		$i = 2;
233 View Code Duplication
		while ($view->file_exists($path) || in_array($path, $excludeList)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
234
			$path = Filesystem::normalizePath($dir . '/' . $name . ' ('.$i.')' . $ext);
235
			$i++;
236
		}
237
238
		return $path;
239
	}
240
241
	/**
242
	 * get default share folder
243
	 *
244
	 * @param \OC\Files\View
245
	 * @return string
246
	 */
247
	public static function getShareFolder($view = null) {
248
		if ($view === null) {
249
			$view = Filesystem::getView();
250
		}
251
		$shareFolder = \OC::$server->getConfig()->getSystemValue('share_folder', '/');
252
		$shareFolder = Filesystem::normalizePath($shareFolder);
253
254 View Code Duplication
		if (!$view->file_exists($shareFolder)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
255
			$dir = '';
256
			$subdirs = explode('/', $shareFolder);
257
			foreach ($subdirs as $subdir) {
258
				$dir = $dir . '/' . $subdir;
259
				if (!$view->is_dir($dir)) {
260
					$view->mkdir($dir);
261
				}
262
			}
263
		}
264
265
		return $shareFolder;
266
267
	}
268
269
	/**
270
	 * set default share folder
271
	 *
272
	 * @param string $shareFolder
273
	 */
274
	public static function setShareFolder($shareFolder) {
275
		\OC::$server->getConfig()->setSystemValue('share_folder', $shareFolder);
276
	}
277
278
}
279