@@ -30,112 +30,112 @@ |
||
| 30 | 30 | * Storage placeholder to represent a missing precondition, storage unavailable |
| 31 | 31 | */ |
| 32 | 32 | class FailedCache implements ICache { |
| 33 | - /** @var bool whether to show the failed storage in the ui */ |
|
| 34 | - private $visible; |
|
| 35 | - |
|
| 36 | - /** |
|
| 37 | - * FailedCache constructor. |
|
| 38 | - * |
|
| 39 | - * @param bool $visible |
|
| 40 | - */ |
|
| 41 | - public function __construct($visible = true) { |
|
| 42 | - $this->visible = $visible; |
|
| 43 | - } |
|
| 44 | - |
|
| 45 | - |
|
| 46 | - public function getNumericStorageId() { |
|
| 47 | - return -1; |
|
| 48 | - } |
|
| 49 | - |
|
| 50 | - public function get($file) { |
|
| 51 | - if ($file === '') { |
|
| 52 | - return new CacheEntry([ |
|
| 53 | - 'fileid' => -1, |
|
| 54 | - 'size' => 0, |
|
| 55 | - 'mimetype' => 'httpd/unix-directory', |
|
| 56 | - 'mimepart' => 'httpd', |
|
| 57 | - 'permissions' => $this->visible ? Constants::PERMISSION_READ : 0, |
|
| 58 | - 'mtime' => time() |
|
| 59 | - ]); |
|
| 60 | - } else { |
|
| 61 | - return false; |
|
| 62 | - } |
|
| 63 | - } |
|
| 64 | - |
|
| 65 | - public function getFolderContents($folder) { |
|
| 66 | - return []; |
|
| 67 | - } |
|
| 68 | - |
|
| 69 | - public function getFolderContentsById($fileId) { |
|
| 70 | - return []; |
|
| 71 | - } |
|
| 72 | - |
|
| 73 | - public function put($file, array $data) { |
|
| 74 | - } |
|
| 75 | - |
|
| 76 | - public function insert($file, array $data) { |
|
| 77 | - } |
|
| 78 | - |
|
| 79 | - public function update($id, array $data) { |
|
| 80 | - } |
|
| 81 | - |
|
| 82 | - public function getId($file) { |
|
| 83 | - return -1; |
|
| 84 | - } |
|
| 85 | - |
|
| 86 | - public function getParentId($file) { |
|
| 87 | - return -1; |
|
| 88 | - } |
|
| 89 | - |
|
| 90 | - public function inCache($file) { |
|
| 91 | - return false; |
|
| 92 | - } |
|
| 93 | - |
|
| 94 | - public function remove($file) { |
|
| 95 | - } |
|
| 96 | - |
|
| 97 | - public function move($source, $target) { |
|
| 98 | - } |
|
| 99 | - |
|
| 100 | - public function moveFromCache(ICache $sourceCache, $sourcePath, $targetPath) { |
|
| 101 | - } |
|
| 102 | - |
|
| 103 | - public function clear() { |
|
| 104 | - } |
|
| 105 | - |
|
| 106 | - public function getStatus($file) { |
|
| 107 | - return ICache::NOT_FOUND; |
|
| 108 | - } |
|
| 109 | - |
|
| 110 | - public function search($pattern) { |
|
| 111 | - return []; |
|
| 112 | - } |
|
| 113 | - |
|
| 114 | - public function searchByMime($mimetype) { |
|
| 115 | - return []; |
|
| 116 | - } |
|
| 117 | - |
|
| 118 | - public function searchByTag($tag, $userId) { |
|
| 119 | - return []; |
|
| 120 | - } |
|
| 121 | - |
|
| 122 | - public function searchQuery(ISearchQuery $query) { |
|
| 123 | - return []; |
|
| 124 | - } |
|
| 125 | - |
|
| 126 | - public function getAll() { |
|
| 127 | - return []; |
|
| 128 | - } |
|
| 129 | - |
|
| 130 | - public function getIncomplete() { |
|
| 131 | - return []; |
|
| 132 | - } |
|
| 133 | - |
|
| 134 | - public function getPathById($id) { |
|
| 135 | - return null; |
|
| 136 | - } |
|
| 137 | - |
|
| 138 | - public function normalize($path) { |
|
| 139 | - return $path; |
|
| 140 | - } |
|
| 33 | + /** @var bool whether to show the failed storage in the ui */ |
|
| 34 | + private $visible; |
|
| 35 | + |
|
| 36 | + /** |
|
| 37 | + * FailedCache constructor. |
|
| 38 | + * |
|
| 39 | + * @param bool $visible |
|
| 40 | + */ |
|
| 41 | + public function __construct($visible = true) { |
|
| 42 | + $this->visible = $visible; |
|
| 43 | + } |
|
| 44 | + |
|
| 45 | + |
|
| 46 | + public function getNumericStorageId() { |
|
| 47 | + return -1; |
|
| 48 | + } |
|
| 49 | + |
|
| 50 | + public function get($file) { |
|
| 51 | + if ($file === '') { |
|
| 52 | + return new CacheEntry([ |
|
| 53 | + 'fileid' => -1, |
|
| 54 | + 'size' => 0, |
|
| 55 | + 'mimetype' => 'httpd/unix-directory', |
|
| 56 | + 'mimepart' => 'httpd', |
|
| 57 | + 'permissions' => $this->visible ? Constants::PERMISSION_READ : 0, |
|
| 58 | + 'mtime' => time() |
|
| 59 | + ]); |
|
| 60 | + } else { |
|
| 61 | + return false; |
|
| 62 | + } |
|
| 63 | + } |
|
| 64 | + |
|
| 65 | + public function getFolderContents($folder) { |
|
| 66 | + return []; |
|
| 67 | + } |
|
| 68 | + |
|
| 69 | + public function getFolderContentsById($fileId) { |
|
| 70 | + return []; |
|
| 71 | + } |
|
| 72 | + |
|
| 73 | + public function put($file, array $data) { |
|
| 74 | + } |
|
| 75 | + |
|
| 76 | + public function insert($file, array $data) { |
|
| 77 | + } |
|
| 78 | + |
|
| 79 | + public function update($id, array $data) { |
|
| 80 | + } |
|
| 81 | + |
|
| 82 | + public function getId($file) { |
|
| 83 | + return -1; |
|
| 84 | + } |
|
| 85 | + |
|
| 86 | + public function getParentId($file) { |
|
| 87 | + return -1; |
|
| 88 | + } |
|
| 89 | + |
|
| 90 | + public function inCache($file) { |
|
| 91 | + return false; |
|
| 92 | + } |
|
| 93 | + |
|
| 94 | + public function remove($file) { |
|
| 95 | + } |
|
| 96 | + |
|
| 97 | + public function move($source, $target) { |
|
| 98 | + } |
|
| 99 | + |
|
| 100 | + public function moveFromCache(ICache $sourceCache, $sourcePath, $targetPath) { |
|
| 101 | + } |
|
| 102 | + |
|
| 103 | + public function clear() { |
|
| 104 | + } |
|
| 105 | + |
|
| 106 | + public function getStatus($file) { |
|
| 107 | + return ICache::NOT_FOUND; |
|
| 108 | + } |
|
| 109 | + |
|
| 110 | + public function search($pattern) { |
|
| 111 | + return []; |
|
| 112 | + } |
|
| 113 | + |
|
| 114 | + public function searchByMime($mimetype) { |
|
| 115 | + return []; |
|
| 116 | + } |
|
| 117 | + |
|
| 118 | + public function searchByTag($tag, $userId) { |
|
| 119 | + return []; |
|
| 120 | + } |
|
| 121 | + |
|
| 122 | + public function searchQuery(ISearchQuery $query) { |
|
| 123 | + return []; |
|
| 124 | + } |
|
| 125 | + |
|
| 126 | + public function getAll() { |
|
| 127 | + return []; |
|
| 128 | + } |
|
| 129 | + |
|
| 130 | + public function getIncomplete() { |
|
| 131 | + return []; |
|
| 132 | + } |
|
| 133 | + |
|
| 134 | + public function getPathById($id) { |
|
| 135 | + return null; |
|
| 136 | + } |
|
| 137 | + |
|
| 138 | + public function normalize($path) { |
|
| 139 | + return $path; |
|
| 140 | + } |
|
| 141 | 141 | } |
@@ -35,392 +35,392 @@ |
||
| 35 | 35 | |
| 36 | 36 | // FIXME: this class really should be abstract |
| 37 | 37 | class Node implements \OCP\Files\Node { |
| 38 | - /** |
|
| 39 | - * @var \OC\Files\View $view |
|
| 40 | - */ |
|
| 41 | - protected $view; |
|
| 42 | - |
|
| 43 | - /** |
|
| 44 | - * @var \OC\Files\Node\Root $root |
|
| 45 | - */ |
|
| 46 | - protected $root; |
|
| 47 | - |
|
| 48 | - /** |
|
| 49 | - * @var string $path |
|
| 50 | - */ |
|
| 51 | - protected $path; |
|
| 52 | - |
|
| 53 | - /** |
|
| 54 | - * @var \OCP\Files\FileInfo |
|
| 55 | - */ |
|
| 56 | - protected $fileInfo; |
|
| 57 | - |
|
| 58 | - /** |
|
| 59 | - * @param \OC\Files\View $view |
|
| 60 | - * @param \OCP\Files\IRootFolder $root |
|
| 61 | - * @param string $path |
|
| 62 | - * @param FileInfo $fileInfo |
|
| 63 | - */ |
|
| 64 | - public function __construct($root, $view, $path, $fileInfo = null) { |
|
| 65 | - $this->view = $view; |
|
| 66 | - $this->root = $root; |
|
| 67 | - $this->path = $path; |
|
| 68 | - $this->fileInfo = $fileInfo; |
|
| 69 | - } |
|
| 70 | - |
|
| 71 | - /** |
|
| 72 | - * Creates a Node of the same type that represents a non-existing path |
|
| 73 | - * |
|
| 74 | - * @param string $path path |
|
| 75 | - * @return string non-existing node class |
|
| 76 | - */ |
|
| 77 | - protected function createNonExistingNode($path) { |
|
| 78 | - throw new \Exception('Must be implemented by subclasses'); |
|
| 79 | - } |
|
| 80 | - |
|
| 81 | - /** |
|
| 82 | - * Returns the matching file info |
|
| 83 | - * |
|
| 84 | - * @return FileInfo |
|
| 85 | - * @throws InvalidPathException |
|
| 86 | - * @throws NotFoundException |
|
| 87 | - */ |
|
| 88 | - public function getFileInfo() { |
|
| 89 | - if (!Filesystem::isValidPath($this->path)) { |
|
| 90 | - throw new InvalidPathException(); |
|
| 91 | - } |
|
| 92 | - if (!$this->fileInfo) { |
|
| 93 | - $fileInfo = $this->view->getFileInfo($this->path); |
|
| 94 | - if ($fileInfo instanceof FileInfo) { |
|
| 95 | - $this->fileInfo = $fileInfo; |
|
| 96 | - } else { |
|
| 97 | - throw new NotFoundException(); |
|
| 98 | - } |
|
| 99 | - } |
|
| 100 | - return $this->fileInfo; |
|
| 101 | - } |
|
| 102 | - |
|
| 103 | - /** |
|
| 104 | - * @param string[] $hooks |
|
| 105 | - */ |
|
| 106 | - protected function sendHooks($hooks) { |
|
| 107 | - foreach ($hooks as $hook) { |
|
| 108 | - $this->root->emit('\OC\Files', $hook, array($this)); |
|
| 109 | - } |
|
| 110 | - } |
|
| 111 | - |
|
| 112 | - /** |
|
| 113 | - * @param int $permissions |
|
| 114 | - * @return bool |
|
| 115 | - */ |
|
| 116 | - protected function checkPermissions($permissions) { |
|
| 117 | - return ($this->getPermissions() & $permissions) === $permissions; |
|
| 118 | - } |
|
| 119 | - |
|
| 120 | - public function delete() { |
|
| 121 | - } |
|
| 122 | - |
|
| 123 | - /** |
|
| 124 | - * @param int $mtime |
|
| 125 | - * @throws \OCP\Files\NotPermittedException |
|
| 126 | - */ |
|
| 127 | - public function touch($mtime = null) { |
|
| 128 | - if ($this->checkPermissions(\OCP\Constants::PERMISSION_UPDATE)) { |
|
| 129 | - $this->sendHooks(array('preTouch')); |
|
| 130 | - $this->view->touch($this->path, $mtime); |
|
| 131 | - $this->sendHooks(array('postTouch')); |
|
| 132 | - if ($this->fileInfo) { |
|
| 133 | - if (is_null($mtime)) { |
|
| 134 | - $mtime = time(); |
|
| 135 | - } |
|
| 136 | - $this->fileInfo['mtime'] = $mtime; |
|
| 137 | - } |
|
| 138 | - } else { |
|
| 139 | - throw new NotPermittedException(); |
|
| 140 | - } |
|
| 141 | - } |
|
| 142 | - |
|
| 143 | - /** |
|
| 144 | - * @return \OC\Files\Storage\Storage |
|
| 145 | - * @throws \OCP\Files\NotFoundException |
|
| 146 | - */ |
|
| 147 | - public function getStorage() { |
|
| 148 | - list($storage,) = $this->view->resolvePath($this->path); |
|
| 149 | - return $storage; |
|
| 150 | - } |
|
| 151 | - |
|
| 152 | - /** |
|
| 153 | - * @return string |
|
| 154 | - */ |
|
| 155 | - public function getPath() { |
|
| 156 | - return $this->path; |
|
| 157 | - } |
|
| 158 | - |
|
| 159 | - /** |
|
| 160 | - * @return string |
|
| 161 | - */ |
|
| 162 | - public function getInternalPath() { |
|
| 163 | - list(, $internalPath) = $this->view->resolvePath($this->path); |
|
| 164 | - return $internalPath; |
|
| 165 | - } |
|
| 166 | - |
|
| 167 | - /** |
|
| 168 | - * @return int |
|
| 169 | - * @throws InvalidPathException |
|
| 170 | - * @throws NotFoundException |
|
| 171 | - */ |
|
| 172 | - public function getId() { |
|
| 173 | - return $this->getFileInfo()->getId(); |
|
| 174 | - } |
|
| 175 | - |
|
| 176 | - /** |
|
| 177 | - * @return array |
|
| 178 | - */ |
|
| 179 | - public function stat() { |
|
| 180 | - return $this->view->stat($this->path); |
|
| 181 | - } |
|
| 182 | - |
|
| 183 | - /** |
|
| 184 | - * @return int |
|
| 185 | - * @throws InvalidPathException |
|
| 186 | - * @throws NotFoundException |
|
| 187 | - */ |
|
| 188 | - public function getMTime() { |
|
| 189 | - return $this->getFileInfo()->getMTime(); |
|
| 190 | - } |
|
| 191 | - |
|
| 192 | - /** |
|
| 193 | - * @return int |
|
| 194 | - * @throws InvalidPathException |
|
| 195 | - * @throws NotFoundException |
|
| 196 | - */ |
|
| 197 | - public function getSize() { |
|
| 198 | - return $this->getFileInfo()->getSize(); |
|
| 199 | - } |
|
| 200 | - |
|
| 201 | - /** |
|
| 202 | - * @return string |
|
| 203 | - * @throws InvalidPathException |
|
| 204 | - * @throws NotFoundException |
|
| 205 | - */ |
|
| 206 | - public function getEtag() { |
|
| 207 | - return $this->getFileInfo()->getEtag(); |
|
| 208 | - } |
|
| 209 | - |
|
| 210 | - /** |
|
| 211 | - * @return int |
|
| 212 | - * @throws InvalidPathException |
|
| 213 | - * @throws NotFoundException |
|
| 214 | - */ |
|
| 215 | - public function getPermissions() { |
|
| 216 | - return $this->getFileInfo()->getPermissions(); |
|
| 217 | - } |
|
| 218 | - |
|
| 219 | - /** |
|
| 220 | - * @return bool |
|
| 221 | - * @throws InvalidPathException |
|
| 222 | - * @throws NotFoundException |
|
| 223 | - */ |
|
| 224 | - public function isReadable() { |
|
| 225 | - return $this->getFileInfo()->isReadable(); |
|
| 226 | - } |
|
| 227 | - |
|
| 228 | - /** |
|
| 229 | - * @return bool |
|
| 230 | - * @throws InvalidPathException |
|
| 231 | - * @throws NotFoundException |
|
| 232 | - */ |
|
| 233 | - public function isUpdateable() { |
|
| 234 | - return $this->getFileInfo()->isUpdateable(); |
|
| 235 | - } |
|
| 236 | - |
|
| 237 | - /** |
|
| 238 | - * @return bool |
|
| 239 | - * @throws InvalidPathException |
|
| 240 | - * @throws NotFoundException |
|
| 241 | - */ |
|
| 242 | - public function isDeletable() { |
|
| 243 | - return $this->getFileInfo()->isDeletable(); |
|
| 244 | - } |
|
| 245 | - |
|
| 246 | - /** |
|
| 247 | - * @return bool |
|
| 248 | - * @throws InvalidPathException |
|
| 249 | - * @throws NotFoundException |
|
| 250 | - */ |
|
| 251 | - public function isShareable() { |
|
| 252 | - return $this->getFileInfo()->isShareable(); |
|
| 253 | - } |
|
| 254 | - |
|
| 255 | - /** |
|
| 256 | - * @return bool |
|
| 257 | - * @throws InvalidPathException |
|
| 258 | - * @throws NotFoundException |
|
| 259 | - */ |
|
| 260 | - public function isCreatable() { |
|
| 261 | - return $this->getFileInfo()->isCreatable(); |
|
| 262 | - } |
|
| 263 | - |
|
| 264 | - /** |
|
| 265 | - * @return Node |
|
| 266 | - */ |
|
| 267 | - public function getParent() { |
|
| 268 | - return $this->root->get(dirname($this->path)); |
|
| 269 | - } |
|
| 270 | - |
|
| 271 | - /** |
|
| 272 | - * @return string |
|
| 273 | - */ |
|
| 274 | - public function getName() { |
|
| 275 | - return basename($this->path); |
|
| 276 | - } |
|
| 277 | - |
|
| 278 | - /** |
|
| 279 | - * @param string $path |
|
| 280 | - * @return string |
|
| 281 | - */ |
|
| 282 | - protected function normalizePath($path) { |
|
| 283 | - if ($path === '' or $path === '/') { |
|
| 284 | - return '/'; |
|
| 285 | - } |
|
| 286 | - //no windows style slashes |
|
| 287 | - $path = str_replace('\\', '/', $path); |
|
| 288 | - //add leading slash |
|
| 289 | - if ($path[0] !== '/') { |
|
| 290 | - $path = '/' . $path; |
|
| 291 | - } |
|
| 292 | - //remove duplicate slashes |
|
| 293 | - while (strpos($path, '//') !== false) { |
|
| 294 | - $path = str_replace('//', '/', $path); |
|
| 295 | - } |
|
| 296 | - //remove trailing slash |
|
| 297 | - $path = rtrim($path, '/'); |
|
| 298 | - |
|
| 299 | - return $path; |
|
| 300 | - } |
|
| 301 | - |
|
| 302 | - /** |
|
| 303 | - * check if the requested path is valid |
|
| 304 | - * |
|
| 305 | - * @param string $path |
|
| 306 | - * @return bool |
|
| 307 | - */ |
|
| 308 | - public function isValidPath($path) { |
|
| 309 | - if (!$path || $path[0] !== '/') { |
|
| 310 | - $path = '/' . $path; |
|
| 311 | - } |
|
| 312 | - if (strstr($path, '/../') || strrchr($path, '/') === '/..') { |
|
| 313 | - return false; |
|
| 314 | - } |
|
| 315 | - return true; |
|
| 316 | - } |
|
| 317 | - |
|
| 318 | - public function isMounted() { |
|
| 319 | - return $this->getFileInfo()->isMounted(); |
|
| 320 | - } |
|
| 321 | - |
|
| 322 | - public function isShared() { |
|
| 323 | - return $this->getFileInfo()->isShared(); |
|
| 324 | - } |
|
| 325 | - |
|
| 326 | - public function getMimeType() { |
|
| 327 | - return $this->getFileInfo()->getMimetype(); |
|
| 328 | - } |
|
| 329 | - |
|
| 330 | - public function getMimePart() { |
|
| 331 | - return $this->getFileInfo()->getMimePart(); |
|
| 332 | - } |
|
| 333 | - |
|
| 334 | - public function getType() { |
|
| 335 | - return $this->getFileInfo()->getType(); |
|
| 336 | - } |
|
| 337 | - |
|
| 338 | - public function isEncrypted() { |
|
| 339 | - return $this->getFileInfo()->isEncrypted(); |
|
| 340 | - } |
|
| 341 | - |
|
| 342 | - public function getMountPoint() { |
|
| 343 | - return $this->getFileInfo()->getMountPoint(); |
|
| 344 | - } |
|
| 345 | - |
|
| 346 | - public function getOwner() { |
|
| 347 | - return $this->getFileInfo()->getOwner(); |
|
| 348 | - } |
|
| 349 | - |
|
| 350 | - public function getChecksum() { |
|
| 351 | - } |
|
| 352 | - |
|
| 353 | - /** |
|
| 354 | - * @param int $type \OCP\Lock\ILockingProvider::LOCK_SHARED or \OCP\Lock\ILockingProvider::LOCK_EXCLUSIVE |
|
| 355 | - * @throws \OCP\Lock\LockedException |
|
| 356 | - */ |
|
| 357 | - public function lock($type) { |
|
| 358 | - $this->view->lockFile($this->path, $type); |
|
| 359 | - } |
|
| 360 | - |
|
| 361 | - /** |
|
| 362 | - * @param int $type \OCP\Lock\ILockingProvider::LOCK_SHARED or \OCP\Lock\ILockingProvider::LOCK_EXCLUSIVE |
|
| 363 | - * @throws \OCP\Lock\LockedException |
|
| 364 | - */ |
|
| 365 | - public function changeLock($type) { |
|
| 366 | - $this->view->changeLock($this->path, $type); |
|
| 367 | - } |
|
| 368 | - |
|
| 369 | - /** |
|
| 370 | - * @param int $type \OCP\Lock\ILockingProvider::LOCK_SHARED or \OCP\Lock\ILockingProvider::LOCK_EXCLUSIVE |
|
| 371 | - * @throws \OCP\Lock\LockedException |
|
| 372 | - */ |
|
| 373 | - public function unlock($type) { |
|
| 374 | - $this->view->unlockFile($this->path, $type); |
|
| 375 | - } |
|
| 376 | - |
|
| 377 | - /** |
|
| 378 | - * @param string $targetPath |
|
| 379 | - * @throws \OCP\Files\NotPermittedException if copy not allowed or failed |
|
| 380 | - * @return \OC\Files\Node\Node |
|
| 381 | - */ |
|
| 382 | - public function copy($targetPath) { |
|
| 383 | - $targetPath = $this->normalizePath($targetPath); |
|
| 384 | - $parent = $this->root->get(dirname($targetPath)); |
|
| 385 | - if ($parent instanceof Folder and $this->isValidPath($targetPath) and $parent->isCreatable()) { |
|
| 386 | - $nonExisting = $this->createNonExistingNode($targetPath); |
|
| 387 | - $this->root->emit('\OC\Files', 'preCopy', [$this, $nonExisting]); |
|
| 388 | - $this->root->emit('\OC\Files', 'preWrite', [$nonExisting]); |
|
| 389 | - if (!$this->view->copy($this->path, $targetPath)) { |
|
| 390 | - throw new NotPermittedException('Could not copy ' . $this->path . ' to ' . $targetPath); |
|
| 391 | - } |
|
| 392 | - $targetNode = $this->root->get($targetPath); |
|
| 393 | - $this->root->emit('\OC\Files', 'postCopy', [$this, $targetNode]); |
|
| 394 | - $this->root->emit('\OC\Files', 'postWrite', [$targetNode]); |
|
| 395 | - return $targetNode; |
|
| 396 | - } else { |
|
| 397 | - throw new NotPermittedException('No permission to copy to path ' . $targetPath); |
|
| 398 | - } |
|
| 399 | - } |
|
| 400 | - |
|
| 401 | - /** |
|
| 402 | - * @param string $targetPath |
|
| 403 | - * @throws \OCP\Files\NotPermittedException if move not allowed or failed |
|
| 404 | - * @return \OC\Files\Node\Node |
|
| 405 | - */ |
|
| 406 | - public function move($targetPath) { |
|
| 407 | - $targetPath = $this->normalizePath($targetPath); |
|
| 408 | - $parent = $this->root->get(dirname($targetPath)); |
|
| 409 | - if ($parent instanceof Folder and $this->isValidPath($targetPath) and $parent->isCreatable()) { |
|
| 410 | - $nonExisting = $this->createNonExistingNode($targetPath); |
|
| 411 | - $this->root->emit('\OC\Files', 'preRename', [$this, $nonExisting]); |
|
| 412 | - $this->root->emit('\OC\Files', 'preWrite', [$nonExisting]); |
|
| 413 | - if (!$this->view->rename($this->path, $targetPath)) { |
|
| 414 | - throw new NotPermittedException('Could not move ' . $this->path . ' to ' . $targetPath); |
|
| 415 | - } |
|
| 416 | - $targetNode = $this->root->get($targetPath); |
|
| 417 | - $this->root->emit('\OC\Files', 'postRename', [$this, $targetNode]); |
|
| 418 | - $this->root->emit('\OC\Files', 'postWrite', [$targetNode]); |
|
| 419 | - $this->path = $targetPath; |
|
| 420 | - return $targetNode; |
|
| 421 | - } else { |
|
| 422 | - throw new NotPermittedException('No permission to move to path ' . $targetPath); |
|
| 423 | - } |
|
| 424 | - } |
|
| 38 | + /** |
|
| 39 | + * @var \OC\Files\View $view |
|
| 40 | + */ |
|
| 41 | + protected $view; |
|
| 42 | + |
|
| 43 | + /** |
|
| 44 | + * @var \OC\Files\Node\Root $root |
|
| 45 | + */ |
|
| 46 | + protected $root; |
|
| 47 | + |
|
| 48 | + /** |
|
| 49 | + * @var string $path |
|
| 50 | + */ |
|
| 51 | + protected $path; |
|
| 52 | + |
|
| 53 | + /** |
|
| 54 | + * @var \OCP\Files\FileInfo |
|
| 55 | + */ |
|
| 56 | + protected $fileInfo; |
|
| 57 | + |
|
| 58 | + /** |
|
| 59 | + * @param \OC\Files\View $view |
|
| 60 | + * @param \OCP\Files\IRootFolder $root |
|
| 61 | + * @param string $path |
|
| 62 | + * @param FileInfo $fileInfo |
|
| 63 | + */ |
|
| 64 | + public function __construct($root, $view, $path, $fileInfo = null) { |
|
| 65 | + $this->view = $view; |
|
| 66 | + $this->root = $root; |
|
| 67 | + $this->path = $path; |
|
| 68 | + $this->fileInfo = $fileInfo; |
|
| 69 | + } |
|
| 70 | + |
|
| 71 | + /** |
|
| 72 | + * Creates a Node of the same type that represents a non-existing path |
|
| 73 | + * |
|
| 74 | + * @param string $path path |
|
| 75 | + * @return string non-existing node class |
|
| 76 | + */ |
|
| 77 | + protected function createNonExistingNode($path) { |
|
| 78 | + throw new \Exception('Must be implemented by subclasses'); |
|
| 79 | + } |
|
| 80 | + |
|
| 81 | + /** |
|
| 82 | + * Returns the matching file info |
|
| 83 | + * |
|
| 84 | + * @return FileInfo |
|
| 85 | + * @throws InvalidPathException |
|
| 86 | + * @throws NotFoundException |
|
| 87 | + */ |
|
| 88 | + public function getFileInfo() { |
|
| 89 | + if (!Filesystem::isValidPath($this->path)) { |
|
| 90 | + throw new InvalidPathException(); |
|
| 91 | + } |
|
| 92 | + if (!$this->fileInfo) { |
|
| 93 | + $fileInfo = $this->view->getFileInfo($this->path); |
|
| 94 | + if ($fileInfo instanceof FileInfo) { |
|
| 95 | + $this->fileInfo = $fileInfo; |
|
| 96 | + } else { |
|
| 97 | + throw new NotFoundException(); |
|
| 98 | + } |
|
| 99 | + } |
|
| 100 | + return $this->fileInfo; |
|
| 101 | + } |
|
| 102 | + |
|
| 103 | + /** |
|
| 104 | + * @param string[] $hooks |
|
| 105 | + */ |
|
| 106 | + protected function sendHooks($hooks) { |
|
| 107 | + foreach ($hooks as $hook) { |
|
| 108 | + $this->root->emit('\OC\Files', $hook, array($this)); |
|
| 109 | + } |
|
| 110 | + } |
|
| 111 | + |
|
| 112 | + /** |
|
| 113 | + * @param int $permissions |
|
| 114 | + * @return bool |
|
| 115 | + */ |
|
| 116 | + protected function checkPermissions($permissions) { |
|
| 117 | + return ($this->getPermissions() & $permissions) === $permissions; |
|
| 118 | + } |
|
| 119 | + |
|
| 120 | + public function delete() { |
|
| 121 | + } |
|
| 122 | + |
|
| 123 | + /** |
|
| 124 | + * @param int $mtime |
|
| 125 | + * @throws \OCP\Files\NotPermittedException |
|
| 126 | + */ |
|
| 127 | + public function touch($mtime = null) { |
|
| 128 | + if ($this->checkPermissions(\OCP\Constants::PERMISSION_UPDATE)) { |
|
| 129 | + $this->sendHooks(array('preTouch')); |
|
| 130 | + $this->view->touch($this->path, $mtime); |
|
| 131 | + $this->sendHooks(array('postTouch')); |
|
| 132 | + if ($this->fileInfo) { |
|
| 133 | + if (is_null($mtime)) { |
|
| 134 | + $mtime = time(); |
|
| 135 | + } |
|
| 136 | + $this->fileInfo['mtime'] = $mtime; |
|
| 137 | + } |
|
| 138 | + } else { |
|
| 139 | + throw new NotPermittedException(); |
|
| 140 | + } |
|
| 141 | + } |
|
| 142 | + |
|
| 143 | + /** |
|
| 144 | + * @return \OC\Files\Storage\Storage |
|
| 145 | + * @throws \OCP\Files\NotFoundException |
|
| 146 | + */ |
|
| 147 | + public function getStorage() { |
|
| 148 | + list($storage,) = $this->view->resolvePath($this->path); |
|
| 149 | + return $storage; |
|
| 150 | + } |
|
| 151 | + |
|
| 152 | + /** |
|
| 153 | + * @return string |
|
| 154 | + */ |
|
| 155 | + public function getPath() { |
|
| 156 | + return $this->path; |
|
| 157 | + } |
|
| 158 | + |
|
| 159 | + /** |
|
| 160 | + * @return string |
|
| 161 | + */ |
|
| 162 | + public function getInternalPath() { |
|
| 163 | + list(, $internalPath) = $this->view->resolvePath($this->path); |
|
| 164 | + return $internalPath; |
|
| 165 | + } |
|
| 166 | + |
|
| 167 | + /** |
|
| 168 | + * @return int |
|
| 169 | + * @throws InvalidPathException |
|
| 170 | + * @throws NotFoundException |
|
| 171 | + */ |
|
| 172 | + public function getId() { |
|
| 173 | + return $this->getFileInfo()->getId(); |
|
| 174 | + } |
|
| 175 | + |
|
| 176 | + /** |
|
| 177 | + * @return array |
|
| 178 | + */ |
|
| 179 | + public function stat() { |
|
| 180 | + return $this->view->stat($this->path); |
|
| 181 | + } |
|
| 182 | + |
|
| 183 | + /** |
|
| 184 | + * @return int |
|
| 185 | + * @throws InvalidPathException |
|
| 186 | + * @throws NotFoundException |
|
| 187 | + */ |
|
| 188 | + public function getMTime() { |
|
| 189 | + return $this->getFileInfo()->getMTime(); |
|
| 190 | + } |
|
| 191 | + |
|
| 192 | + /** |
|
| 193 | + * @return int |
|
| 194 | + * @throws InvalidPathException |
|
| 195 | + * @throws NotFoundException |
|
| 196 | + */ |
|
| 197 | + public function getSize() { |
|
| 198 | + return $this->getFileInfo()->getSize(); |
|
| 199 | + } |
|
| 200 | + |
|
| 201 | + /** |
|
| 202 | + * @return string |
|
| 203 | + * @throws InvalidPathException |
|
| 204 | + * @throws NotFoundException |
|
| 205 | + */ |
|
| 206 | + public function getEtag() { |
|
| 207 | + return $this->getFileInfo()->getEtag(); |
|
| 208 | + } |
|
| 209 | + |
|
| 210 | + /** |
|
| 211 | + * @return int |
|
| 212 | + * @throws InvalidPathException |
|
| 213 | + * @throws NotFoundException |
|
| 214 | + */ |
|
| 215 | + public function getPermissions() { |
|
| 216 | + return $this->getFileInfo()->getPermissions(); |
|
| 217 | + } |
|
| 218 | + |
|
| 219 | + /** |
|
| 220 | + * @return bool |
|
| 221 | + * @throws InvalidPathException |
|
| 222 | + * @throws NotFoundException |
|
| 223 | + */ |
|
| 224 | + public function isReadable() { |
|
| 225 | + return $this->getFileInfo()->isReadable(); |
|
| 226 | + } |
|
| 227 | + |
|
| 228 | + /** |
|
| 229 | + * @return bool |
|
| 230 | + * @throws InvalidPathException |
|
| 231 | + * @throws NotFoundException |
|
| 232 | + */ |
|
| 233 | + public function isUpdateable() { |
|
| 234 | + return $this->getFileInfo()->isUpdateable(); |
|
| 235 | + } |
|
| 236 | + |
|
| 237 | + /** |
|
| 238 | + * @return bool |
|
| 239 | + * @throws InvalidPathException |
|
| 240 | + * @throws NotFoundException |
|
| 241 | + */ |
|
| 242 | + public function isDeletable() { |
|
| 243 | + return $this->getFileInfo()->isDeletable(); |
|
| 244 | + } |
|
| 245 | + |
|
| 246 | + /** |
|
| 247 | + * @return bool |
|
| 248 | + * @throws InvalidPathException |
|
| 249 | + * @throws NotFoundException |
|
| 250 | + */ |
|
| 251 | + public function isShareable() { |
|
| 252 | + return $this->getFileInfo()->isShareable(); |
|
| 253 | + } |
|
| 254 | + |
|
| 255 | + /** |
|
| 256 | + * @return bool |
|
| 257 | + * @throws InvalidPathException |
|
| 258 | + * @throws NotFoundException |
|
| 259 | + */ |
|
| 260 | + public function isCreatable() { |
|
| 261 | + return $this->getFileInfo()->isCreatable(); |
|
| 262 | + } |
|
| 263 | + |
|
| 264 | + /** |
|
| 265 | + * @return Node |
|
| 266 | + */ |
|
| 267 | + public function getParent() { |
|
| 268 | + return $this->root->get(dirname($this->path)); |
|
| 269 | + } |
|
| 270 | + |
|
| 271 | + /** |
|
| 272 | + * @return string |
|
| 273 | + */ |
|
| 274 | + public function getName() { |
|
| 275 | + return basename($this->path); |
|
| 276 | + } |
|
| 277 | + |
|
| 278 | + /** |
|
| 279 | + * @param string $path |
|
| 280 | + * @return string |
|
| 281 | + */ |
|
| 282 | + protected function normalizePath($path) { |
|
| 283 | + if ($path === '' or $path === '/') { |
|
| 284 | + return '/'; |
|
| 285 | + } |
|
| 286 | + //no windows style slashes |
|
| 287 | + $path = str_replace('\\', '/', $path); |
|
| 288 | + //add leading slash |
|
| 289 | + if ($path[0] !== '/') { |
|
| 290 | + $path = '/' . $path; |
|
| 291 | + } |
|
| 292 | + //remove duplicate slashes |
|
| 293 | + while (strpos($path, '//') !== false) { |
|
| 294 | + $path = str_replace('//', '/', $path); |
|
| 295 | + } |
|
| 296 | + //remove trailing slash |
|
| 297 | + $path = rtrim($path, '/'); |
|
| 298 | + |
|
| 299 | + return $path; |
|
| 300 | + } |
|
| 301 | + |
|
| 302 | + /** |
|
| 303 | + * check if the requested path is valid |
|
| 304 | + * |
|
| 305 | + * @param string $path |
|
| 306 | + * @return bool |
|
| 307 | + */ |
|
| 308 | + public function isValidPath($path) { |
|
| 309 | + if (!$path || $path[0] !== '/') { |
|
| 310 | + $path = '/' . $path; |
|
| 311 | + } |
|
| 312 | + if (strstr($path, '/../') || strrchr($path, '/') === '/..') { |
|
| 313 | + return false; |
|
| 314 | + } |
|
| 315 | + return true; |
|
| 316 | + } |
|
| 317 | + |
|
| 318 | + public function isMounted() { |
|
| 319 | + return $this->getFileInfo()->isMounted(); |
|
| 320 | + } |
|
| 321 | + |
|
| 322 | + public function isShared() { |
|
| 323 | + return $this->getFileInfo()->isShared(); |
|
| 324 | + } |
|
| 325 | + |
|
| 326 | + public function getMimeType() { |
|
| 327 | + return $this->getFileInfo()->getMimetype(); |
|
| 328 | + } |
|
| 329 | + |
|
| 330 | + public function getMimePart() { |
|
| 331 | + return $this->getFileInfo()->getMimePart(); |
|
| 332 | + } |
|
| 333 | + |
|
| 334 | + public function getType() { |
|
| 335 | + return $this->getFileInfo()->getType(); |
|
| 336 | + } |
|
| 337 | + |
|
| 338 | + public function isEncrypted() { |
|
| 339 | + return $this->getFileInfo()->isEncrypted(); |
|
| 340 | + } |
|
| 341 | + |
|
| 342 | + public function getMountPoint() { |
|
| 343 | + return $this->getFileInfo()->getMountPoint(); |
|
| 344 | + } |
|
| 345 | + |
|
| 346 | + public function getOwner() { |
|
| 347 | + return $this->getFileInfo()->getOwner(); |
|
| 348 | + } |
|
| 349 | + |
|
| 350 | + public function getChecksum() { |
|
| 351 | + } |
|
| 352 | + |
|
| 353 | + /** |
|
| 354 | + * @param int $type \OCP\Lock\ILockingProvider::LOCK_SHARED or \OCP\Lock\ILockingProvider::LOCK_EXCLUSIVE |
|
| 355 | + * @throws \OCP\Lock\LockedException |
|
| 356 | + */ |
|
| 357 | + public function lock($type) { |
|
| 358 | + $this->view->lockFile($this->path, $type); |
|
| 359 | + } |
|
| 360 | + |
|
| 361 | + /** |
|
| 362 | + * @param int $type \OCP\Lock\ILockingProvider::LOCK_SHARED or \OCP\Lock\ILockingProvider::LOCK_EXCLUSIVE |
|
| 363 | + * @throws \OCP\Lock\LockedException |
|
| 364 | + */ |
|
| 365 | + public function changeLock($type) { |
|
| 366 | + $this->view->changeLock($this->path, $type); |
|
| 367 | + } |
|
| 368 | + |
|
| 369 | + /** |
|
| 370 | + * @param int $type \OCP\Lock\ILockingProvider::LOCK_SHARED or \OCP\Lock\ILockingProvider::LOCK_EXCLUSIVE |
|
| 371 | + * @throws \OCP\Lock\LockedException |
|
| 372 | + */ |
|
| 373 | + public function unlock($type) { |
|
| 374 | + $this->view->unlockFile($this->path, $type); |
|
| 375 | + } |
|
| 376 | + |
|
| 377 | + /** |
|
| 378 | + * @param string $targetPath |
|
| 379 | + * @throws \OCP\Files\NotPermittedException if copy not allowed or failed |
|
| 380 | + * @return \OC\Files\Node\Node |
|
| 381 | + */ |
|
| 382 | + public function copy($targetPath) { |
|
| 383 | + $targetPath = $this->normalizePath($targetPath); |
|
| 384 | + $parent = $this->root->get(dirname($targetPath)); |
|
| 385 | + if ($parent instanceof Folder and $this->isValidPath($targetPath) and $parent->isCreatable()) { |
|
| 386 | + $nonExisting = $this->createNonExistingNode($targetPath); |
|
| 387 | + $this->root->emit('\OC\Files', 'preCopy', [$this, $nonExisting]); |
|
| 388 | + $this->root->emit('\OC\Files', 'preWrite', [$nonExisting]); |
|
| 389 | + if (!$this->view->copy($this->path, $targetPath)) { |
|
| 390 | + throw new NotPermittedException('Could not copy ' . $this->path . ' to ' . $targetPath); |
|
| 391 | + } |
|
| 392 | + $targetNode = $this->root->get($targetPath); |
|
| 393 | + $this->root->emit('\OC\Files', 'postCopy', [$this, $targetNode]); |
|
| 394 | + $this->root->emit('\OC\Files', 'postWrite', [$targetNode]); |
|
| 395 | + return $targetNode; |
|
| 396 | + } else { |
|
| 397 | + throw new NotPermittedException('No permission to copy to path ' . $targetPath); |
|
| 398 | + } |
|
| 399 | + } |
|
| 400 | + |
|
| 401 | + /** |
|
| 402 | + * @param string $targetPath |
|
| 403 | + * @throws \OCP\Files\NotPermittedException if move not allowed or failed |
|
| 404 | + * @return \OC\Files\Node\Node |
|
| 405 | + */ |
|
| 406 | + public function move($targetPath) { |
|
| 407 | + $targetPath = $this->normalizePath($targetPath); |
|
| 408 | + $parent = $this->root->get(dirname($targetPath)); |
|
| 409 | + if ($parent instanceof Folder and $this->isValidPath($targetPath) and $parent->isCreatable()) { |
|
| 410 | + $nonExisting = $this->createNonExistingNode($targetPath); |
|
| 411 | + $this->root->emit('\OC\Files', 'preRename', [$this, $nonExisting]); |
|
| 412 | + $this->root->emit('\OC\Files', 'preWrite', [$nonExisting]); |
|
| 413 | + if (!$this->view->rename($this->path, $targetPath)) { |
|
| 414 | + throw new NotPermittedException('Could not move ' . $this->path . ' to ' . $targetPath); |
|
| 415 | + } |
|
| 416 | + $targetNode = $this->root->get($targetPath); |
|
| 417 | + $this->root->emit('\OC\Files', 'postRename', [$this, $targetNode]); |
|
| 418 | + $this->root->emit('\OC\Files', 'postWrite', [$targetNode]); |
|
| 419 | + $this->path = $targetPath; |
|
| 420 | + return $targetNode; |
|
| 421 | + } else { |
|
| 422 | + throw new NotPermittedException('No permission to move to path ' . $targetPath); |
|
| 423 | + } |
|
| 424 | + } |
|
| 425 | 425 | |
| 426 | 426 | } |
@@ -27,15 +27,15 @@ |
||
| 27 | 27 | |
| 28 | 28 | class Plugin extends \Sabre\CalDAV\Plugin { |
| 29 | 29 | |
| 30 | - /** |
|
| 31 | - * @inheritdoc |
|
| 32 | - */ |
|
| 33 | - function getCalendarHomeForPrincipal($principalUrl) { |
|
| 30 | + /** |
|
| 31 | + * @inheritdoc |
|
| 32 | + */ |
|
| 33 | + function getCalendarHomeForPrincipal($principalUrl) { |
|
| 34 | 34 | |
| 35 | - if (strrpos($principalUrl, 'principals/users', -strlen($principalUrl)) !== false) { |
|
| 36 | - list(, $principalId) = \Sabre\Uri\split($principalUrl); |
|
| 37 | - return self::CALENDAR_ROOT .'/' . $principalId; |
|
| 38 | - } |
|
| 39 | - } |
|
| 35 | + if (strrpos($principalUrl, 'principals/users', -strlen($principalUrl)) !== false) { |
|
| 36 | + list(, $principalId) = \Sabre\Uri\split($principalUrl); |
|
| 37 | + return self::CALENDAR_ROOT .'/' . $principalId; |
|
| 38 | + } |
|
| 39 | + } |
|
| 40 | 40 | |
| 41 | 41 | } |
@@ -34,7 +34,7 @@ |
||
| 34 | 34 | |
| 35 | 35 | if (strrpos($principalUrl, 'principals/users', -strlen($principalUrl)) !== false) { |
| 36 | 36 | list(, $principalId) = \Sabre\Uri\split($principalUrl); |
| 37 | - return self::CALENDAR_ROOT .'/' . $principalId; |
|
| 37 | + return self::CALENDAR_ROOT.'/'.$principalId; |
|
| 38 | 38 | } |
| 39 | 39 | } |
| 40 | 40 | |
@@ -53,1036 +53,1036 @@ |
||
| 53 | 53 | */ |
| 54 | 54 | class ShareByMailProvider implements IShareProvider { |
| 55 | 55 | |
| 56 | - /** @var IDBConnection */ |
|
| 57 | - private $dbConnection; |
|
| 58 | - |
|
| 59 | - /** @var ILogger */ |
|
| 60 | - private $logger; |
|
| 61 | - |
|
| 62 | - /** @var ISecureRandom */ |
|
| 63 | - private $secureRandom; |
|
| 64 | - |
|
| 65 | - /** @var IUserManager */ |
|
| 66 | - private $userManager; |
|
| 67 | - |
|
| 68 | - /** @var IRootFolder */ |
|
| 69 | - private $rootFolder; |
|
| 70 | - |
|
| 71 | - /** @var IL10N */ |
|
| 72 | - private $l; |
|
| 73 | - |
|
| 74 | - /** @var IMailer */ |
|
| 75 | - private $mailer; |
|
| 76 | - |
|
| 77 | - /** @var IURLGenerator */ |
|
| 78 | - private $urlGenerator; |
|
| 79 | - |
|
| 80 | - /** @var IManager */ |
|
| 81 | - private $activityManager; |
|
| 82 | - |
|
| 83 | - /** @var SettingsManager */ |
|
| 84 | - private $settingsManager; |
|
| 85 | - |
|
| 86 | - /** @var Defaults */ |
|
| 87 | - private $defaults; |
|
| 88 | - |
|
| 89 | - /** @var IHasher */ |
|
| 90 | - private $hasher; |
|
| 91 | - |
|
| 92 | - /** @var CapabilitiesManager */ |
|
| 93 | - private $capabilitiesManager; |
|
| 94 | - |
|
| 95 | - /** |
|
| 96 | - * Return the identifier of this provider. |
|
| 97 | - * |
|
| 98 | - * @return string Containing only [a-zA-Z0-9] |
|
| 99 | - */ |
|
| 100 | - public function identifier() { |
|
| 101 | - return 'ocMailShare'; |
|
| 102 | - } |
|
| 103 | - |
|
| 104 | - /** |
|
| 105 | - * DefaultShareProvider constructor. |
|
| 106 | - * |
|
| 107 | - * @param IDBConnection $connection |
|
| 108 | - * @param ISecureRandom $secureRandom |
|
| 109 | - * @param IUserManager $userManager |
|
| 110 | - * @param IRootFolder $rootFolder |
|
| 111 | - * @param IL10N $l |
|
| 112 | - * @param ILogger $logger |
|
| 113 | - * @param IMailer $mailer |
|
| 114 | - * @param IURLGenerator $urlGenerator |
|
| 115 | - * @param IManager $activityManager |
|
| 116 | - * @param SettingsManager $settingsManager |
|
| 117 | - * @param Defaults $defaults |
|
| 118 | - * @param IHasher $hasher |
|
| 119 | - * @param CapabilitiesManager $capabilitiesManager |
|
| 120 | - */ |
|
| 121 | - public function __construct( |
|
| 122 | - IDBConnection $connection, |
|
| 123 | - ISecureRandom $secureRandom, |
|
| 124 | - IUserManager $userManager, |
|
| 125 | - IRootFolder $rootFolder, |
|
| 126 | - IL10N $l, |
|
| 127 | - ILogger $logger, |
|
| 128 | - IMailer $mailer, |
|
| 129 | - IURLGenerator $urlGenerator, |
|
| 130 | - IManager $activityManager, |
|
| 131 | - SettingsManager $settingsManager, |
|
| 132 | - Defaults $defaults, |
|
| 133 | - IHasher $hasher, |
|
| 134 | - CapabilitiesManager $capabilitiesManager |
|
| 135 | - ) { |
|
| 136 | - $this->dbConnection = $connection; |
|
| 137 | - $this->secureRandom = $secureRandom; |
|
| 138 | - $this->userManager = $userManager; |
|
| 139 | - $this->rootFolder = $rootFolder; |
|
| 140 | - $this->l = $l; |
|
| 141 | - $this->logger = $logger; |
|
| 142 | - $this->mailer = $mailer; |
|
| 143 | - $this->urlGenerator = $urlGenerator; |
|
| 144 | - $this->activityManager = $activityManager; |
|
| 145 | - $this->settingsManager = $settingsManager; |
|
| 146 | - $this->defaults = $defaults; |
|
| 147 | - $this->hasher = $hasher; |
|
| 148 | - $this->capabilitiesManager = $capabilitiesManager; |
|
| 149 | - } |
|
| 150 | - |
|
| 151 | - /** |
|
| 152 | - * Share a path |
|
| 153 | - * |
|
| 154 | - * @param IShare $share |
|
| 155 | - * @return IShare The share object |
|
| 156 | - * @throws ShareNotFound |
|
| 157 | - * @throws \Exception |
|
| 158 | - */ |
|
| 159 | - public function create(IShare $share) { |
|
| 160 | - |
|
| 161 | - $shareWith = $share->getSharedWith(); |
|
| 162 | - /* |
|
| 56 | + /** @var IDBConnection */ |
|
| 57 | + private $dbConnection; |
|
| 58 | + |
|
| 59 | + /** @var ILogger */ |
|
| 60 | + private $logger; |
|
| 61 | + |
|
| 62 | + /** @var ISecureRandom */ |
|
| 63 | + private $secureRandom; |
|
| 64 | + |
|
| 65 | + /** @var IUserManager */ |
|
| 66 | + private $userManager; |
|
| 67 | + |
|
| 68 | + /** @var IRootFolder */ |
|
| 69 | + private $rootFolder; |
|
| 70 | + |
|
| 71 | + /** @var IL10N */ |
|
| 72 | + private $l; |
|
| 73 | + |
|
| 74 | + /** @var IMailer */ |
|
| 75 | + private $mailer; |
|
| 76 | + |
|
| 77 | + /** @var IURLGenerator */ |
|
| 78 | + private $urlGenerator; |
|
| 79 | + |
|
| 80 | + /** @var IManager */ |
|
| 81 | + private $activityManager; |
|
| 82 | + |
|
| 83 | + /** @var SettingsManager */ |
|
| 84 | + private $settingsManager; |
|
| 85 | + |
|
| 86 | + /** @var Defaults */ |
|
| 87 | + private $defaults; |
|
| 88 | + |
|
| 89 | + /** @var IHasher */ |
|
| 90 | + private $hasher; |
|
| 91 | + |
|
| 92 | + /** @var CapabilitiesManager */ |
|
| 93 | + private $capabilitiesManager; |
|
| 94 | + |
|
| 95 | + /** |
|
| 96 | + * Return the identifier of this provider. |
|
| 97 | + * |
|
| 98 | + * @return string Containing only [a-zA-Z0-9] |
|
| 99 | + */ |
|
| 100 | + public function identifier() { |
|
| 101 | + return 'ocMailShare'; |
|
| 102 | + } |
|
| 103 | + |
|
| 104 | + /** |
|
| 105 | + * DefaultShareProvider constructor. |
|
| 106 | + * |
|
| 107 | + * @param IDBConnection $connection |
|
| 108 | + * @param ISecureRandom $secureRandom |
|
| 109 | + * @param IUserManager $userManager |
|
| 110 | + * @param IRootFolder $rootFolder |
|
| 111 | + * @param IL10N $l |
|
| 112 | + * @param ILogger $logger |
|
| 113 | + * @param IMailer $mailer |
|
| 114 | + * @param IURLGenerator $urlGenerator |
|
| 115 | + * @param IManager $activityManager |
|
| 116 | + * @param SettingsManager $settingsManager |
|
| 117 | + * @param Defaults $defaults |
|
| 118 | + * @param IHasher $hasher |
|
| 119 | + * @param CapabilitiesManager $capabilitiesManager |
|
| 120 | + */ |
|
| 121 | + public function __construct( |
|
| 122 | + IDBConnection $connection, |
|
| 123 | + ISecureRandom $secureRandom, |
|
| 124 | + IUserManager $userManager, |
|
| 125 | + IRootFolder $rootFolder, |
|
| 126 | + IL10N $l, |
|
| 127 | + ILogger $logger, |
|
| 128 | + IMailer $mailer, |
|
| 129 | + IURLGenerator $urlGenerator, |
|
| 130 | + IManager $activityManager, |
|
| 131 | + SettingsManager $settingsManager, |
|
| 132 | + Defaults $defaults, |
|
| 133 | + IHasher $hasher, |
|
| 134 | + CapabilitiesManager $capabilitiesManager |
|
| 135 | + ) { |
|
| 136 | + $this->dbConnection = $connection; |
|
| 137 | + $this->secureRandom = $secureRandom; |
|
| 138 | + $this->userManager = $userManager; |
|
| 139 | + $this->rootFolder = $rootFolder; |
|
| 140 | + $this->l = $l; |
|
| 141 | + $this->logger = $logger; |
|
| 142 | + $this->mailer = $mailer; |
|
| 143 | + $this->urlGenerator = $urlGenerator; |
|
| 144 | + $this->activityManager = $activityManager; |
|
| 145 | + $this->settingsManager = $settingsManager; |
|
| 146 | + $this->defaults = $defaults; |
|
| 147 | + $this->hasher = $hasher; |
|
| 148 | + $this->capabilitiesManager = $capabilitiesManager; |
|
| 149 | + } |
|
| 150 | + |
|
| 151 | + /** |
|
| 152 | + * Share a path |
|
| 153 | + * |
|
| 154 | + * @param IShare $share |
|
| 155 | + * @return IShare The share object |
|
| 156 | + * @throws ShareNotFound |
|
| 157 | + * @throws \Exception |
|
| 158 | + */ |
|
| 159 | + public function create(IShare $share) { |
|
| 160 | + |
|
| 161 | + $shareWith = $share->getSharedWith(); |
|
| 162 | + /* |
|
| 163 | 163 | * Check if file is not already shared with the remote user |
| 164 | 164 | */ |
| 165 | - $alreadyShared = $this->getSharedWith($shareWith, \OCP\Share::SHARE_TYPE_EMAIL, $share->getNode(), 1, 0); |
|
| 166 | - if (!empty($alreadyShared)) { |
|
| 167 | - $message = 'Sharing %s failed, this item is already shared with %s'; |
|
| 168 | - $message_t = $this->l->t('Sharing %s failed, this item is already shared with %s', array($share->getNode()->getName(), $shareWith)); |
|
| 169 | - $this->logger->debug(sprintf($message, $share->getNode()->getName(), $shareWith), ['app' => 'Federated File Sharing']); |
|
| 170 | - throw new \Exception($message_t); |
|
| 171 | - } |
|
| 172 | - |
|
| 173 | - // if the admin enforces a password for all mail shares we create a |
|
| 174 | - // random password and send it to the recipient |
|
| 175 | - $password = ''; |
|
| 176 | - $passwordEnforced = $this->settingsManager->enforcePasswordProtection(); |
|
| 177 | - if ($passwordEnforced) { |
|
| 178 | - $password = $this->autoGeneratePassword($share); |
|
| 179 | - } |
|
| 180 | - |
|
| 181 | - $shareId = $this->createMailShare($share); |
|
| 182 | - $send = $this->sendPassword($share, $password); |
|
| 183 | - if ($passwordEnforced && $send === false) { |
|
| 184 | - $this->sendPasswordToOwner($share, $password); |
|
| 185 | - } |
|
| 186 | - |
|
| 187 | - $this->createShareActivity($share); |
|
| 188 | - $data = $this->getRawShare($shareId); |
|
| 189 | - |
|
| 190 | - return $this->createShareObject($data); |
|
| 191 | - |
|
| 192 | - } |
|
| 193 | - |
|
| 194 | - /** |
|
| 195 | - * auto generate password in case of password enforcement on mail shares |
|
| 196 | - * |
|
| 197 | - * @param IShare $share |
|
| 198 | - * @return string |
|
| 199 | - * @throws \Exception |
|
| 200 | - */ |
|
| 201 | - protected function autoGeneratePassword($share) { |
|
| 202 | - $initiatorUser = $this->userManager->get($share->getSharedBy()); |
|
| 203 | - $initiatorEMailAddress = ($initiatorUser instanceof IUser) ? $initiatorUser->getEMailAddress() : null; |
|
| 204 | - $allowPasswordByMail = $this->settingsManager->sendPasswordByMail(); |
|
| 205 | - |
|
| 206 | - if ($initiatorEMailAddress === null && !$allowPasswordByMail) { |
|
| 207 | - throw new \Exception( |
|
| 208 | - $this->l->t("We can't send you the auto-generated password. Please set a valid email address in your personal settings and try again.") |
|
| 209 | - ); |
|
| 210 | - } |
|
| 211 | - |
|
| 212 | - $passwordPolicy = $this->getPasswordPolicy(); |
|
| 213 | - $passwordCharset = ISecureRandom::CHAR_LOWER . ISecureRandom::CHAR_UPPER . ISecureRandom::CHAR_DIGITS; |
|
| 214 | - $passwordLength = 8; |
|
| 215 | - if (!empty($passwordPolicy)) { |
|
| 216 | - $passwordLength = (int)$passwordPolicy['minLength'] > 0 ? (int)$passwordPolicy['minLength'] : $passwordLength; |
|
| 217 | - $passwordCharset .= $passwordPolicy['enforceSpecialCharacters'] ? ISecureRandom::CHAR_SYMBOLS : ''; |
|
| 218 | - } |
|
| 219 | - |
|
| 220 | - $password = $this->secureRandom->generate($passwordLength, $passwordCharset); |
|
| 221 | - |
|
| 222 | - $share->setPassword($this->hasher->hash($password)); |
|
| 223 | - |
|
| 224 | - return $password; |
|
| 225 | - } |
|
| 226 | - |
|
| 227 | - /** |
|
| 228 | - * get password policy |
|
| 229 | - * |
|
| 230 | - * @return array |
|
| 231 | - */ |
|
| 232 | - protected function getPasswordPolicy() { |
|
| 233 | - $capabilities = $this->capabilitiesManager->getCapabilities(); |
|
| 234 | - if (isset($capabilities['password_policy'])) { |
|
| 235 | - return $capabilities['password_policy']; |
|
| 236 | - } |
|
| 237 | - |
|
| 238 | - return []; |
|
| 239 | - } |
|
| 240 | - |
|
| 241 | - /** |
|
| 242 | - * create activity if a file/folder was shared by mail |
|
| 243 | - * |
|
| 244 | - * @param IShare $share |
|
| 245 | - */ |
|
| 246 | - protected function createShareActivity(IShare $share) { |
|
| 247 | - |
|
| 248 | - $userFolder = $this->rootFolder->getUserFolder($share->getSharedBy()); |
|
| 249 | - |
|
| 250 | - $this->publishActivity( |
|
| 251 | - Activity::SUBJECT_SHARED_EMAIL_SELF, |
|
| 252 | - [$userFolder->getRelativePath($share->getNode()->getPath()), $share->getSharedWith()], |
|
| 253 | - $share->getSharedBy(), |
|
| 254 | - $share->getNode()->getId(), |
|
| 255 | - $userFolder->getRelativePath($share->getNode()->getPath()) |
|
| 256 | - ); |
|
| 257 | - |
|
| 258 | - if ($share->getShareOwner() !== $share->getSharedBy()) { |
|
| 259 | - $ownerFolder = $this->rootFolder->getUserFolder($share->getShareOwner()); |
|
| 260 | - $fileId = $share->getNode()->getId(); |
|
| 261 | - $nodes = $ownerFolder->getById($fileId); |
|
| 262 | - $ownerPath = $nodes[0]->getPath(); |
|
| 263 | - $this->publishActivity( |
|
| 264 | - Activity::SUBJECT_SHARED_EMAIL_BY, |
|
| 265 | - [$ownerFolder->getRelativePath($ownerPath), $share->getSharedWith(), $share->getSharedBy()], |
|
| 266 | - $share->getShareOwner(), |
|
| 267 | - $fileId, |
|
| 268 | - $ownerFolder->getRelativePath($ownerPath) |
|
| 269 | - ); |
|
| 270 | - } |
|
| 271 | - |
|
| 272 | - } |
|
| 273 | - |
|
| 274 | - /** |
|
| 275 | - * create activity if a file/folder was shared by mail |
|
| 276 | - * |
|
| 277 | - * @param IShare $share |
|
| 278 | - * @param string $sharedWith |
|
| 279 | - * @param bool $sendToSelf |
|
| 280 | - */ |
|
| 281 | - protected function createPasswordSendActivity(IShare $share, $sharedWith, $sendToSelf) { |
|
| 282 | - |
|
| 283 | - $userFolder = $this->rootFolder->getUserFolder($share->getSharedBy()); |
|
| 284 | - |
|
| 285 | - if ($sendToSelf) { |
|
| 286 | - $this->publishActivity( |
|
| 287 | - Activity::SUBJECT_SHARED_EMAIL_PASSWORD_SEND_SELF, |
|
| 288 | - [$userFolder->getRelativePath($share->getNode()->getPath())], |
|
| 289 | - $share->getSharedBy(), |
|
| 290 | - $share->getNode()->getId(), |
|
| 291 | - $userFolder->getRelativePath($share->getNode()->getPath()) |
|
| 292 | - ); |
|
| 293 | - } else { |
|
| 294 | - $this->publishActivity( |
|
| 295 | - Activity::SUBJECT_SHARED_EMAIL_PASSWORD_SEND, |
|
| 296 | - [$userFolder->getRelativePath($share->getNode()->getPath()), $sharedWith], |
|
| 297 | - $share->getSharedBy(), |
|
| 298 | - $share->getNode()->getId(), |
|
| 299 | - $userFolder->getRelativePath($share->getNode()->getPath()) |
|
| 300 | - ); |
|
| 301 | - } |
|
| 302 | - } |
|
| 303 | - |
|
| 304 | - |
|
| 305 | - /** |
|
| 306 | - * publish activity if a file/folder was shared by mail |
|
| 307 | - * |
|
| 308 | - * @param $subject |
|
| 309 | - * @param $parameters |
|
| 310 | - * @param $affectedUser |
|
| 311 | - * @param $fileId |
|
| 312 | - * @param $filePath |
|
| 313 | - */ |
|
| 314 | - protected function publishActivity($subject, $parameters, $affectedUser, $fileId, $filePath) { |
|
| 315 | - $event = $this->activityManager->generateEvent(); |
|
| 316 | - $event->setApp('sharebymail') |
|
| 317 | - ->setType('shared') |
|
| 318 | - ->setSubject($subject, $parameters) |
|
| 319 | - ->setAffectedUser($affectedUser) |
|
| 320 | - ->setObject('files', $fileId, $filePath); |
|
| 321 | - $this->activityManager->publish($event); |
|
| 322 | - |
|
| 323 | - } |
|
| 324 | - |
|
| 325 | - /** |
|
| 326 | - * @param IShare $share |
|
| 327 | - * @return int |
|
| 328 | - * @throws \Exception |
|
| 329 | - */ |
|
| 330 | - protected function createMailShare(IShare $share) { |
|
| 331 | - $share->setToken($this->generateToken()); |
|
| 332 | - $shareId = $this->addShareToDB( |
|
| 333 | - $share->getNodeId(), |
|
| 334 | - $share->getNodeType(), |
|
| 335 | - $share->getSharedWith(), |
|
| 336 | - $share->getSharedBy(), |
|
| 337 | - $share->getShareOwner(), |
|
| 338 | - $share->getPermissions(), |
|
| 339 | - $share->getToken(), |
|
| 340 | - $share->getPassword() |
|
| 341 | - ); |
|
| 342 | - |
|
| 343 | - try { |
|
| 344 | - $link = $this->urlGenerator->linkToRouteAbsolute('files_sharing.sharecontroller.showShare', |
|
| 345 | - ['token' => $share->getToken()]); |
|
| 346 | - $this->sendMailNotification( |
|
| 347 | - $share->getNode()->getName(), |
|
| 348 | - $link, |
|
| 349 | - $share->getSharedBy(), |
|
| 350 | - $share->getSharedWith(), |
|
| 351 | - $share->getExpirationDate() |
|
| 352 | - ); |
|
| 353 | - } catch (HintException $hintException) { |
|
| 354 | - $this->logger->logException($hintException, [ |
|
| 355 | - 'message' => 'Failed to send share by mail.', |
|
| 356 | - 'level' => \OCP\Util::ERROR, |
|
| 357 | - 'app' => 'sharebymail', |
|
| 358 | - ]); |
|
| 359 | - $this->removeShareFromTable($shareId); |
|
| 360 | - throw $hintException; |
|
| 361 | - } catch (\Exception $e) { |
|
| 362 | - $this->logger->logException($e, [ |
|
| 363 | - 'message' => 'Failed to send share by mail.', |
|
| 364 | - 'level' => \OCP\Util::ERROR, |
|
| 365 | - 'app' => 'sharebymail', |
|
| 366 | - ]); |
|
| 367 | - $this->removeShareFromTable($shareId); |
|
| 368 | - throw new HintException('Failed to send share by mail', |
|
| 369 | - $this->l->t('Failed to send share by email')); |
|
| 370 | - } |
|
| 371 | - |
|
| 372 | - return $shareId; |
|
| 373 | - |
|
| 374 | - } |
|
| 375 | - |
|
| 376 | - /** |
|
| 377 | - * @param string $filename |
|
| 378 | - * @param string $link |
|
| 379 | - * @param string $initiator |
|
| 380 | - * @param string $shareWith |
|
| 381 | - * @param \DateTime|null $expiration |
|
| 382 | - * @throws \Exception If mail couldn't be sent |
|
| 383 | - */ |
|
| 384 | - protected function sendMailNotification($filename, |
|
| 385 | - $link, |
|
| 386 | - $initiator, |
|
| 387 | - $shareWith, |
|
| 388 | - \DateTime $expiration = null) { |
|
| 389 | - $initiatorUser = $this->userManager->get($initiator); |
|
| 390 | - $initiatorDisplayName = ($initiatorUser instanceof IUser) ? $initiatorUser->getDisplayName() : $initiator; |
|
| 391 | - $message = $this->mailer->createMessage(); |
|
| 392 | - |
|
| 393 | - $emailTemplate = $this->mailer->createEMailTemplate('sharebymail.RecipientNotification', [ |
|
| 394 | - 'filename' => $filename, |
|
| 395 | - 'link' => $link, |
|
| 396 | - 'initiator' => $initiatorDisplayName, |
|
| 397 | - 'expiration' => $expiration, |
|
| 398 | - 'shareWith' => $shareWith, |
|
| 399 | - ]); |
|
| 400 | - |
|
| 401 | - $emailTemplate->setSubject($this->l->t('%s shared »%s« with you', array($initiatorDisplayName, $filename))); |
|
| 402 | - $emailTemplate->addHeader(); |
|
| 403 | - $emailTemplate->addHeading($this->l->t('%s shared »%s« with you', [$initiatorDisplayName, $filename]), false); |
|
| 404 | - $text = $this->l->t('%s shared »%s« with you.', [$initiatorDisplayName, $filename]); |
|
| 405 | - |
|
| 406 | - $emailTemplate->addBodyText( |
|
| 407 | - $text . ' ' . $this->l->t('Click the button below to open it.'), |
|
| 408 | - $text |
|
| 409 | - ); |
|
| 410 | - $emailTemplate->addBodyButton( |
|
| 411 | - $this->l->t('Open »%s«', [$filename]), |
|
| 412 | - $link |
|
| 413 | - ); |
|
| 414 | - |
|
| 415 | - $message->setTo([$shareWith]); |
|
| 416 | - |
|
| 417 | - // The "From" contains the sharers name |
|
| 418 | - $instanceName = $this->defaults->getName(); |
|
| 419 | - $senderName = $this->l->t( |
|
| 420 | - '%s via %s', |
|
| 421 | - [ |
|
| 422 | - $initiatorDisplayName, |
|
| 423 | - $instanceName |
|
| 424 | - ] |
|
| 425 | - ); |
|
| 426 | - $message->setFrom([\OCP\Util::getDefaultEmailAddress($instanceName) => $senderName]); |
|
| 427 | - |
|
| 428 | - // The "Reply-To" is set to the sharer if an mail address is configured |
|
| 429 | - // also the default footer contains a "Do not reply" which needs to be adjusted. |
|
| 430 | - $initiatorEmail = $initiatorUser->getEMailAddress(); |
|
| 431 | - if($initiatorEmail !== null) { |
|
| 432 | - $message->setReplyTo([$initiatorEmail => $initiatorDisplayName]); |
|
| 433 | - $emailTemplate->addFooter($instanceName . ($this->defaults->getSlogan() !== '' ? ' - ' . $this->defaults->getSlogan() : '')); |
|
| 434 | - } else { |
|
| 435 | - $emailTemplate->addFooter(); |
|
| 436 | - } |
|
| 437 | - |
|
| 438 | - $message->useTemplate($emailTemplate); |
|
| 439 | - $this->mailer->send($message); |
|
| 440 | - } |
|
| 441 | - |
|
| 442 | - /** |
|
| 443 | - * send password to recipient of a mail share |
|
| 444 | - * |
|
| 445 | - * @param IShare $share |
|
| 446 | - * @param string $password |
|
| 447 | - * @return bool |
|
| 448 | - */ |
|
| 449 | - protected function sendPassword(IShare $share, $password) { |
|
| 450 | - |
|
| 451 | - $filename = $share->getNode()->getName(); |
|
| 452 | - $initiator = $share->getSharedBy(); |
|
| 453 | - $shareWith = $share->getSharedWith(); |
|
| 454 | - |
|
| 455 | - if ($password === '' || $this->settingsManager->sendPasswordByMail() === false) { |
|
| 456 | - return false; |
|
| 457 | - } |
|
| 458 | - |
|
| 459 | - $initiatorUser = $this->userManager->get($initiator); |
|
| 460 | - $initiatorDisplayName = ($initiatorUser instanceof IUser) ? $initiatorUser->getDisplayName() : $initiator; |
|
| 461 | - $initiatorEmailAddress = ($initiatorUser instanceof IUser) ? $initiatorUser->getEMailAddress() : null; |
|
| 462 | - |
|
| 463 | - $plainBodyPart = $this->l->t("%s shared »%s« with you.\nYou should have already received a separate mail with a link to access it.\n", [$initiatorDisplayName, $filename]); |
|
| 464 | - $htmlBodyPart = $this->l->t('%s shared »%s« with you. You should have already received a separate mail with a link to access it.', [$initiatorDisplayName, $filename]); |
|
| 465 | - |
|
| 466 | - $message = $this->mailer->createMessage(); |
|
| 467 | - |
|
| 468 | - $emailTemplate = $this->mailer->createEMailTemplate('sharebymail.RecipientPasswordNotification', [ |
|
| 469 | - 'filename' => $filename, |
|
| 470 | - 'password' => $password, |
|
| 471 | - 'initiator' => $initiatorDisplayName, |
|
| 472 | - 'initiatorEmail' => $initiatorEmailAddress, |
|
| 473 | - 'shareWith' => $shareWith, |
|
| 474 | - ]); |
|
| 475 | - |
|
| 476 | - $emailTemplate->setSubject($this->l->t('Password to access »%s« shared to you by %s', [$filename, $initiatorDisplayName])); |
|
| 477 | - $emailTemplate->addHeader(); |
|
| 478 | - $emailTemplate->addHeading($this->l->t('Password to access »%s«', [$filename]), false); |
|
| 479 | - $emailTemplate->addBodyText($htmlBodyPart, $plainBodyPart); |
|
| 480 | - $emailTemplate->addBodyText($this->l->t('It is protected with the following password: %s', [$password])); |
|
| 481 | - |
|
| 482 | - // The "From" contains the sharers name |
|
| 483 | - $instanceName = $this->defaults->getName(); |
|
| 484 | - $senderName = $this->l->t( |
|
| 485 | - '%s via %s', |
|
| 486 | - [ |
|
| 487 | - $initiatorDisplayName, |
|
| 488 | - $instanceName |
|
| 489 | - ] |
|
| 490 | - ); |
|
| 491 | - $message->setFrom([\OCP\Util::getDefaultEmailAddress($instanceName) => $senderName]); |
|
| 492 | - if ($initiatorEmailAddress !== null) { |
|
| 493 | - $message->setReplyTo([$initiatorEmailAddress => $initiatorDisplayName]); |
|
| 494 | - $emailTemplate->addFooter($instanceName . ' - ' . $this->defaults->getSlogan()); |
|
| 495 | - } else { |
|
| 496 | - $emailTemplate->addFooter(); |
|
| 497 | - } |
|
| 498 | - |
|
| 499 | - $message->setTo([$shareWith]); |
|
| 500 | - $message->useTemplate($emailTemplate); |
|
| 501 | - $this->mailer->send($message); |
|
| 502 | - |
|
| 503 | - $this->createPasswordSendActivity($share, $shareWith, false); |
|
| 504 | - |
|
| 505 | - return true; |
|
| 506 | - } |
|
| 507 | - |
|
| 508 | - /** |
|
| 509 | - * send auto generated password to the owner. This happens if the admin enforces |
|
| 510 | - * a password for mail shares and forbid to send the password by mail to the recipient |
|
| 511 | - * |
|
| 512 | - * @param IShare $share |
|
| 513 | - * @param string $password |
|
| 514 | - * @return bool |
|
| 515 | - * @throws \Exception |
|
| 516 | - */ |
|
| 517 | - protected function sendPasswordToOwner(IShare $share, $password) { |
|
| 518 | - |
|
| 519 | - $filename = $share->getNode()->getName(); |
|
| 520 | - $initiator = $this->userManager->get($share->getSharedBy()); |
|
| 521 | - $initiatorEMailAddress = ($initiator instanceof IUser) ? $initiator->getEMailAddress() : null; |
|
| 522 | - $initiatorDisplayName = ($initiator instanceof IUser) ? $initiator->getDisplayName() : $share->getSharedBy(); |
|
| 523 | - $shareWith = $share->getSharedWith(); |
|
| 524 | - |
|
| 525 | - if ($initiatorEMailAddress === null) { |
|
| 526 | - throw new \Exception( |
|
| 527 | - $this->l->t("We can't send you the auto-generated password. Please set a valid email address in your personal settings and try again.") |
|
| 528 | - ); |
|
| 529 | - } |
|
| 530 | - |
|
| 531 | - $bodyPart = $this->l->t("You just shared »%s« with %s. The share was already send to the recipient. Due to the security policies defined by the administrator of %s each share needs to be protected by password and it is not allowed to send the password directly to the recipient. Therefore you need to forward the password manually to the recipient.", [$filename, $shareWith, $this->defaults->getName()]); |
|
| 532 | - |
|
| 533 | - $message = $this->mailer->createMessage(); |
|
| 534 | - $emailTemplate = $this->mailer->createEMailTemplate('sharebymail.OwnerPasswordNotification', [ |
|
| 535 | - 'filename' => $filename, |
|
| 536 | - 'password' => $password, |
|
| 537 | - 'initiator' => $initiatorDisplayName, |
|
| 538 | - 'initiatorEmail' => $initiatorEMailAddress, |
|
| 539 | - 'shareWith' => $shareWith, |
|
| 540 | - ]); |
|
| 541 | - |
|
| 542 | - $emailTemplate->setSubject($this->l->t('Password to access »%s« shared with %s', [$filename, $shareWith])); |
|
| 543 | - $emailTemplate->addHeader(); |
|
| 544 | - $emailTemplate->addHeading($this->l->t('Password to access »%s«', [$filename]), false); |
|
| 545 | - $emailTemplate->addBodyText($bodyPart); |
|
| 546 | - $emailTemplate->addBodyText($this->l->t('This is the password: %s', [$password])); |
|
| 547 | - $emailTemplate->addBodyText($this->l->t('You can choose a different password at any time in the share dialog.')); |
|
| 548 | - $emailTemplate->addFooter(); |
|
| 549 | - |
|
| 550 | - if ($initiatorEMailAddress) { |
|
| 551 | - $message->setFrom([$initiatorEMailAddress => $initiatorDisplayName]); |
|
| 552 | - } |
|
| 553 | - $message->setTo([$initiatorEMailAddress => $initiatorDisplayName]); |
|
| 554 | - $message->useTemplate($emailTemplate); |
|
| 555 | - $this->mailer->send($message); |
|
| 556 | - |
|
| 557 | - $this->createPasswordSendActivity($share, $shareWith, true); |
|
| 558 | - |
|
| 559 | - return true; |
|
| 560 | - } |
|
| 561 | - |
|
| 562 | - /** |
|
| 563 | - * generate share token |
|
| 564 | - * |
|
| 565 | - * @return string |
|
| 566 | - */ |
|
| 567 | - protected function generateToken($size = 15) { |
|
| 568 | - $token = $this->secureRandom->generate($size, ISecureRandom::CHAR_HUMAN_READABLE); |
|
| 569 | - return $token; |
|
| 570 | - } |
|
| 571 | - |
|
| 572 | - /** |
|
| 573 | - * Get all children of this share |
|
| 574 | - * |
|
| 575 | - * @param IShare $parent |
|
| 576 | - * @return IShare[] |
|
| 577 | - */ |
|
| 578 | - public function getChildren(IShare $parent) { |
|
| 579 | - $children = []; |
|
| 580 | - |
|
| 581 | - $qb = $this->dbConnection->getQueryBuilder(); |
|
| 582 | - $qb->select('*') |
|
| 583 | - ->from('share') |
|
| 584 | - ->where($qb->expr()->eq('parent', $qb->createNamedParameter($parent->getId()))) |
|
| 585 | - ->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_EMAIL))) |
|
| 586 | - ->orderBy('id'); |
|
| 587 | - |
|
| 588 | - $cursor = $qb->execute(); |
|
| 589 | - while($data = $cursor->fetch()) { |
|
| 590 | - $children[] = $this->createShareObject($data); |
|
| 591 | - } |
|
| 592 | - $cursor->closeCursor(); |
|
| 593 | - |
|
| 594 | - return $children; |
|
| 595 | - } |
|
| 596 | - |
|
| 597 | - /** |
|
| 598 | - * add share to the database and return the ID |
|
| 599 | - * |
|
| 600 | - * @param int $itemSource |
|
| 601 | - * @param string $itemType |
|
| 602 | - * @param string $shareWith |
|
| 603 | - * @param string $sharedBy |
|
| 604 | - * @param string $uidOwner |
|
| 605 | - * @param int $permissions |
|
| 606 | - * @param string $token |
|
| 607 | - * @return int |
|
| 608 | - */ |
|
| 609 | - protected function addShareToDB($itemSource, $itemType, $shareWith, $sharedBy, $uidOwner, $permissions, $token, $password) { |
|
| 610 | - $qb = $this->dbConnection->getQueryBuilder(); |
|
| 611 | - $qb->insert('share') |
|
| 612 | - ->setValue('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_EMAIL)) |
|
| 613 | - ->setValue('item_type', $qb->createNamedParameter($itemType)) |
|
| 614 | - ->setValue('item_source', $qb->createNamedParameter($itemSource)) |
|
| 615 | - ->setValue('file_source', $qb->createNamedParameter($itemSource)) |
|
| 616 | - ->setValue('share_with', $qb->createNamedParameter($shareWith)) |
|
| 617 | - ->setValue('uid_owner', $qb->createNamedParameter($uidOwner)) |
|
| 618 | - ->setValue('uid_initiator', $qb->createNamedParameter($sharedBy)) |
|
| 619 | - ->setValue('permissions', $qb->createNamedParameter($permissions)) |
|
| 620 | - ->setValue('token', $qb->createNamedParameter($token)) |
|
| 621 | - ->setValue('password', $qb->createNamedParameter($password)) |
|
| 622 | - ->setValue('stime', $qb->createNamedParameter(time())); |
|
| 623 | - |
|
| 624 | - /* |
|
| 165 | + $alreadyShared = $this->getSharedWith($shareWith, \OCP\Share::SHARE_TYPE_EMAIL, $share->getNode(), 1, 0); |
|
| 166 | + if (!empty($alreadyShared)) { |
|
| 167 | + $message = 'Sharing %s failed, this item is already shared with %s'; |
|
| 168 | + $message_t = $this->l->t('Sharing %s failed, this item is already shared with %s', array($share->getNode()->getName(), $shareWith)); |
|
| 169 | + $this->logger->debug(sprintf($message, $share->getNode()->getName(), $shareWith), ['app' => 'Federated File Sharing']); |
|
| 170 | + throw new \Exception($message_t); |
|
| 171 | + } |
|
| 172 | + |
|
| 173 | + // if the admin enforces a password for all mail shares we create a |
|
| 174 | + // random password and send it to the recipient |
|
| 175 | + $password = ''; |
|
| 176 | + $passwordEnforced = $this->settingsManager->enforcePasswordProtection(); |
|
| 177 | + if ($passwordEnforced) { |
|
| 178 | + $password = $this->autoGeneratePassword($share); |
|
| 179 | + } |
|
| 180 | + |
|
| 181 | + $shareId = $this->createMailShare($share); |
|
| 182 | + $send = $this->sendPassword($share, $password); |
|
| 183 | + if ($passwordEnforced && $send === false) { |
|
| 184 | + $this->sendPasswordToOwner($share, $password); |
|
| 185 | + } |
|
| 186 | + |
|
| 187 | + $this->createShareActivity($share); |
|
| 188 | + $data = $this->getRawShare($shareId); |
|
| 189 | + |
|
| 190 | + return $this->createShareObject($data); |
|
| 191 | + |
|
| 192 | + } |
|
| 193 | + |
|
| 194 | + /** |
|
| 195 | + * auto generate password in case of password enforcement on mail shares |
|
| 196 | + * |
|
| 197 | + * @param IShare $share |
|
| 198 | + * @return string |
|
| 199 | + * @throws \Exception |
|
| 200 | + */ |
|
| 201 | + protected function autoGeneratePassword($share) { |
|
| 202 | + $initiatorUser = $this->userManager->get($share->getSharedBy()); |
|
| 203 | + $initiatorEMailAddress = ($initiatorUser instanceof IUser) ? $initiatorUser->getEMailAddress() : null; |
|
| 204 | + $allowPasswordByMail = $this->settingsManager->sendPasswordByMail(); |
|
| 205 | + |
|
| 206 | + if ($initiatorEMailAddress === null && !$allowPasswordByMail) { |
|
| 207 | + throw new \Exception( |
|
| 208 | + $this->l->t("We can't send you the auto-generated password. Please set a valid email address in your personal settings and try again.") |
|
| 209 | + ); |
|
| 210 | + } |
|
| 211 | + |
|
| 212 | + $passwordPolicy = $this->getPasswordPolicy(); |
|
| 213 | + $passwordCharset = ISecureRandom::CHAR_LOWER . ISecureRandom::CHAR_UPPER . ISecureRandom::CHAR_DIGITS; |
|
| 214 | + $passwordLength = 8; |
|
| 215 | + if (!empty($passwordPolicy)) { |
|
| 216 | + $passwordLength = (int)$passwordPolicy['minLength'] > 0 ? (int)$passwordPolicy['minLength'] : $passwordLength; |
|
| 217 | + $passwordCharset .= $passwordPolicy['enforceSpecialCharacters'] ? ISecureRandom::CHAR_SYMBOLS : ''; |
|
| 218 | + } |
|
| 219 | + |
|
| 220 | + $password = $this->secureRandom->generate($passwordLength, $passwordCharset); |
|
| 221 | + |
|
| 222 | + $share->setPassword($this->hasher->hash($password)); |
|
| 223 | + |
|
| 224 | + return $password; |
|
| 225 | + } |
|
| 226 | + |
|
| 227 | + /** |
|
| 228 | + * get password policy |
|
| 229 | + * |
|
| 230 | + * @return array |
|
| 231 | + */ |
|
| 232 | + protected function getPasswordPolicy() { |
|
| 233 | + $capabilities = $this->capabilitiesManager->getCapabilities(); |
|
| 234 | + if (isset($capabilities['password_policy'])) { |
|
| 235 | + return $capabilities['password_policy']; |
|
| 236 | + } |
|
| 237 | + |
|
| 238 | + return []; |
|
| 239 | + } |
|
| 240 | + |
|
| 241 | + /** |
|
| 242 | + * create activity if a file/folder was shared by mail |
|
| 243 | + * |
|
| 244 | + * @param IShare $share |
|
| 245 | + */ |
|
| 246 | + protected function createShareActivity(IShare $share) { |
|
| 247 | + |
|
| 248 | + $userFolder = $this->rootFolder->getUserFolder($share->getSharedBy()); |
|
| 249 | + |
|
| 250 | + $this->publishActivity( |
|
| 251 | + Activity::SUBJECT_SHARED_EMAIL_SELF, |
|
| 252 | + [$userFolder->getRelativePath($share->getNode()->getPath()), $share->getSharedWith()], |
|
| 253 | + $share->getSharedBy(), |
|
| 254 | + $share->getNode()->getId(), |
|
| 255 | + $userFolder->getRelativePath($share->getNode()->getPath()) |
|
| 256 | + ); |
|
| 257 | + |
|
| 258 | + if ($share->getShareOwner() !== $share->getSharedBy()) { |
|
| 259 | + $ownerFolder = $this->rootFolder->getUserFolder($share->getShareOwner()); |
|
| 260 | + $fileId = $share->getNode()->getId(); |
|
| 261 | + $nodes = $ownerFolder->getById($fileId); |
|
| 262 | + $ownerPath = $nodes[0]->getPath(); |
|
| 263 | + $this->publishActivity( |
|
| 264 | + Activity::SUBJECT_SHARED_EMAIL_BY, |
|
| 265 | + [$ownerFolder->getRelativePath($ownerPath), $share->getSharedWith(), $share->getSharedBy()], |
|
| 266 | + $share->getShareOwner(), |
|
| 267 | + $fileId, |
|
| 268 | + $ownerFolder->getRelativePath($ownerPath) |
|
| 269 | + ); |
|
| 270 | + } |
|
| 271 | + |
|
| 272 | + } |
|
| 273 | + |
|
| 274 | + /** |
|
| 275 | + * create activity if a file/folder was shared by mail |
|
| 276 | + * |
|
| 277 | + * @param IShare $share |
|
| 278 | + * @param string $sharedWith |
|
| 279 | + * @param bool $sendToSelf |
|
| 280 | + */ |
|
| 281 | + protected function createPasswordSendActivity(IShare $share, $sharedWith, $sendToSelf) { |
|
| 282 | + |
|
| 283 | + $userFolder = $this->rootFolder->getUserFolder($share->getSharedBy()); |
|
| 284 | + |
|
| 285 | + if ($sendToSelf) { |
|
| 286 | + $this->publishActivity( |
|
| 287 | + Activity::SUBJECT_SHARED_EMAIL_PASSWORD_SEND_SELF, |
|
| 288 | + [$userFolder->getRelativePath($share->getNode()->getPath())], |
|
| 289 | + $share->getSharedBy(), |
|
| 290 | + $share->getNode()->getId(), |
|
| 291 | + $userFolder->getRelativePath($share->getNode()->getPath()) |
|
| 292 | + ); |
|
| 293 | + } else { |
|
| 294 | + $this->publishActivity( |
|
| 295 | + Activity::SUBJECT_SHARED_EMAIL_PASSWORD_SEND, |
|
| 296 | + [$userFolder->getRelativePath($share->getNode()->getPath()), $sharedWith], |
|
| 297 | + $share->getSharedBy(), |
|
| 298 | + $share->getNode()->getId(), |
|
| 299 | + $userFolder->getRelativePath($share->getNode()->getPath()) |
|
| 300 | + ); |
|
| 301 | + } |
|
| 302 | + } |
|
| 303 | + |
|
| 304 | + |
|
| 305 | + /** |
|
| 306 | + * publish activity if a file/folder was shared by mail |
|
| 307 | + * |
|
| 308 | + * @param $subject |
|
| 309 | + * @param $parameters |
|
| 310 | + * @param $affectedUser |
|
| 311 | + * @param $fileId |
|
| 312 | + * @param $filePath |
|
| 313 | + */ |
|
| 314 | + protected function publishActivity($subject, $parameters, $affectedUser, $fileId, $filePath) { |
|
| 315 | + $event = $this->activityManager->generateEvent(); |
|
| 316 | + $event->setApp('sharebymail') |
|
| 317 | + ->setType('shared') |
|
| 318 | + ->setSubject($subject, $parameters) |
|
| 319 | + ->setAffectedUser($affectedUser) |
|
| 320 | + ->setObject('files', $fileId, $filePath); |
|
| 321 | + $this->activityManager->publish($event); |
|
| 322 | + |
|
| 323 | + } |
|
| 324 | + |
|
| 325 | + /** |
|
| 326 | + * @param IShare $share |
|
| 327 | + * @return int |
|
| 328 | + * @throws \Exception |
|
| 329 | + */ |
|
| 330 | + protected function createMailShare(IShare $share) { |
|
| 331 | + $share->setToken($this->generateToken()); |
|
| 332 | + $shareId = $this->addShareToDB( |
|
| 333 | + $share->getNodeId(), |
|
| 334 | + $share->getNodeType(), |
|
| 335 | + $share->getSharedWith(), |
|
| 336 | + $share->getSharedBy(), |
|
| 337 | + $share->getShareOwner(), |
|
| 338 | + $share->getPermissions(), |
|
| 339 | + $share->getToken(), |
|
| 340 | + $share->getPassword() |
|
| 341 | + ); |
|
| 342 | + |
|
| 343 | + try { |
|
| 344 | + $link = $this->urlGenerator->linkToRouteAbsolute('files_sharing.sharecontroller.showShare', |
|
| 345 | + ['token' => $share->getToken()]); |
|
| 346 | + $this->sendMailNotification( |
|
| 347 | + $share->getNode()->getName(), |
|
| 348 | + $link, |
|
| 349 | + $share->getSharedBy(), |
|
| 350 | + $share->getSharedWith(), |
|
| 351 | + $share->getExpirationDate() |
|
| 352 | + ); |
|
| 353 | + } catch (HintException $hintException) { |
|
| 354 | + $this->logger->logException($hintException, [ |
|
| 355 | + 'message' => 'Failed to send share by mail.', |
|
| 356 | + 'level' => \OCP\Util::ERROR, |
|
| 357 | + 'app' => 'sharebymail', |
|
| 358 | + ]); |
|
| 359 | + $this->removeShareFromTable($shareId); |
|
| 360 | + throw $hintException; |
|
| 361 | + } catch (\Exception $e) { |
|
| 362 | + $this->logger->logException($e, [ |
|
| 363 | + 'message' => 'Failed to send share by mail.', |
|
| 364 | + 'level' => \OCP\Util::ERROR, |
|
| 365 | + 'app' => 'sharebymail', |
|
| 366 | + ]); |
|
| 367 | + $this->removeShareFromTable($shareId); |
|
| 368 | + throw new HintException('Failed to send share by mail', |
|
| 369 | + $this->l->t('Failed to send share by email')); |
|
| 370 | + } |
|
| 371 | + |
|
| 372 | + return $shareId; |
|
| 373 | + |
|
| 374 | + } |
|
| 375 | + |
|
| 376 | + /** |
|
| 377 | + * @param string $filename |
|
| 378 | + * @param string $link |
|
| 379 | + * @param string $initiator |
|
| 380 | + * @param string $shareWith |
|
| 381 | + * @param \DateTime|null $expiration |
|
| 382 | + * @throws \Exception If mail couldn't be sent |
|
| 383 | + */ |
|
| 384 | + protected function sendMailNotification($filename, |
|
| 385 | + $link, |
|
| 386 | + $initiator, |
|
| 387 | + $shareWith, |
|
| 388 | + \DateTime $expiration = null) { |
|
| 389 | + $initiatorUser = $this->userManager->get($initiator); |
|
| 390 | + $initiatorDisplayName = ($initiatorUser instanceof IUser) ? $initiatorUser->getDisplayName() : $initiator; |
|
| 391 | + $message = $this->mailer->createMessage(); |
|
| 392 | + |
|
| 393 | + $emailTemplate = $this->mailer->createEMailTemplate('sharebymail.RecipientNotification', [ |
|
| 394 | + 'filename' => $filename, |
|
| 395 | + 'link' => $link, |
|
| 396 | + 'initiator' => $initiatorDisplayName, |
|
| 397 | + 'expiration' => $expiration, |
|
| 398 | + 'shareWith' => $shareWith, |
|
| 399 | + ]); |
|
| 400 | + |
|
| 401 | + $emailTemplate->setSubject($this->l->t('%s shared »%s« with you', array($initiatorDisplayName, $filename))); |
|
| 402 | + $emailTemplate->addHeader(); |
|
| 403 | + $emailTemplate->addHeading($this->l->t('%s shared »%s« with you', [$initiatorDisplayName, $filename]), false); |
|
| 404 | + $text = $this->l->t('%s shared »%s« with you.', [$initiatorDisplayName, $filename]); |
|
| 405 | + |
|
| 406 | + $emailTemplate->addBodyText( |
|
| 407 | + $text . ' ' . $this->l->t('Click the button below to open it.'), |
|
| 408 | + $text |
|
| 409 | + ); |
|
| 410 | + $emailTemplate->addBodyButton( |
|
| 411 | + $this->l->t('Open »%s«', [$filename]), |
|
| 412 | + $link |
|
| 413 | + ); |
|
| 414 | + |
|
| 415 | + $message->setTo([$shareWith]); |
|
| 416 | + |
|
| 417 | + // The "From" contains the sharers name |
|
| 418 | + $instanceName = $this->defaults->getName(); |
|
| 419 | + $senderName = $this->l->t( |
|
| 420 | + '%s via %s', |
|
| 421 | + [ |
|
| 422 | + $initiatorDisplayName, |
|
| 423 | + $instanceName |
|
| 424 | + ] |
|
| 425 | + ); |
|
| 426 | + $message->setFrom([\OCP\Util::getDefaultEmailAddress($instanceName) => $senderName]); |
|
| 427 | + |
|
| 428 | + // The "Reply-To" is set to the sharer if an mail address is configured |
|
| 429 | + // also the default footer contains a "Do not reply" which needs to be adjusted. |
|
| 430 | + $initiatorEmail = $initiatorUser->getEMailAddress(); |
|
| 431 | + if($initiatorEmail !== null) { |
|
| 432 | + $message->setReplyTo([$initiatorEmail => $initiatorDisplayName]); |
|
| 433 | + $emailTemplate->addFooter($instanceName . ($this->defaults->getSlogan() !== '' ? ' - ' . $this->defaults->getSlogan() : '')); |
|
| 434 | + } else { |
|
| 435 | + $emailTemplate->addFooter(); |
|
| 436 | + } |
|
| 437 | + |
|
| 438 | + $message->useTemplate($emailTemplate); |
|
| 439 | + $this->mailer->send($message); |
|
| 440 | + } |
|
| 441 | + |
|
| 442 | + /** |
|
| 443 | + * send password to recipient of a mail share |
|
| 444 | + * |
|
| 445 | + * @param IShare $share |
|
| 446 | + * @param string $password |
|
| 447 | + * @return bool |
|
| 448 | + */ |
|
| 449 | + protected function sendPassword(IShare $share, $password) { |
|
| 450 | + |
|
| 451 | + $filename = $share->getNode()->getName(); |
|
| 452 | + $initiator = $share->getSharedBy(); |
|
| 453 | + $shareWith = $share->getSharedWith(); |
|
| 454 | + |
|
| 455 | + if ($password === '' || $this->settingsManager->sendPasswordByMail() === false) { |
|
| 456 | + return false; |
|
| 457 | + } |
|
| 458 | + |
|
| 459 | + $initiatorUser = $this->userManager->get($initiator); |
|
| 460 | + $initiatorDisplayName = ($initiatorUser instanceof IUser) ? $initiatorUser->getDisplayName() : $initiator; |
|
| 461 | + $initiatorEmailAddress = ($initiatorUser instanceof IUser) ? $initiatorUser->getEMailAddress() : null; |
|
| 462 | + |
|
| 463 | + $plainBodyPart = $this->l->t("%s shared »%s« with you.\nYou should have already received a separate mail with a link to access it.\n", [$initiatorDisplayName, $filename]); |
|
| 464 | + $htmlBodyPart = $this->l->t('%s shared »%s« with you. You should have already received a separate mail with a link to access it.', [$initiatorDisplayName, $filename]); |
|
| 465 | + |
|
| 466 | + $message = $this->mailer->createMessage(); |
|
| 467 | + |
|
| 468 | + $emailTemplate = $this->mailer->createEMailTemplate('sharebymail.RecipientPasswordNotification', [ |
|
| 469 | + 'filename' => $filename, |
|
| 470 | + 'password' => $password, |
|
| 471 | + 'initiator' => $initiatorDisplayName, |
|
| 472 | + 'initiatorEmail' => $initiatorEmailAddress, |
|
| 473 | + 'shareWith' => $shareWith, |
|
| 474 | + ]); |
|
| 475 | + |
|
| 476 | + $emailTemplate->setSubject($this->l->t('Password to access »%s« shared to you by %s', [$filename, $initiatorDisplayName])); |
|
| 477 | + $emailTemplate->addHeader(); |
|
| 478 | + $emailTemplate->addHeading($this->l->t('Password to access »%s«', [$filename]), false); |
|
| 479 | + $emailTemplate->addBodyText($htmlBodyPart, $plainBodyPart); |
|
| 480 | + $emailTemplate->addBodyText($this->l->t('It is protected with the following password: %s', [$password])); |
|
| 481 | + |
|
| 482 | + // The "From" contains the sharers name |
|
| 483 | + $instanceName = $this->defaults->getName(); |
|
| 484 | + $senderName = $this->l->t( |
|
| 485 | + '%s via %s', |
|
| 486 | + [ |
|
| 487 | + $initiatorDisplayName, |
|
| 488 | + $instanceName |
|
| 489 | + ] |
|
| 490 | + ); |
|
| 491 | + $message->setFrom([\OCP\Util::getDefaultEmailAddress($instanceName) => $senderName]); |
|
| 492 | + if ($initiatorEmailAddress !== null) { |
|
| 493 | + $message->setReplyTo([$initiatorEmailAddress => $initiatorDisplayName]); |
|
| 494 | + $emailTemplate->addFooter($instanceName . ' - ' . $this->defaults->getSlogan()); |
|
| 495 | + } else { |
|
| 496 | + $emailTemplate->addFooter(); |
|
| 497 | + } |
|
| 498 | + |
|
| 499 | + $message->setTo([$shareWith]); |
|
| 500 | + $message->useTemplate($emailTemplate); |
|
| 501 | + $this->mailer->send($message); |
|
| 502 | + |
|
| 503 | + $this->createPasswordSendActivity($share, $shareWith, false); |
|
| 504 | + |
|
| 505 | + return true; |
|
| 506 | + } |
|
| 507 | + |
|
| 508 | + /** |
|
| 509 | + * send auto generated password to the owner. This happens if the admin enforces |
|
| 510 | + * a password for mail shares and forbid to send the password by mail to the recipient |
|
| 511 | + * |
|
| 512 | + * @param IShare $share |
|
| 513 | + * @param string $password |
|
| 514 | + * @return bool |
|
| 515 | + * @throws \Exception |
|
| 516 | + */ |
|
| 517 | + protected function sendPasswordToOwner(IShare $share, $password) { |
|
| 518 | + |
|
| 519 | + $filename = $share->getNode()->getName(); |
|
| 520 | + $initiator = $this->userManager->get($share->getSharedBy()); |
|
| 521 | + $initiatorEMailAddress = ($initiator instanceof IUser) ? $initiator->getEMailAddress() : null; |
|
| 522 | + $initiatorDisplayName = ($initiator instanceof IUser) ? $initiator->getDisplayName() : $share->getSharedBy(); |
|
| 523 | + $shareWith = $share->getSharedWith(); |
|
| 524 | + |
|
| 525 | + if ($initiatorEMailAddress === null) { |
|
| 526 | + throw new \Exception( |
|
| 527 | + $this->l->t("We can't send you the auto-generated password. Please set a valid email address in your personal settings and try again.") |
|
| 528 | + ); |
|
| 529 | + } |
|
| 530 | + |
|
| 531 | + $bodyPart = $this->l->t("You just shared »%s« with %s. The share was already send to the recipient. Due to the security policies defined by the administrator of %s each share needs to be protected by password and it is not allowed to send the password directly to the recipient. Therefore you need to forward the password manually to the recipient.", [$filename, $shareWith, $this->defaults->getName()]); |
|
| 532 | + |
|
| 533 | + $message = $this->mailer->createMessage(); |
|
| 534 | + $emailTemplate = $this->mailer->createEMailTemplate('sharebymail.OwnerPasswordNotification', [ |
|
| 535 | + 'filename' => $filename, |
|
| 536 | + 'password' => $password, |
|
| 537 | + 'initiator' => $initiatorDisplayName, |
|
| 538 | + 'initiatorEmail' => $initiatorEMailAddress, |
|
| 539 | + 'shareWith' => $shareWith, |
|
| 540 | + ]); |
|
| 541 | + |
|
| 542 | + $emailTemplate->setSubject($this->l->t('Password to access »%s« shared with %s', [$filename, $shareWith])); |
|
| 543 | + $emailTemplate->addHeader(); |
|
| 544 | + $emailTemplate->addHeading($this->l->t('Password to access »%s«', [$filename]), false); |
|
| 545 | + $emailTemplate->addBodyText($bodyPart); |
|
| 546 | + $emailTemplate->addBodyText($this->l->t('This is the password: %s', [$password])); |
|
| 547 | + $emailTemplate->addBodyText($this->l->t('You can choose a different password at any time in the share dialog.')); |
|
| 548 | + $emailTemplate->addFooter(); |
|
| 549 | + |
|
| 550 | + if ($initiatorEMailAddress) { |
|
| 551 | + $message->setFrom([$initiatorEMailAddress => $initiatorDisplayName]); |
|
| 552 | + } |
|
| 553 | + $message->setTo([$initiatorEMailAddress => $initiatorDisplayName]); |
|
| 554 | + $message->useTemplate($emailTemplate); |
|
| 555 | + $this->mailer->send($message); |
|
| 556 | + |
|
| 557 | + $this->createPasswordSendActivity($share, $shareWith, true); |
|
| 558 | + |
|
| 559 | + return true; |
|
| 560 | + } |
|
| 561 | + |
|
| 562 | + /** |
|
| 563 | + * generate share token |
|
| 564 | + * |
|
| 565 | + * @return string |
|
| 566 | + */ |
|
| 567 | + protected function generateToken($size = 15) { |
|
| 568 | + $token = $this->secureRandom->generate($size, ISecureRandom::CHAR_HUMAN_READABLE); |
|
| 569 | + return $token; |
|
| 570 | + } |
|
| 571 | + |
|
| 572 | + /** |
|
| 573 | + * Get all children of this share |
|
| 574 | + * |
|
| 575 | + * @param IShare $parent |
|
| 576 | + * @return IShare[] |
|
| 577 | + */ |
|
| 578 | + public function getChildren(IShare $parent) { |
|
| 579 | + $children = []; |
|
| 580 | + |
|
| 581 | + $qb = $this->dbConnection->getQueryBuilder(); |
|
| 582 | + $qb->select('*') |
|
| 583 | + ->from('share') |
|
| 584 | + ->where($qb->expr()->eq('parent', $qb->createNamedParameter($parent->getId()))) |
|
| 585 | + ->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_EMAIL))) |
|
| 586 | + ->orderBy('id'); |
|
| 587 | + |
|
| 588 | + $cursor = $qb->execute(); |
|
| 589 | + while($data = $cursor->fetch()) { |
|
| 590 | + $children[] = $this->createShareObject($data); |
|
| 591 | + } |
|
| 592 | + $cursor->closeCursor(); |
|
| 593 | + |
|
| 594 | + return $children; |
|
| 595 | + } |
|
| 596 | + |
|
| 597 | + /** |
|
| 598 | + * add share to the database and return the ID |
|
| 599 | + * |
|
| 600 | + * @param int $itemSource |
|
| 601 | + * @param string $itemType |
|
| 602 | + * @param string $shareWith |
|
| 603 | + * @param string $sharedBy |
|
| 604 | + * @param string $uidOwner |
|
| 605 | + * @param int $permissions |
|
| 606 | + * @param string $token |
|
| 607 | + * @return int |
|
| 608 | + */ |
|
| 609 | + protected function addShareToDB($itemSource, $itemType, $shareWith, $sharedBy, $uidOwner, $permissions, $token, $password) { |
|
| 610 | + $qb = $this->dbConnection->getQueryBuilder(); |
|
| 611 | + $qb->insert('share') |
|
| 612 | + ->setValue('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_EMAIL)) |
|
| 613 | + ->setValue('item_type', $qb->createNamedParameter($itemType)) |
|
| 614 | + ->setValue('item_source', $qb->createNamedParameter($itemSource)) |
|
| 615 | + ->setValue('file_source', $qb->createNamedParameter($itemSource)) |
|
| 616 | + ->setValue('share_with', $qb->createNamedParameter($shareWith)) |
|
| 617 | + ->setValue('uid_owner', $qb->createNamedParameter($uidOwner)) |
|
| 618 | + ->setValue('uid_initiator', $qb->createNamedParameter($sharedBy)) |
|
| 619 | + ->setValue('permissions', $qb->createNamedParameter($permissions)) |
|
| 620 | + ->setValue('token', $qb->createNamedParameter($token)) |
|
| 621 | + ->setValue('password', $qb->createNamedParameter($password)) |
|
| 622 | + ->setValue('stime', $qb->createNamedParameter(time())); |
|
| 623 | + |
|
| 624 | + /* |
|
| 625 | 625 | * Added to fix https://github.com/owncloud/core/issues/22215 |
| 626 | 626 | * Can be removed once we get rid of ajax/share.php |
| 627 | 627 | */ |
| 628 | - $qb->setValue('file_target', $qb->createNamedParameter('')); |
|
| 628 | + $qb->setValue('file_target', $qb->createNamedParameter('')); |
|
| 629 | 629 | |
| 630 | - $qb->execute(); |
|
| 631 | - $id = $qb->getLastInsertId(); |
|
| 630 | + $qb->execute(); |
|
| 631 | + $id = $qb->getLastInsertId(); |
|
| 632 | 632 | |
| 633 | - return (int)$id; |
|
| 634 | - } |
|
| 633 | + return (int)$id; |
|
| 634 | + } |
|
| 635 | 635 | |
| 636 | - /** |
|
| 637 | - * Update a share |
|
| 638 | - * |
|
| 639 | - * @param IShare $share |
|
| 640 | - * @param string|null $plainTextPassword |
|
| 641 | - * @return IShare The share object |
|
| 642 | - */ |
|
| 643 | - public function update(IShare $share, $plainTextPassword = null) { |
|
| 636 | + /** |
|
| 637 | + * Update a share |
|
| 638 | + * |
|
| 639 | + * @param IShare $share |
|
| 640 | + * @param string|null $plainTextPassword |
|
| 641 | + * @return IShare The share object |
|
| 642 | + */ |
|
| 643 | + public function update(IShare $share, $plainTextPassword = null) { |
|
| 644 | 644 | |
| 645 | - $originalShare = $this->getShareById($share->getId()); |
|
| 645 | + $originalShare = $this->getShareById($share->getId()); |
|
| 646 | 646 | |
| 647 | - // a real password was given |
|
| 648 | - $validPassword = $plainTextPassword !== null && $plainTextPassword !== ''; |
|
| 647 | + // a real password was given |
|
| 648 | + $validPassword = $plainTextPassword !== null && $plainTextPassword !== ''; |
|
| 649 | 649 | |
| 650 | - if($validPassword && $originalShare->getPassword() !== $share->getPassword()) { |
|
| 651 | - $this->sendPassword($share, $plainTextPassword); |
|
| 652 | - } |
|
| 653 | - /* |
|
| 650 | + if($validPassword && $originalShare->getPassword() !== $share->getPassword()) { |
|
| 651 | + $this->sendPassword($share, $plainTextPassword); |
|
| 652 | + } |
|
| 653 | + /* |
|
| 654 | 654 | * We allow updating the permissions and password of mail shares |
| 655 | 655 | */ |
| 656 | - $qb = $this->dbConnection->getQueryBuilder(); |
|
| 657 | - $qb->update('share') |
|
| 658 | - ->where($qb->expr()->eq('id', $qb->createNamedParameter($share->getId()))) |
|
| 659 | - ->set('permissions', $qb->createNamedParameter($share->getPermissions())) |
|
| 660 | - ->set('uid_owner', $qb->createNamedParameter($share->getShareOwner())) |
|
| 661 | - ->set('uid_initiator', $qb->createNamedParameter($share->getSharedBy())) |
|
| 662 | - ->set('password', $qb->createNamedParameter($share->getPassword())) |
|
| 663 | - ->set('expiration', $qb->createNamedParameter($share->getExpirationDate(), IQueryBuilder::PARAM_DATE)) |
|
| 664 | - ->execute(); |
|
| 665 | - |
|
| 666 | - return $share; |
|
| 667 | - } |
|
| 668 | - |
|
| 669 | - /** |
|
| 670 | - * @inheritdoc |
|
| 671 | - */ |
|
| 672 | - public function move(IShare $share, $recipient) { |
|
| 673 | - /** |
|
| 674 | - * nothing to do here, mail shares are only outgoing shares |
|
| 675 | - */ |
|
| 676 | - return $share; |
|
| 677 | - } |
|
| 678 | - |
|
| 679 | - /** |
|
| 680 | - * Delete a share (owner unShares the file) |
|
| 681 | - * |
|
| 682 | - * @param IShare $share |
|
| 683 | - */ |
|
| 684 | - public function delete(IShare $share) { |
|
| 685 | - $this->removeShareFromTable($share->getId()); |
|
| 686 | - } |
|
| 687 | - |
|
| 688 | - /** |
|
| 689 | - * @inheritdoc |
|
| 690 | - */ |
|
| 691 | - public function deleteFromSelf(IShare $share, $recipient) { |
|
| 692 | - // nothing to do here, mail shares are only outgoing shares |
|
| 693 | - } |
|
| 694 | - |
|
| 695 | - /** |
|
| 696 | - * @inheritdoc |
|
| 697 | - */ |
|
| 698 | - public function getSharesBy($userId, $shareType, $node, $reshares, $limit, $offset) { |
|
| 699 | - $qb = $this->dbConnection->getQueryBuilder(); |
|
| 700 | - $qb->select('*') |
|
| 701 | - ->from('share'); |
|
| 702 | - |
|
| 703 | - $qb->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_EMAIL))); |
|
| 704 | - |
|
| 705 | - /** |
|
| 706 | - * Reshares for this user are shares where they are the owner. |
|
| 707 | - */ |
|
| 708 | - if ($reshares === false) { |
|
| 709 | - //Special case for old shares created via the web UI |
|
| 710 | - $or1 = $qb->expr()->andX( |
|
| 711 | - $qb->expr()->eq('uid_owner', $qb->createNamedParameter($userId)), |
|
| 712 | - $qb->expr()->isNull('uid_initiator') |
|
| 713 | - ); |
|
| 714 | - |
|
| 715 | - $qb->andWhere( |
|
| 716 | - $qb->expr()->orX( |
|
| 717 | - $qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId)), |
|
| 718 | - $or1 |
|
| 719 | - ) |
|
| 720 | - ); |
|
| 721 | - } else { |
|
| 722 | - $qb->andWhere( |
|
| 723 | - $qb->expr()->orX( |
|
| 724 | - $qb->expr()->eq('uid_owner', $qb->createNamedParameter($userId)), |
|
| 725 | - $qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId)) |
|
| 726 | - ) |
|
| 727 | - ); |
|
| 728 | - } |
|
| 729 | - |
|
| 730 | - if ($node !== null) { |
|
| 731 | - $qb->andWhere($qb->expr()->eq('file_source', $qb->createNamedParameter($node->getId()))); |
|
| 732 | - } |
|
| 733 | - |
|
| 734 | - if ($limit !== -1) { |
|
| 735 | - $qb->setMaxResults($limit); |
|
| 736 | - } |
|
| 737 | - |
|
| 738 | - $qb->setFirstResult($offset); |
|
| 739 | - $qb->orderBy('id'); |
|
| 740 | - |
|
| 741 | - $cursor = $qb->execute(); |
|
| 742 | - $shares = []; |
|
| 743 | - while($data = $cursor->fetch()) { |
|
| 744 | - $shares[] = $this->createShareObject($data); |
|
| 745 | - } |
|
| 746 | - $cursor->closeCursor(); |
|
| 747 | - |
|
| 748 | - return $shares; |
|
| 749 | - } |
|
| 750 | - |
|
| 751 | - /** |
|
| 752 | - * @inheritdoc |
|
| 753 | - */ |
|
| 754 | - public function getShareById($id, $recipientId = null) { |
|
| 755 | - $qb = $this->dbConnection->getQueryBuilder(); |
|
| 756 | - |
|
| 757 | - $qb->select('*') |
|
| 758 | - ->from('share') |
|
| 759 | - ->where($qb->expr()->eq('id', $qb->createNamedParameter($id))) |
|
| 760 | - ->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_EMAIL))); |
|
| 761 | - |
|
| 762 | - $cursor = $qb->execute(); |
|
| 763 | - $data = $cursor->fetch(); |
|
| 764 | - $cursor->closeCursor(); |
|
| 765 | - |
|
| 766 | - if ($data === false) { |
|
| 767 | - throw new ShareNotFound(); |
|
| 768 | - } |
|
| 769 | - |
|
| 770 | - try { |
|
| 771 | - $share = $this->createShareObject($data); |
|
| 772 | - } catch (InvalidShare $e) { |
|
| 773 | - throw new ShareNotFound(); |
|
| 774 | - } |
|
| 775 | - |
|
| 776 | - return $share; |
|
| 777 | - } |
|
| 778 | - |
|
| 779 | - /** |
|
| 780 | - * Get shares for a given path |
|
| 781 | - * |
|
| 782 | - * @param \OCP\Files\Node $path |
|
| 783 | - * @return IShare[] |
|
| 784 | - */ |
|
| 785 | - public function getSharesByPath(Node $path) { |
|
| 786 | - $qb = $this->dbConnection->getQueryBuilder(); |
|
| 787 | - |
|
| 788 | - $cursor = $qb->select('*') |
|
| 789 | - ->from('share') |
|
| 790 | - ->andWhere($qb->expr()->eq('file_source', $qb->createNamedParameter($path->getId()))) |
|
| 791 | - ->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_EMAIL))) |
|
| 792 | - ->execute(); |
|
| 793 | - |
|
| 794 | - $shares = []; |
|
| 795 | - while($data = $cursor->fetch()) { |
|
| 796 | - $shares[] = $this->createShareObject($data); |
|
| 797 | - } |
|
| 798 | - $cursor->closeCursor(); |
|
| 799 | - |
|
| 800 | - return $shares; |
|
| 801 | - } |
|
| 802 | - |
|
| 803 | - /** |
|
| 804 | - * @inheritdoc |
|
| 805 | - */ |
|
| 806 | - public function getSharedWith($userId, $shareType, $node, $limit, $offset) { |
|
| 807 | - /** @var IShare[] $shares */ |
|
| 808 | - $shares = []; |
|
| 809 | - |
|
| 810 | - //Get shares directly with this user |
|
| 811 | - $qb = $this->dbConnection->getQueryBuilder(); |
|
| 812 | - $qb->select('*') |
|
| 813 | - ->from('share'); |
|
| 814 | - |
|
| 815 | - // Order by id |
|
| 816 | - $qb->orderBy('id'); |
|
| 817 | - |
|
| 818 | - // Set limit and offset |
|
| 819 | - if ($limit !== -1) { |
|
| 820 | - $qb->setMaxResults($limit); |
|
| 821 | - } |
|
| 822 | - $qb->setFirstResult($offset); |
|
| 823 | - |
|
| 824 | - $qb->where($qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_EMAIL))); |
|
| 825 | - $qb->andWhere($qb->expr()->eq('share_with', $qb->createNamedParameter($userId))); |
|
| 826 | - |
|
| 827 | - // Filter by node if provided |
|
| 828 | - if ($node !== null) { |
|
| 829 | - $qb->andWhere($qb->expr()->eq('file_source', $qb->createNamedParameter($node->getId()))); |
|
| 830 | - } |
|
| 831 | - |
|
| 832 | - $cursor = $qb->execute(); |
|
| 833 | - |
|
| 834 | - while($data = $cursor->fetch()) { |
|
| 835 | - $shares[] = $this->createShareObject($data); |
|
| 836 | - } |
|
| 837 | - $cursor->closeCursor(); |
|
| 838 | - |
|
| 839 | - |
|
| 840 | - return $shares; |
|
| 841 | - } |
|
| 842 | - |
|
| 843 | - /** |
|
| 844 | - * Get a share by token |
|
| 845 | - * |
|
| 846 | - * @param string $token |
|
| 847 | - * @return IShare |
|
| 848 | - * @throws ShareNotFound |
|
| 849 | - */ |
|
| 850 | - public function getShareByToken($token) { |
|
| 851 | - $qb = $this->dbConnection->getQueryBuilder(); |
|
| 852 | - |
|
| 853 | - $cursor = $qb->select('*') |
|
| 854 | - ->from('share') |
|
| 855 | - ->where($qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_EMAIL))) |
|
| 856 | - ->andWhere($qb->expr()->eq('token', $qb->createNamedParameter($token))) |
|
| 857 | - ->execute(); |
|
| 858 | - |
|
| 859 | - $data = $cursor->fetch(); |
|
| 860 | - |
|
| 861 | - if ($data === false) { |
|
| 862 | - throw new ShareNotFound('Share not found', $this->l->t('Could not find share')); |
|
| 863 | - } |
|
| 864 | - |
|
| 865 | - try { |
|
| 866 | - $share = $this->createShareObject($data); |
|
| 867 | - } catch (InvalidShare $e) { |
|
| 868 | - throw new ShareNotFound('Share not found', $this->l->t('Could not find share')); |
|
| 869 | - } |
|
| 870 | - |
|
| 871 | - return $share; |
|
| 872 | - } |
|
| 873 | - |
|
| 874 | - /** |
|
| 875 | - * remove share from table |
|
| 876 | - * |
|
| 877 | - * @param string $shareId |
|
| 878 | - */ |
|
| 879 | - protected function removeShareFromTable($shareId) { |
|
| 880 | - $qb = $this->dbConnection->getQueryBuilder(); |
|
| 881 | - $qb->delete('share') |
|
| 882 | - ->where($qb->expr()->eq('id', $qb->createNamedParameter($shareId))); |
|
| 883 | - $qb->execute(); |
|
| 884 | - } |
|
| 885 | - |
|
| 886 | - /** |
|
| 887 | - * Create a share object from an database row |
|
| 888 | - * |
|
| 889 | - * @param array $data |
|
| 890 | - * @return IShare |
|
| 891 | - * @throws InvalidShare |
|
| 892 | - * @throws ShareNotFound |
|
| 893 | - */ |
|
| 894 | - protected function createShareObject($data) { |
|
| 895 | - |
|
| 896 | - $share = new Share($this->rootFolder, $this->userManager); |
|
| 897 | - $share->setId((int)$data['id']) |
|
| 898 | - ->setShareType((int)$data['share_type']) |
|
| 899 | - ->setPermissions((int)$data['permissions']) |
|
| 900 | - ->setTarget($data['file_target']) |
|
| 901 | - ->setMailSend((bool)$data['mail_send']) |
|
| 902 | - ->setToken($data['token']); |
|
| 903 | - |
|
| 904 | - $shareTime = new \DateTime(); |
|
| 905 | - $shareTime->setTimestamp((int)$data['stime']); |
|
| 906 | - $share->setShareTime($shareTime); |
|
| 907 | - $share->setSharedWith($data['share_with']); |
|
| 908 | - $share->setPassword($data['password']); |
|
| 909 | - |
|
| 910 | - if ($data['uid_initiator'] !== null) { |
|
| 911 | - $share->setShareOwner($data['uid_owner']); |
|
| 912 | - $share->setSharedBy($data['uid_initiator']); |
|
| 913 | - } else { |
|
| 914 | - //OLD SHARE |
|
| 915 | - $share->setSharedBy($data['uid_owner']); |
|
| 916 | - $path = $this->getNode($share->getSharedBy(), (int)$data['file_source']); |
|
| 917 | - |
|
| 918 | - $owner = $path->getOwner(); |
|
| 919 | - $share->setShareOwner($owner->getUID()); |
|
| 920 | - } |
|
| 921 | - |
|
| 922 | - if ($data['expiration'] !== null) { |
|
| 923 | - $expiration = \DateTime::createFromFormat('Y-m-d H:i:s', $data['expiration']); |
|
| 924 | - if ($expiration !== false) { |
|
| 925 | - $share->setExpirationDate($expiration); |
|
| 926 | - } |
|
| 927 | - } |
|
| 928 | - |
|
| 929 | - $share->setNodeId((int)$data['file_source']); |
|
| 930 | - $share->setNodeType($data['item_type']); |
|
| 931 | - |
|
| 932 | - $share->setProviderId($this->identifier()); |
|
| 933 | - |
|
| 934 | - return $share; |
|
| 935 | - } |
|
| 936 | - |
|
| 937 | - /** |
|
| 938 | - * Get the node with file $id for $user |
|
| 939 | - * |
|
| 940 | - * @param string $userId |
|
| 941 | - * @param int $id |
|
| 942 | - * @return \OCP\Files\File|\OCP\Files\Folder |
|
| 943 | - * @throws InvalidShare |
|
| 944 | - */ |
|
| 945 | - private function getNode($userId, $id) { |
|
| 946 | - try { |
|
| 947 | - $userFolder = $this->rootFolder->getUserFolder($userId); |
|
| 948 | - } catch (NoUserException $e) { |
|
| 949 | - throw new InvalidShare(); |
|
| 950 | - } |
|
| 951 | - |
|
| 952 | - $nodes = $userFolder->getById($id); |
|
| 953 | - |
|
| 954 | - if (empty($nodes)) { |
|
| 955 | - throw new InvalidShare(); |
|
| 956 | - } |
|
| 957 | - |
|
| 958 | - return $nodes[0]; |
|
| 959 | - } |
|
| 960 | - |
|
| 961 | - /** |
|
| 962 | - * A user is deleted from the system |
|
| 963 | - * So clean up the relevant shares. |
|
| 964 | - * |
|
| 965 | - * @param string $uid |
|
| 966 | - * @param int $shareType |
|
| 967 | - */ |
|
| 968 | - public function userDeleted($uid, $shareType) { |
|
| 969 | - $qb = $this->dbConnection->getQueryBuilder(); |
|
| 970 | - |
|
| 971 | - $qb->delete('share') |
|
| 972 | - ->where($qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_EMAIL))) |
|
| 973 | - ->andWhere($qb->expr()->eq('uid_owner', $qb->createNamedParameter($uid))) |
|
| 974 | - ->execute(); |
|
| 975 | - } |
|
| 976 | - |
|
| 977 | - /** |
|
| 978 | - * This provider does not support group shares |
|
| 979 | - * |
|
| 980 | - * @param string $gid |
|
| 981 | - */ |
|
| 982 | - public function groupDeleted($gid) { |
|
| 983 | - } |
|
| 984 | - |
|
| 985 | - /** |
|
| 986 | - * This provider does not support group shares |
|
| 987 | - * |
|
| 988 | - * @param string $uid |
|
| 989 | - * @param string $gid |
|
| 990 | - */ |
|
| 991 | - public function userDeletedFromGroup($uid, $gid) { |
|
| 992 | - } |
|
| 993 | - |
|
| 994 | - /** |
|
| 995 | - * get database row of a give share |
|
| 996 | - * |
|
| 997 | - * @param $id |
|
| 998 | - * @return array |
|
| 999 | - * @throws ShareNotFound |
|
| 1000 | - */ |
|
| 1001 | - protected function getRawShare($id) { |
|
| 1002 | - |
|
| 1003 | - // Now fetch the inserted share and create a complete share object |
|
| 1004 | - $qb = $this->dbConnection->getQueryBuilder(); |
|
| 1005 | - $qb->select('*') |
|
| 1006 | - ->from('share') |
|
| 1007 | - ->where($qb->expr()->eq('id', $qb->createNamedParameter($id))); |
|
| 1008 | - |
|
| 1009 | - $cursor = $qb->execute(); |
|
| 1010 | - $data = $cursor->fetch(); |
|
| 1011 | - $cursor->closeCursor(); |
|
| 1012 | - |
|
| 1013 | - if ($data === false) { |
|
| 1014 | - throw new ShareNotFound; |
|
| 1015 | - } |
|
| 1016 | - |
|
| 1017 | - return $data; |
|
| 1018 | - } |
|
| 1019 | - |
|
| 1020 | - public function getSharesInFolder($userId, Folder $node, $reshares) { |
|
| 1021 | - $qb = $this->dbConnection->getQueryBuilder(); |
|
| 1022 | - $qb->select('*') |
|
| 1023 | - ->from('share', 's') |
|
| 1024 | - ->andWhere($qb->expr()->orX( |
|
| 1025 | - $qb->expr()->eq('item_type', $qb->createNamedParameter('file')), |
|
| 1026 | - $qb->expr()->eq('item_type', $qb->createNamedParameter('folder')) |
|
| 1027 | - )) |
|
| 1028 | - ->andWhere( |
|
| 1029 | - $qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_EMAIL)) |
|
| 1030 | - ); |
|
| 1031 | - |
|
| 1032 | - /** |
|
| 1033 | - * Reshares for this user are shares where they are the owner. |
|
| 1034 | - */ |
|
| 1035 | - if ($reshares === false) { |
|
| 1036 | - $qb->andWhere($qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId))); |
|
| 1037 | - } else { |
|
| 1038 | - $qb->andWhere( |
|
| 1039 | - $qb->expr()->orX( |
|
| 1040 | - $qb->expr()->eq('uid_owner', $qb->createNamedParameter($userId)), |
|
| 1041 | - $qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId)) |
|
| 1042 | - ) |
|
| 1043 | - ); |
|
| 1044 | - } |
|
| 1045 | - |
|
| 1046 | - $qb->innerJoin('s', 'filecache' ,'f', $qb->expr()->eq('s.file_source', 'f.fileid')); |
|
| 1047 | - $qb->andWhere($qb->expr()->eq('f.parent', $qb->createNamedParameter($node->getId()))); |
|
| 1048 | - |
|
| 1049 | - $qb->orderBy('id'); |
|
| 1050 | - |
|
| 1051 | - $cursor = $qb->execute(); |
|
| 1052 | - $shares = []; |
|
| 1053 | - while ($data = $cursor->fetch()) { |
|
| 1054 | - $shares[$data['fileid']][] = $this->createShareObject($data); |
|
| 1055 | - } |
|
| 1056 | - $cursor->closeCursor(); |
|
| 1057 | - |
|
| 1058 | - return $shares; |
|
| 1059 | - } |
|
| 1060 | - |
|
| 1061 | - /** |
|
| 1062 | - * @inheritdoc |
|
| 1063 | - */ |
|
| 1064 | - public function getAccessList($nodes, $currentAccess) { |
|
| 1065 | - $ids = []; |
|
| 1066 | - foreach ($nodes as $node) { |
|
| 1067 | - $ids[] = $node->getId(); |
|
| 1068 | - } |
|
| 1069 | - |
|
| 1070 | - $qb = $this->dbConnection->getQueryBuilder(); |
|
| 1071 | - $qb->select('share_with') |
|
| 1072 | - ->from('share') |
|
| 1073 | - ->where($qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_EMAIL))) |
|
| 1074 | - ->andWhere($qb->expr()->in('file_source', $qb->createNamedParameter($ids, IQueryBuilder::PARAM_INT_ARRAY))) |
|
| 1075 | - ->andWhere($qb->expr()->orX( |
|
| 1076 | - $qb->expr()->eq('item_type', $qb->createNamedParameter('file')), |
|
| 1077 | - $qb->expr()->eq('item_type', $qb->createNamedParameter('folder')) |
|
| 1078 | - )) |
|
| 1079 | - ->setMaxResults(1); |
|
| 1080 | - $cursor = $qb->execute(); |
|
| 1081 | - |
|
| 1082 | - $mail = $cursor->fetch() !== false; |
|
| 1083 | - $cursor->closeCursor(); |
|
| 1084 | - |
|
| 1085 | - return ['public' => $mail]; |
|
| 1086 | - } |
|
| 656 | + $qb = $this->dbConnection->getQueryBuilder(); |
|
| 657 | + $qb->update('share') |
|
| 658 | + ->where($qb->expr()->eq('id', $qb->createNamedParameter($share->getId()))) |
|
| 659 | + ->set('permissions', $qb->createNamedParameter($share->getPermissions())) |
|
| 660 | + ->set('uid_owner', $qb->createNamedParameter($share->getShareOwner())) |
|
| 661 | + ->set('uid_initiator', $qb->createNamedParameter($share->getSharedBy())) |
|
| 662 | + ->set('password', $qb->createNamedParameter($share->getPassword())) |
|
| 663 | + ->set('expiration', $qb->createNamedParameter($share->getExpirationDate(), IQueryBuilder::PARAM_DATE)) |
|
| 664 | + ->execute(); |
|
| 665 | + |
|
| 666 | + return $share; |
|
| 667 | + } |
|
| 668 | + |
|
| 669 | + /** |
|
| 670 | + * @inheritdoc |
|
| 671 | + */ |
|
| 672 | + public function move(IShare $share, $recipient) { |
|
| 673 | + /** |
|
| 674 | + * nothing to do here, mail shares are only outgoing shares |
|
| 675 | + */ |
|
| 676 | + return $share; |
|
| 677 | + } |
|
| 678 | + |
|
| 679 | + /** |
|
| 680 | + * Delete a share (owner unShares the file) |
|
| 681 | + * |
|
| 682 | + * @param IShare $share |
|
| 683 | + */ |
|
| 684 | + public function delete(IShare $share) { |
|
| 685 | + $this->removeShareFromTable($share->getId()); |
|
| 686 | + } |
|
| 687 | + |
|
| 688 | + /** |
|
| 689 | + * @inheritdoc |
|
| 690 | + */ |
|
| 691 | + public function deleteFromSelf(IShare $share, $recipient) { |
|
| 692 | + // nothing to do here, mail shares are only outgoing shares |
|
| 693 | + } |
|
| 694 | + |
|
| 695 | + /** |
|
| 696 | + * @inheritdoc |
|
| 697 | + */ |
|
| 698 | + public function getSharesBy($userId, $shareType, $node, $reshares, $limit, $offset) { |
|
| 699 | + $qb = $this->dbConnection->getQueryBuilder(); |
|
| 700 | + $qb->select('*') |
|
| 701 | + ->from('share'); |
|
| 702 | + |
|
| 703 | + $qb->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_EMAIL))); |
|
| 704 | + |
|
| 705 | + /** |
|
| 706 | + * Reshares for this user are shares where they are the owner. |
|
| 707 | + */ |
|
| 708 | + if ($reshares === false) { |
|
| 709 | + //Special case for old shares created via the web UI |
|
| 710 | + $or1 = $qb->expr()->andX( |
|
| 711 | + $qb->expr()->eq('uid_owner', $qb->createNamedParameter($userId)), |
|
| 712 | + $qb->expr()->isNull('uid_initiator') |
|
| 713 | + ); |
|
| 714 | + |
|
| 715 | + $qb->andWhere( |
|
| 716 | + $qb->expr()->orX( |
|
| 717 | + $qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId)), |
|
| 718 | + $or1 |
|
| 719 | + ) |
|
| 720 | + ); |
|
| 721 | + } else { |
|
| 722 | + $qb->andWhere( |
|
| 723 | + $qb->expr()->orX( |
|
| 724 | + $qb->expr()->eq('uid_owner', $qb->createNamedParameter($userId)), |
|
| 725 | + $qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId)) |
|
| 726 | + ) |
|
| 727 | + ); |
|
| 728 | + } |
|
| 729 | + |
|
| 730 | + if ($node !== null) { |
|
| 731 | + $qb->andWhere($qb->expr()->eq('file_source', $qb->createNamedParameter($node->getId()))); |
|
| 732 | + } |
|
| 733 | + |
|
| 734 | + if ($limit !== -1) { |
|
| 735 | + $qb->setMaxResults($limit); |
|
| 736 | + } |
|
| 737 | + |
|
| 738 | + $qb->setFirstResult($offset); |
|
| 739 | + $qb->orderBy('id'); |
|
| 740 | + |
|
| 741 | + $cursor = $qb->execute(); |
|
| 742 | + $shares = []; |
|
| 743 | + while($data = $cursor->fetch()) { |
|
| 744 | + $shares[] = $this->createShareObject($data); |
|
| 745 | + } |
|
| 746 | + $cursor->closeCursor(); |
|
| 747 | + |
|
| 748 | + return $shares; |
|
| 749 | + } |
|
| 750 | + |
|
| 751 | + /** |
|
| 752 | + * @inheritdoc |
|
| 753 | + */ |
|
| 754 | + public function getShareById($id, $recipientId = null) { |
|
| 755 | + $qb = $this->dbConnection->getQueryBuilder(); |
|
| 756 | + |
|
| 757 | + $qb->select('*') |
|
| 758 | + ->from('share') |
|
| 759 | + ->where($qb->expr()->eq('id', $qb->createNamedParameter($id))) |
|
| 760 | + ->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_EMAIL))); |
|
| 761 | + |
|
| 762 | + $cursor = $qb->execute(); |
|
| 763 | + $data = $cursor->fetch(); |
|
| 764 | + $cursor->closeCursor(); |
|
| 765 | + |
|
| 766 | + if ($data === false) { |
|
| 767 | + throw new ShareNotFound(); |
|
| 768 | + } |
|
| 769 | + |
|
| 770 | + try { |
|
| 771 | + $share = $this->createShareObject($data); |
|
| 772 | + } catch (InvalidShare $e) { |
|
| 773 | + throw new ShareNotFound(); |
|
| 774 | + } |
|
| 775 | + |
|
| 776 | + return $share; |
|
| 777 | + } |
|
| 778 | + |
|
| 779 | + /** |
|
| 780 | + * Get shares for a given path |
|
| 781 | + * |
|
| 782 | + * @param \OCP\Files\Node $path |
|
| 783 | + * @return IShare[] |
|
| 784 | + */ |
|
| 785 | + public function getSharesByPath(Node $path) { |
|
| 786 | + $qb = $this->dbConnection->getQueryBuilder(); |
|
| 787 | + |
|
| 788 | + $cursor = $qb->select('*') |
|
| 789 | + ->from('share') |
|
| 790 | + ->andWhere($qb->expr()->eq('file_source', $qb->createNamedParameter($path->getId()))) |
|
| 791 | + ->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_EMAIL))) |
|
| 792 | + ->execute(); |
|
| 793 | + |
|
| 794 | + $shares = []; |
|
| 795 | + while($data = $cursor->fetch()) { |
|
| 796 | + $shares[] = $this->createShareObject($data); |
|
| 797 | + } |
|
| 798 | + $cursor->closeCursor(); |
|
| 799 | + |
|
| 800 | + return $shares; |
|
| 801 | + } |
|
| 802 | + |
|
| 803 | + /** |
|
| 804 | + * @inheritdoc |
|
| 805 | + */ |
|
| 806 | + public function getSharedWith($userId, $shareType, $node, $limit, $offset) { |
|
| 807 | + /** @var IShare[] $shares */ |
|
| 808 | + $shares = []; |
|
| 809 | + |
|
| 810 | + //Get shares directly with this user |
|
| 811 | + $qb = $this->dbConnection->getQueryBuilder(); |
|
| 812 | + $qb->select('*') |
|
| 813 | + ->from('share'); |
|
| 814 | + |
|
| 815 | + // Order by id |
|
| 816 | + $qb->orderBy('id'); |
|
| 817 | + |
|
| 818 | + // Set limit and offset |
|
| 819 | + if ($limit !== -1) { |
|
| 820 | + $qb->setMaxResults($limit); |
|
| 821 | + } |
|
| 822 | + $qb->setFirstResult($offset); |
|
| 823 | + |
|
| 824 | + $qb->where($qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_EMAIL))); |
|
| 825 | + $qb->andWhere($qb->expr()->eq('share_with', $qb->createNamedParameter($userId))); |
|
| 826 | + |
|
| 827 | + // Filter by node if provided |
|
| 828 | + if ($node !== null) { |
|
| 829 | + $qb->andWhere($qb->expr()->eq('file_source', $qb->createNamedParameter($node->getId()))); |
|
| 830 | + } |
|
| 831 | + |
|
| 832 | + $cursor = $qb->execute(); |
|
| 833 | + |
|
| 834 | + while($data = $cursor->fetch()) { |
|
| 835 | + $shares[] = $this->createShareObject($data); |
|
| 836 | + } |
|
| 837 | + $cursor->closeCursor(); |
|
| 838 | + |
|
| 839 | + |
|
| 840 | + return $shares; |
|
| 841 | + } |
|
| 842 | + |
|
| 843 | + /** |
|
| 844 | + * Get a share by token |
|
| 845 | + * |
|
| 846 | + * @param string $token |
|
| 847 | + * @return IShare |
|
| 848 | + * @throws ShareNotFound |
|
| 849 | + */ |
|
| 850 | + public function getShareByToken($token) { |
|
| 851 | + $qb = $this->dbConnection->getQueryBuilder(); |
|
| 852 | + |
|
| 853 | + $cursor = $qb->select('*') |
|
| 854 | + ->from('share') |
|
| 855 | + ->where($qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_EMAIL))) |
|
| 856 | + ->andWhere($qb->expr()->eq('token', $qb->createNamedParameter($token))) |
|
| 857 | + ->execute(); |
|
| 858 | + |
|
| 859 | + $data = $cursor->fetch(); |
|
| 860 | + |
|
| 861 | + if ($data === false) { |
|
| 862 | + throw new ShareNotFound('Share not found', $this->l->t('Could not find share')); |
|
| 863 | + } |
|
| 864 | + |
|
| 865 | + try { |
|
| 866 | + $share = $this->createShareObject($data); |
|
| 867 | + } catch (InvalidShare $e) { |
|
| 868 | + throw new ShareNotFound('Share not found', $this->l->t('Could not find share')); |
|
| 869 | + } |
|
| 870 | + |
|
| 871 | + return $share; |
|
| 872 | + } |
|
| 873 | + |
|
| 874 | + /** |
|
| 875 | + * remove share from table |
|
| 876 | + * |
|
| 877 | + * @param string $shareId |
|
| 878 | + */ |
|
| 879 | + protected function removeShareFromTable($shareId) { |
|
| 880 | + $qb = $this->dbConnection->getQueryBuilder(); |
|
| 881 | + $qb->delete('share') |
|
| 882 | + ->where($qb->expr()->eq('id', $qb->createNamedParameter($shareId))); |
|
| 883 | + $qb->execute(); |
|
| 884 | + } |
|
| 885 | + |
|
| 886 | + /** |
|
| 887 | + * Create a share object from an database row |
|
| 888 | + * |
|
| 889 | + * @param array $data |
|
| 890 | + * @return IShare |
|
| 891 | + * @throws InvalidShare |
|
| 892 | + * @throws ShareNotFound |
|
| 893 | + */ |
|
| 894 | + protected function createShareObject($data) { |
|
| 895 | + |
|
| 896 | + $share = new Share($this->rootFolder, $this->userManager); |
|
| 897 | + $share->setId((int)$data['id']) |
|
| 898 | + ->setShareType((int)$data['share_type']) |
|
| 899 | + ->setPermissions((int)$data['permissions']) |
|
| 900 | + ->setTarget($data['file_target']) |
|
| 901 | + ->setMailSend((bool)$data['mail_send']) |
|
| 902 | + ->setToken($data['token']); |
|
| 903 | + |
|
| 904 | + $shareTime = new \DateTime(); |
|
| 905 | + $shareTime->setTimestamp((int)$data['stime']); |
|
| 906 | + $share->setShareTime($shareTime); |
|
| 907 | + $share->setSharedWith($data['share_with']); |
|
| 908 | + $share->setPassword($data['password']); |
|
| 909 | + |
|
| 910 | + if ($data['uid_initiator'] !== null) { |
|
| 911 | + $share->setShareOwner($data['uid_owner']); |
|
| 912 | + $share->setSharedBy($data['uid_initiator']); |
|
| 913 | + } else { |
|
| 914 | + //OLD SHARE |
|
| 915 | + $share->setSharedBy($data['uid_owner']); |
|
| 916 | + $path = $this->getNode($share->getSharedBy(), (int)$data['file_source']); |
|
| 917 | + |
|
| 918 | + $owner = $path->getOwner(); |
|
| 919 | + $share->setShareOwner($owner->getUID()); |
|
| 920 | + } |
|
| 921 | + |
|
| 922 | + if ($data['expiration'] !== null) { |
|
| 923 | + $expiration = \DateTime::createFromFormat('Y-m-d H:i:s', $data['expiration']); |
|
| 924 | + if ($expiration !== false) { |
|
| 925 | + $share->setExpirationDate($expiration); |
|
| 926 | + } |
|
| 927 | + } |
|
| 928 | + |
|
| 929 | + $share->setNodeId((int)$data['file_source']); |
|
| 930 | + $share->setNodeType($data['item_type']); |
|
| 931 | + |
|
| 932 | + $share->setProviderId($this->identifier()); |
|
| 933 | + |
|
| 934 | + return $share; |
|
| 935 | + } |
|
| 936 | + |
|
| 937 | + /** |
|
| 938 | + * Get the node with file $id for $user |
|
| 939 | + * |
|
| 940 | + * @param string $userId |
|
| 941 | + * @param int $id |
|
| 942 | + * @return \OCP\Files\File|\OCP\Files\Folder |
|
| 943 | + * @throws InvalidShare |
|
| 944 | + */ |
|
| 945 | + private function getNode($userId, $id) { |
|
| 946 | + try { |
|
| 947 | + $userFolder = $this->rootFolder->getUserFolder($userId); |
|
| 948 | + } catch (NoUserException $e) { |
|
| 949 | + throw new InvalidShare(); |
|
| 950 | + } |
|
| 951 | + |
|
| 952 | + $nodes = $userFolder->getById($id); |
|
| 953 | + |
|
| 954 | + if (empty($nodes)) { |
|
| 955 | + throw new InvalidShare(); |
|
| 956 | + } |
|
| 957 | + |
|
| 958 | + return $nodes[0]; |
|
| 959 | + } |
|
| 960 | + |
|
| 961 | + /** |
|
| 962 | + * A user is deleted from the system |
|
| 963 | + * So clean up the relevant shares. |
|
| 964 | + * |
|
| 965 | + * @param string $uid |
|
| 966 | + * @param int $shareType |
|
| 967 | + */ |
|
| 968 | + public function userDeleted($uid, $shareType) { |
|
| 969 | + $qb = $this->dbConnection->getQueryBuilder(); |
|
| 970 | + |
|
| 971 | + $qb->delete('share') |
|
| 972 | + ->where($qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_EMAIL))) |
|
| 973 | + ->andWhere($qb->expr()->eq('uid_owner', $qb->createNamedParameter($uid))) |
|
| 974 | + ->execute(); |
|
| 975 | + } |
|
| 976 | + |
|
| 977 | + /** |
|
| 978 | + * This provider does not support group shares |
|
| 979 | + * |
|
| 980 | + * @param string $gid |
|
| 981 | + */ |
|
| 982 | + public function groupDeleted($gid) { |
|
| 983 | + } |
|
| 984 | + |
|
| 985 | + /** |
|
| 986 | + * This provider does not support group shares |
|
| 987 | + * |
|
| 988 | + * @param string $uid |
|
| 989 | + * @param string $gid |
|
| 990 | + */ |
|
| 991 | + public function userDeletedFromGroup($uid, $gid) { |
|
| 992 | + } |
|
| 993 | + |
|
| 994 | + /** |
|
| 995 | + * get database row of a give share |
|
| 996 | + * |
|
| 997 | + * @param $id |
|
| 998 | + * @return array |
|
| 999 | + * @throws ShareNotFound |
|
| 1000 | + */ |
|
| 1001 | + protected function getRawShare($id) { |
|
| 1002 | + |
|
| 1003 | + // Now fetch the inserted share and create a complete share object |
|
| 1004 | + $qb = $this->dbConnection->getQueryBuilder(); |
|
| 1005 | + $qb->select('*') |
|
| 1006 | + ->from('share') |
|
| 1007 | + ->where($qb->expr()->eq('id', $qb->createNamedParameter($id))); |
|
| 1008 | + |
|
| 1009 | + $cursor = $qb->execute(); |
|
| 1010 | + $data = $cursor->fetch(); |
|
| 1011 | + $cursor->closeCursor(); |
|
| 1012 | + |
|
| 1013 | + if ($data === false) { |
|
| 1014 | + throw new ShareNotFound; |
|
| 1015 | + } |
|
| 1016 | + |
|
| 1017 | + return $data; |
|
| 1018 | + } |
|
| 1019 | + |
|
| 1020 | + public function getSharesInFolder($userId, Folder $node, $reshares) { |
|
| 1021 | + $qb = $this->dbConnection->getQueryBuilder(); |
|
| 1022 | + $qb->select('*') |
|
| 1023 | + ->from('share', 's') |
|
| 1024 | + ->andWhere($qb->expr()->orX( |
|
| 1025 | + $qb->expr()->eq('item_type', $qb->createNamedParameter('file')), |
|
| 1026 | + $qb->expr()->eq('item_type', $qb->createNamedParameter('folder')) |
|
| 1027 | + )) |
|
| 1028 | + ->andWhere( |
|
| 1029 | + $qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_EMAIL)) |
|
| 1030 | + ); |
|
| 1031 | + |
|
| 1032 | + /** |
|
| 1033 | + * Reshares for this user are shares where they are the owner. |
|
| 1034 | + */ |
|
| 1035 | + if ($reshares === false) { |
|
| 1036 | + $qb->andWhere($qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId))); |
|
| 1037 | + } else { |
|
| 1038 | + $qb->andWhere( |
|
| 1039 | + $qb->expr()->orX( |
|
| 1040 | + $qb->expr()->eq('uid_owner', $qb->createNamedParameter($userId)), |
|
| 1041 | + $qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId)) |
|
| 1042 | + ) |
|
| 1043 | + ); |
|
| 1044 | + } |
|
| 1045 | + |
|
| 1046 | + $qb->innerJoin('s', 'filecache' ,'f', $qb->expr()->eq('s.file_source', 'f.fileid')); |
|
| 1047 | + $qb->andWhere($qb->expr()->eq('f.parent', $qb->createNamedParameter($node->getId()))); |
|
| 1048 | + |
|
| 1049 | + $qb->orderBy('id'); |
|
| 1050 | + |
|
| 1051 | + $cursor = $qb->execute(); |
|
| 1052 | + $shares = []; |
|
| 1053 | + while ($data = $cursor->fetch()) { |
|
| 1054 | + $shares[$data['fileid']][] = $this->createShareObject($data); |
|
| 1055 | + } |
|
| 1056 | + $cursor->closeCursor(); |
|
| 1057 | + |
|
| 1058 | + return $shares; |
|
| 1059 | + } |
|
| 1060 | + |
|
| 1061 | + /** |
|
| 1062 | + * @inheritdoc |
|
| 1063 | + */ |
|
| 1064 | + public function getAccessList($nodes, $currentAccess) { |
|
| 1065 | + $ids = []; |
|
| 1066 | + foreach ($nodes as $node) { |
|
| 1067 | + $ids[] = $node->getId(); |
|
| 1068 | + } |
|
| 1069 | + |
|
| 1070 | + $qb = $this->dbConnection->getQueryBuilder(); |
|
| 1071 | + $qb->select('share_with') |
|
| 1072 | + ->from('share') |
|
| 1073 | + ->where($qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_EMAIL))) |
|
| 1074 | + ->andWhere($qb->expr()->in('file_source', $qb->createNamedParameter($ids, IQueryBuilder::PARAM_INT_ARRAY))) |
|
| 1075 | + ->andWhere($qb->expr()->orX( |
|
| 1076 | + $qb->expr()->eq('item_type', $qb->createNamedParameter('file')), |
|
| 1077 | + $qb->expr()->eq('item_type', $qb->createNamedParameter('folder')) |
|
| 1078 | + )) |
|
| 1079 | + ->setMaxResults(1); |
|
| 1080 | + $cursor = $qb->execute(); |
|
| 1081 | + |
|
| 1082 | + $mail = $cursor->fetch() !== false; |
|
| 1083 | + $cursor->closeCursor(); |
|
| 1084 | + |
|
| 1085 | + return ['public' => $mail]; |
|
| 1086 | + } |
|
| 1087 | 1087 | |
| 1088 | 1088 | } |
@@ -53,989 +53,989 @@ |
||
| 53 | 53 | */ |
| 54 | 54 | class FederatedShareProvider implements IShareProvider { |
| 55 | 55 | |
| 56 | - const SHARE_TYPE_REMOTE = 6; |
|
| 57 | - |
|
| 58 | - /** @var IDBConnection */ |
|
| 59 | - private $dbConnection; |
|
| 60 | - |
|
| 61 | - /** @var AddressHandler */ |
|
| 62 | - private $addressHandler; |
|
| 63 | - |
|
| 64 | - /** @var Notifications */ |
|
| 65 | - private $notifications; |
|
| 66 | - |
|
| 67 | - /** @var TokenHandler */ |
|
| 68 | - private $tokenHandler; |
|
| 69 | - |
|
| 70 | - /** @var IL10N */ |
|
| 71 | - private $l; |
|
| 72 | - |
|
| 73 | - /** @var ILogger */ |
|
| 74 | - private $logger; |
|
| 75 | - |
|
| 76 | - /** @var IRootFolder */ |
|
| 77 | - private $rootFolder; |
|
| 78 | - |
|
| 79 | - /** @var IConfig */ |
|
| 80 | - private $config; |
|
| 81 | - |
|
| 82 | - /** @var string */ |
|
| 83 | - private $externalShareTable = 'share_external'; |
|
| 84 | - |
|
| 85 | - /** @var IUserManager */ |
|
| 86 | - private $userManager; |
|
| 87 | - |
|
| 88 | - /** @var ICloudIdManager */ |
|
| 89 | - private $cloudIdManager; |
|
| 90 | - |
|
| 91 | - /** @var \OCP\GlobalScale\IConfig */ |
|
| 92 | - private $gsConfig; |
|
| 93 | - |
|
| 94 | - /** |
|
| 95 | - * DefaultShareProvider constructor. |
|
| 96 | - * |
|
| 97 | - * @param IDBConnection $connection |
|
| 98 | - * @param AddressHandler $addressHandler |
|
| 99 | - * @param Notifications $notifications |
|
| 100 | - * @param TokenHandler $tokenHandler |
|
| 101 | - * @param IL10N $l10n |
|
| 102 | - * @param ILogger $logger |
|
| 103 | - * @param IRootFolder $rootFolder |
|
| 104 | - * @param IConfig $config |
|
| 105 | - * @param IUserManager $userManager |
|
| 106 | - * @param ICloudIdManager $cloudIdManager |
|
| 107 | - * @param \OCP\GlobalScale\IConfig $globalScaleConfig |
|
| 108 | - */ |
|
| 109 | - public function __construct( |
|
| 110 | - IDBConnection $connection, |
|
| 111 | - AddressHandler $addressHandler, |
|
| 112 | - Notifications $notifications, |
|
| 113 | - TokenHandler $tokenHandler, |
|
| 114 | - IL10N $l10n, |
|
| 115 | - ILogger $logger, |
|
| 116 | - IRootFolder $rootFolder, |
|
| 117 | - IConfig $config, |
|
| 118 | - IUserManager $userManager, |
|
| 119 | - ICloudIdManager $cloudIdManager, |
|
| 120 | - \OCP\GlobalScale\IConfig $globalScaleConfig |
|
| 121 | - ) { |
|
| 122 | - $this->dbConnection = $connection; |
|
| 123 | - $this->addressHandler = $addressHandler; |
|
| 124 | - $this->notifications = $notifications; |
|
| 125 | - $this->tokenHandler = $tokenHandler; |
|
| 126 | - $this->l = $l10n; |
|
| 127 | - $this->logger = $logger; |
|
| 128 | - $this->rootFolder = $rootFolder; |
|
| 129 | - $this->config = $config; |
|
| 130 | - $this->userManager = $userManager; |
|
| 131 | - $this->cloudIdManager = $cloudIdManager; |
|
| 132 | - $this->gsConfig = $globalScaleConfig; |
|
| 133 | - } |
|
| 134 | - |
|
| 135 | - /** |
|
| 136 | - * Return the identifier of this provider. |
|
| 137 | - * |
|
| 138 | - * @return string Containing only [a-zA-Z0-9] |
|
| 139 | - */ |
|
| 140 | - public function identifier() { |
|
| 141 | - return 'ocFederatedSharing'; |
|
| 142 | - } |
|
| 143 | - |
|
| 144 | - /** |
|
| 145 | - * Share a path |
|
| 146 | - * |
|
| 147 | - * @param IShare $share |
|
| 148 | - * @return IShare The share object |
|
| 149 | - * @throws ShareNotFound |
|
| 150 | - * @throws \Exception |
|
| 151 | - */ |
|
| 152 | - public function create(IShare $share) { |
|
| 153 | - |
|
| 154 | - $shareWith = $share->getSharedWith(); |
|
| 155 | - $itemSource = $share->getNodeId(); |
|
| 156 | - $itemType = $share->getNodeType(); |
|
| 157 | - $permissions = $share->getPermissions(); |
|
| 158 | - $sharedBy = $share->getSharedBy(); |
|
| 159 | - |
|
| 160 | - /* |
|
| 56 | + const SHARE_TYPE_REMOTE = 6; |
|
| 57 | + |
|
| 58 | + /** @var IDBConnection */ |
|
| 59 | + private $dbConnection; |
|
| 60 | + |
|
| 61 | + /** @var AddressHandler */ |
|
| 62 | + private $addressHandler; |
|
| 63 | + |
|
| 64 | + /** @var Notifications */ |
|
| 65 | + private $notifications; |
|
| 66 | + |
|
| 67 | + /** @var TokenHandler */ |
|
| 68 | + private $tokenHandler; |
|
| 69 | + |
|
| 70 | + /** @var IL10N */ |
|
| 71 | + private $l; |
|
| 72 | + |
|
| 73 | + /** @var ILogger */ |
|
| 74 | + private $logger; |
|
| 75 | + |
|
| 76 | + /** @var IRootFolder */ |
|
| 77 | + private $rootFolder; |
|
| 78 | + |
|
| 79 | + /** @var IConfig */ |
|
| 80 | + private $config; |
|
| 81 | + |
|
| 82 | + /** @var string */ |
|
| 83 | + private $externalShareTable = 'share_external'; |
|
| 84 | + |
|
| 85 | + /** @var IUserManager */ |
|
| 86 | + private $userManager; |
|
| 87 | + |
|
| 88 | + /** @var ICloudIdManager */ |
|
| 89 | + private $cloudIdManager; |
|
| 90 | + |
|
| 91 | + /** @var \OCP\GlobalScale\IConfig */ |
|
| 92 | + private $gsConfig; |
|
| 93 | + |
|
| 94 | + /** |
|
| 95 | + * DefaultShareProvider constructor. |
|
| 96 | + * |
|
| 97 | + * @param IDBConnection $connection |
|
| 98 | + * @param AddressHandler $addressHandler |
|
| 99 | + * @param Notifications $notifications |
|
| 100 | + * @param TokenHandler $tokenHandler |
|
| 101 | + * @param IL10N $l10n |
|
| 102 | + * @param ILogger $logger |
|
| 103 | + * @param IRootFolder $rootFolder |
|
| 104 | + * @param IConfig $config |
|
| 105 | + * @param IUserManager $userManager |
|
| 106 | + * @param ICloudIdManager $cloudIdManager |
|
| 107 | + * @param \OCP\GlobalScale\IConfig $globalScaleConfig |
|
| 108 | + */ |
|
| 109 | + public function __construct( |
|
| 110 | + IDBConnection $connection, |
|
| 111 | + AddressHandler $addressHandler, |
|
| 112 | + Notifications $notifications, |
|
| 113 | + TokenHandler $tokenHandler, |
|
| 114 | + IL10N $l10n, |
|
| 115 | + ILogger $logger, |
|
| 116 | + IRootFolder $rootFolder, |
|
| 117 | + IConfig $config, |
|
| 118 | + IUserManager $userManager, |
|
| 119 | + ICloudIdManager $cloudIdManager, |
|
| 120 | + \OCP\GlobalScale\IConfig $globalScaleConfig |
|
| 121 | + ) { |
|
| 122 | + $this->dbConnection = $connection; |
|
| 123 | + $this->addressHandler = $addressHandler; |
|
| 124 | + $this->notifications = $notifications; |
|
| 125 | + $this->tokenHandler = $tokenHandler; |
|
| 126 | + $this->l = $l10n; |
|
| 127 | + $this->logger = $logger; |
|
| 128 | + $this->rootFolder = $rootFolder; |
|
| 129 | + $this->config = $config; |
|
| 130 | + $this->userManager = $userManager; |
|
| 131 | + $this->cloudIdManager = $cloudIdManager; |
|
| 132 | + $this->gsConfig = $globalScaleConfig; |
|
| 133 | + } |
|
| 134 | + |
|
| 135 | + /** |
|
| 136 | + * Return the identifier of this provider. |
|
| 137 | + * |
|
| 138 | + * @return string Containing only [a-zA-Z0-9] |
|
| 139 | + */ |
|
| 140 | + public function identifier() { |
|
| 141 | + return 'ocFederatedSharing'; |
|
| 142 | + } |
|
| 143 | + |
|
| 144 | + /** |
|
| 145 | + * Share a path |
|
| 146 | + * |
|
| 147 | + * @param IShare $share |
|
| 148 | + * @return IShare The share object |
|
| 149 | + * @throws ShareNotFound |
|
| 150 | + * @throws \Exception |
|
| 151 | + */ |
|
| 152 | + public function create(IShare $share) { |
|
| 153 | + |
|
| 154 | + $shareWith = $share->getSharedWith(); |
|
| 155 | + $itemSource = $share->getNodeId(); |
|
| 156 | + $itemType = $share->getNodeType(); |
|
| 157 | + $permissions = $share->getPermissions(); |
|
| 158 | + $sharedBy = $share->getSharedBy(); |
|
| 159 | + |
|
| 160 | + /* |
|
| 161 | 161 | * Check if file is not already shared with the remote user |
| 162 | 162 | */ |
| 163 | - $alreadyShared = $this->getSharedWith($shareWith, self::SHARE_TYPE_REMOTE, $share->getNode(), 1, 0); |
|
| 164 | - if (!empty($alreadyShared)) { |
|
| 165 | - $message = 'Sharing %s failed, because this item is already shared with %s'; |
|
| 166 | - $message_t = $this->l->t('Sharing %s failed, because this item is already shared with %s', array($share->getNode()->getName(), $shareWith)); |
|
| 167 | - $this->logger->debug(sprintf($message, $share->getNode()->getName(), $shareWith), ['app' => 'Federated File Sharing']); |
|
| 168 | - throw new \Exception($message_t); |
|
| 169 | - } |
|
| 170 | - |
|
| 171 | - |
|
| 172 | - // don't allow federated shares if source and target server are the same |
|
| 173 | - $cloudId = $this->cloudIdManager->resolveCloudId($shareWith); |
|
| 174 | - $currentServer = $this->addressHandler->generateRemoteURL(); |
|
| 175 | - $currentUser = $sharedBy; |
|
| 176 | - if ($this->addressHandler->compareAddresses($cloudId->getUser(), $cloudId->getRemote(), $currentUser, $currentServer)) { |
|
| 177 | - $message = 'Not allowed to create a federated share with the same user.'; |
|
| 178 | - $message_t = $this->l->t('Not allowed to create a federated share with the same user'); |
|
| 179 | - $this->logger->debug($message, ['app' => 'Federated File Sharing']); |
|
| 180 | - throw new \Exception($message_t); |
|
| 181 | - } |
|
| 182 | - |
|
| 183 | - |
|
| 184 | - $share->setSharedWith($cloudId->getId()); |
|
| 185 | - |
|
| 186 | - try { |
|
| 187 | - $remoteShare = $this->getShareFromExternalShareTable($share); |
|
| 188 | - } catch (ShareNotFound $e) { |
|
| 189 | - $remoteShare = null; |
|
| 190 | - } |
|
| 191 | - |
|
| 192 | - if ($remoteShare) { |
|
| 193 | - try { |
|
| 194 | - $ownerCloudId = $this->cloudIdManager->getCloudId($remoteShare['owner'], $remoteShare['remote']); |
|
| 195 | - $shareId = $this->addShareToDB($itemSource, $itemType, $shareWith, $sharedBy, $ownerCloudId->getId(), $permissions, 'tmp_token_' . time()); |
|
| 196 | - $share->setId($shareId); |
|
| 197 | - list($token, $remoteId) = $this->askOwnerToReShare($shareWith, $share, $shareId); |
|
| 198 | - // remote share was create successfully if we get a valid token as return |
|
| 199 | - $send = is_string($token) && $token !== ''; |
|
| 200 | - } catch (\Exception $e) { |
|
| 201 | - // fall back to old re-share behavior if the remote server |
|
| 202 | - // doesn't support flat re-shares (was introduced with Nextcloud 9.1) |
|
| 203 | - $this->removeShareFromTable($share); |
|
| 204 | - $shareId = $this->createFederatedShare($share); |
|
| 205 | - } |
|
| 206 | - if ($send) { |
|
| 207 | - $this->updateSuccessfulReshare($shareId, $token); |
|
| 208 | - $this->storeRemoteId($shareId, $remoteId); |
|
| 209 | - } else { |
|
| 210 | - $this->removeShareFromTable($share); |
|
| 211 | - $message_t = $this->l->t('File is already shared with %s', [$shareWith]); |
|
| 212 | - throw new \Exception($message_t); |
|
| 213 | - } |
|
| 214 | - |
|
| 215 | - } else { |
|
| 216 | - $shareId = $this->createFederatedShare($share); |
|
| 217 | - } |
|
| 218 | - |
|
| 219 | - $data = $this->getRawShare($shareId); |
|
| 220 | - return $this->createShareObject($data); |
|
| 221 | - } |
|
| 222 | - |
|
| 223 | - /** |
|
| 224 | - * create federated share and inform the recipient |
|
| 225 | - * |
|
| 226 | - * @param IShare $share |
|
| 227 | - * @return int |
|
| 228 | - * @throws ShareNotFound |
|
| 229 | - * @throws \Exception |
|
| 230 | - */ |
|
| 231 | - protected function createFederatedShare(IShare $share) { |
|
| 232 | - $token = $this->tokenHandler->generateToken(); |
|
| 233 | - $shareId = $this->addShareToDB( |
|
| 234 | - $share->getNodeId(), |
|
| 235 | - $share->getNodeType(), |
|
| 236 | - $share->getSharedWith(), |
|
| 237 | - $share->getSharedBy(), |
|
| 238 | - $share->getShareOwner(), |
|
| 239 | - $share->getPermissions(), |
|
| 240 | - $token |
|
| 241 | - ); |
|
| 242 | - |
|
| 243 | - $failure = false; |
|
| 244 | - |
|
| 245 | - try { |
|
| 246 | - $sharedByFederatedId = $share->getSharedBy(); |
|
| 247 | - if ($this->userManager->userExists($sharedByFederatedId)) { |
|
| 248 | - $cloudId = $this->cloudIdManager->getCloudId($sharedByFederatedId, $this->addressHandler->generateRemoteURL()); |
|
| 249 | - $sharedByFederatedId = $cloudId->getId(); |
|
| 250 | - } |
|
| 251 | - $ownerCloudId = $this->cloudIdManager->getCloudId($share->getShareOwner(), $this->addressHandler->generateRemoteURL()); |
|
| 252 | - $send = $this->notifications->sendRemoteShare( |
|
| 253 | - $token, |
|
| 254 | - $share->getSharedWith(), |
|
| 255 | - $share->getNode()->getName(), |
|
| 256 | - $shareId, |
|
| 257 | - $share->getShareOwner(), |
|
| 258 | - $ownerCloudId->getId(), |
|
| 259 | - $share->getSharedBy(), |
|
| 260 | - $sharedByFederatedId |
|
| 261 | - ); |
|
| 262 | - |
|
| 263 | - if ($send === false) { |
|
| 264 | - $failure = true; |
|
| 265 | - } |
|
| 266 | - } catch (\Exception $e) { |
|
| 267 | - $this->logger->logException($e, [ |
|
| 268 | - 'message' => 'Failed to notify remote server of federated share, removing share.', |
|
| 269 | - 'level' => \OCP\Util::ERROR, |
|
| 270 | - 'app' => 'federatedfilesharing', |
|
| 271 | - ]); |
|
| 272 | - $failure = true; |
|
| 273 | - } |
|
| 274 | - |
|
| 275 | - if($failure) { |
|
| 276 | - $this->removeShareFromTableById($shareId); |
|
| 277 | - $message_t = $this->l->t('Sharing %s failed, could not find %s, maybe the server is currently unreachable or uses a self-signed certificate.', |
|
| 278 | - [$share->getNode()->getName(), $share->getSharedWith()]); |
|
| 279 | - throw new \Exception($message_t); |
|
| 280 | - } |
|
| 281 | - |
|
| 282 | - return $shareId; |
|
| 283 | - |
|
| 284 | - } |
|
| 285 | - |
|
| 286 | - /** |
|
| 287 | - * @param string $shareWith |
|
| 288 | - * @param IShare $share |
|
| 289 | - * @param string $shareId internal share Id |
|
| 290 | - * @return array |
|
| 291 | - * @throws \Exception |
|
| 292 | - */ |
|
| 293 | - protected function askOwnerToReShare($shareWith, IShare $share, $shareId) { |
|
| 294 | - |
|
| 295 | - $remoteShare = $this->getShareFromExternalShareTable($share); |
|
| 296 | - $token = $remoteShare['share_token']; |
|
| 297 | - $remoteId = $remoteShare['remote_id']; |
|
| 298 | - $remote = $remoteShare['remote']; |
|
| 299 | - |
|
| 300 | - list($token, $remoteId) = $this->notifications->requestReShare( |
|
| 301 | - $token, |
|
| 302 | - $remoteId, |
|
| 303 | - $shareId, |
|
| 304 | - $remote, |
|
| 305 | - $shareWith, |
|
| 306 | - $share->getPermissions() |
|
| 307 | - ); |
|
| 308 | - |
|
| 309 | - return [$token, $remoteId]; |
|
| 310 | - } |
|
| 311 | - |
|
| 312 | - /** |
|
| 313 | - * get federated share from the share_external table but exclude mounted link shares |
|
| 314 | - * |
|
| 315 | - * @param IShare $share |
|
| 316 | - * @return array |
|
| 317 | - * @throws ShareNotFound |
|
| 318 | - */ |
|
| 319 | - protected function getShareFromExternalShareTable(IShare $share) { |
|
| 320 | - $query = $this->dbConnection->getQueryBuilder(); |
|
| 321 | - $query->select('*')->from($this->externalShareTable) |
|
| 322 | - ->where($query->expr()->eq('user', $query->createNamedParameter($share->getShareOwner()))) |
|
| 323 | - ->andWhere($query->expr()->eq('mountpoint', $query->createNamedParameter($share->getTarget()))); |
|
| 324 | - $result = $query->execute()->fetchAll(); |
|
| 325 | - |
|
| 326 | - if (isset($result[0]) && (int)$result[0]['remote_id'] > 0) { |
|
| 327 | - return $result[0]; |
|
| 328 | - } |
|
| 329 | - |
|
| 330 | - throw new ShareNotFound('share not found in share_external table'); |
|
| 331 | - } |
|
| 332 | - |
|
| 333 | - /** |
|
| 334 | - * add share to the database and return the ID |
|
| 335 | - * |
|
| 336 | - * @param int $itemSource |
|
| 337 | - * @param string $itemType |
|
| 338 | - * @param string $shareWith |
|
| 339 | - * @param string $sharedBy |
|
| 340 | - * @param string $uidOwner |
|
| 341 | - * @param int $permissions |
|
| 342 | - * @param string $token |
|
| 343 | - * @return int |
|
| 344 | - */ |
|
| 345 | - private function addShareToDB($itemSource, $itemType, $shareWith, $sharedBy, $uidOwner, $permissions, $token) { |
|
| 346 | - $qb = $this->dbConnection->getQueryBuilder(); |
|
| 347 | - $qb->insert('share') |
|
| 348 | - ->setValue('share_type', $qb->createNamedParameter(self::SHARE_TYPE_REMOTE)) |
|
| 349 | - ->setValue('item_type', $qb->createNamedParameter($itemType)) |
|
| 350 | - ->setValue('item_source', $qb->createNamedParameter($itemSource)) |
|
| 351 | - ->setValue('file_source', $qb->createNamedParameter($itemSource)) |
|
| 352 | - ->setValue('share_with', $qb->createNamedParameter($shareWith)) |
|
| 353 | - ->setValue('uid_owner', $qb->createNamedParameter($uidOwner)) |
|
| 354 | - ->setValue('uid_initiator', $qb->createNamedParameter($sharedBy)) |
|
| 355 | - ->setValue('permissions', $qb->createNamedParameter($permissions)) |
|
| 356 | - ->setValue('token', $qb->createNamedParameter($token)) |
|
| 357 | - ->setValue('stime', $qb->createNamedParameter(time())); |
|
| 358 | - |
|
| 359 | - /* |
|
| 163 | + $alreadyShared = $this->getSharedWith($shareWith, self::SHARE_TYPE_REMOTE, $share->getNode(), 1, 0); |
|
| 164 | + if (!empty($alreadyShared)) { |
|
| 165 | + $message = 'Sharing %s failed, because this item is already shared with %s'; |
|
| 166 | + $message_t = $this->l->t('Sharing %s failed, because this item is already shared with %s', array($share->getNode()->getName(), $shareWith)); |
|
| 167 | + $this->logger->debug(sprintf($message, $share->getNode()->getName(), $shareWith), ['app' => 'Federated File Sharing']); |
|
| 168 | + throw new \Exception($message_t); |
|
| 169 | + } |
|
| 170 | + |
|
| 171 | + |
|
| 172 | + // don't allow federated shares if source and target server are the same |
|
| 173 | + $cloudId = $this->cloudIdManager->resolveCloudId($shareWith); |
|
| 174 | + $currentServer = $this->addressHandler->generateRemoteURL(); |
|
| 175 | + $currentUser = $sharedBy; |
|
| 176 | + if ($this->addressHandler->compareAddresses($cloudId->getUser(), $cloudId->getRemote(), $currentUser, $currentServer)) { |
|
| 177 | + $message = 'Not allowed to create a federated share with the same user.'; |
|
| 178 | + $message_t = $this->l->t('Not allowed to create a federated share with the same user'); |
|
| 179 | + $this->logger->debug($message, ['app' => 'Federated File Sharing']); |
|
| 180 | + throw new \Exception($message_t); |
|
| 181 | + } |
|
| 182 | + |
|
| 183 | + |
|
| 184 | + $share->setSharedWith($cloudId->getId()); |
|
| 185 | + |
|
| 186 | + try { |
|
| 187 | + $remoteShare = $this->getShareFromExternalShareTable($share); |
|
| 188 | + } catch (ShareNotFound $e) { |
|
| 189 | + $remoteShare = null; |
|
| 190 | + } |
|
| 191 | + |
|
| 192 | + if ($remoteShare) { |
|
| 193 | + try { |
|
| 194 | + $ownerCloudId = $this->cloudIdManager->getCloudId($remoteShare['owner'], $remoteShare['remote']); |
|
| 195 | + $shareId = $this->addShareToDB($itemSource, $itemType, $shareWith, $sharedBy, $ownerCloudId->getId(), $permissions, 'tmp_token_' . time()); |
|
| 196 | + $share->setId($shareId); |
|
| 197 | + list($token, $remoteId) = $this->askOwnerToReShare($shareWith, $share, $shareId); |
|
| 198 | + // remote share was create successfully if we get a valid token as return |
|
| 199 | + $send = is_string($token) && $token !== ''; |
|
| 200 | + } catch (\Exception $e) { |
|
| 201 | + // fall back to old re-share behavior if the remote server |
|
| 202 | + // doesn't support flat re-shares (was introduced with Nextcloud 9.1) |
|
| 203 | + $this->removeShareFromTable($share); |
|
| 204 | + $shareId = $this->createFederatedShare($share); |
|
| 205 | + } |
|
| 206 | + if ($send) { |
|
| 207 | + $this->updateSuccessfulReshare($shareId, $token); |
|
| 208 | + $this->storeRemoteId($shareId, $remoteId); |
|
| 209 | + } else { |
|
| 210 | + $this->removeShareFromTable($share); |
|
| 211 | + $message_t = $this->l->t('File is already shared with %s', [$shareWith]); |
|
| 212 | + throw new \Exception($message_t); |
|
| 213 | + } |
|
| 214 | + |
|
| 215 | + } else { |
|
| 216 | + $shareId = $this->createFederatedShare($share); |
|
| 217 | + } |
|
| 218 | + |
|
| 219 | + $data = $this->getRawShare($shareId); |
|
| 220 | + return $this->createShareObject($data); |
|
| 221 | + } |
|
| 222 | + |
|
| 223 | + /** |
|
| 224 | + * create federated share and inform the recipient |
|
| 225 | + * |
|
| 226 | + * @param IShare $share |
|
| 227 | + * @return int |
|
| 228 | + * @throws ShareNotFound |
|
| 229 | + * @throws \Exception |
|
| 230 | + */ |
|
| 231 | + protected function createFederatedShare(IShare $share) { |
|
| 232 | + $token = $this->tokenHandler->generateToken(); |
|
| 233 | + $shareId = $this->addShareToDB( |
|
| 234 | + $share->getNodeId(), |
|
| 235 | + $share->getNodeType(), |
|
| 236 | + $share->getSharedWith(), |
|
| 237 | + $share->getSharedBy(), |
|
| 238 | + $share->getShareOwner(), |
|
| 239 | + $share->getPermissions(), |
|
| 240 | + $token |
|
| 241 | + ); |
|
| 242 | + |
|
| 243 | + $failure = false; |
|
| 244 | + |
|
| 245 | + try { |
|
| 246 | + $sharedByFederatedId = $share->getSharedBy(); |
|
| 247 | + if ($this->userManager->userExists($sharedByFederatedId)) { |
|
| 248 | + $cloudId = $this->cloudIdManager->getCloudId($sharedByFederatedId, $this->addressHandler->generateRemoteURL()); |
|
| 249 | + $sharedByFederatedId = $cloudId->getId(); |
|
| 250 | + } |
|
| 251 | + $ownerCloudId = $this->cloudIdManager->getCloudId($share->getShareOwner(), $this->addressHandler->generateRemoteURL()); |
|
| 252 | + $send = $this->notifications->sendRemoteShare( |
|
| 253 | + $token, |
|
| 254 | + $share->getSharedWith(), |
|
| 255 | + $share->getNode()->getName(), |
|
| 256 | + $shareId, |
|
| 257 | + $share->getShareOwner(), |
|
| 258 | + $ownerCloudId->getId(), |
|
| 259 | + $share->getSharedBy(), |
|
| 260 | + $sharedByFederatedId |
|
| 261 | + ); |
|
| 262 | + |
|
| 263 | + if ($send === false) { |
|
| 264 | + $failure = true; |
|
| 265 | + } |
|
| 266 | + } catch (\Exception $e) { |
|
| 267 | + $this->logger->logException($e, [ |
|
| 268 | + 'message' => 'Failed to notify remote server of federated share, removing share.', |
|
| 269 | + 'level' => \OCP\Util::ERROR, |
|
| 270 | + 'app' => 'federatedfilesharing', |
|
| 271 | + ]); |
|
| 272 | + $failure = true; |
|
| 273 | + } |
|
| 274 | + |
|
| 275 | + if($failure) { |
|
| 276 | + $this->removeShareFromTableById($shareId); |
|
| 277 | + $message_t = $this->l->t('Sharing %s failed, could not find %s, maybe the server is currently unreachable or uses a self-signed certificate.', |
|
| 278 | + [$share->getNode()->getName(), $share->getSharedWith()]); |
|
| 279 | + throw new \Exception($message_t); |
|
| 280 | + } |
|
| 281 | + |
|
| 282 | + return $shareId; |
|
| 283 | + |
|
| 284 | + } |
|
| 285 | + |
|
| 286 | + /** |
|
| 287 | + * @param string $shareWith |
|
| 288 | + * @param IShare $share |
|
| 289 | + * @param string $shareId internal share Id |
|
| 290 | + * @return array |
|
| 291 | + * @throws \Exception |
|
| 292 | + */ |
|
| 293 | + protected function askOwnerToReShare($shareWith, IShare $share, $shareId) { |
|
| 294 | + |
|
| 295 | + $remoteShare = $this->getShareFromExternalShareTable($share); |
|
| 296 | + $token = $remoteShare['share_token']; |
|
| 297 | + $remoteId = $remoteShare['remote_id']; |
|
| 298 | + $remote = $remoteShare['remote']; |
|
| 299 | + |
|
| 300 | + list($token, $remoteId) = $this->notifications->requestReShare( |
|
| 301 | + $token, |
|
| 302 | + $remoteId, |
|
| 303 | + $shareId, |
|
| 304 | + $remote, |
|
| 305 | + $shareWith, |
|
| 306 | + $share->getPermissions() |
|
| 307 | + ); |
|
| 308 | + |
|
| 309 | + return [$token, $remoteId]; |
|
| 310 | + } |
|
| 311 | + |
|
| 312 | + /** |
|
| 313 | + * get federated share from the share_external table but exclude mounted link shares |
|
| 314 | + * |
|
| 315 | + * @param IShare $share |
|
| 316 | + * @return array |
|
| 317 | + * @throws ShareNotFound |
|
| 318 | + */ |
|
| 319 | + protected function getShareFromExternalShareTable(IShare $share) { |
|
| 320 | + $query = $this->dbConnection->getQueryBuilder(); |
|
| 321 | + $query->select('*')->from($this->externalShareTable) |
|
| 322 | + ->where($query->expr()->eq('user', $query->createNamedParameter($share->getShareOwner()))) |
|
| 323 | + ->andWhere($query->expr()->eq('mountpoint', $query->createNamedParameter($share->getTarget()))); |
|
| 324 | + $result = $query->execute()->fetchAll(); |
|
| 325 | + |
|
| 326 | + if (isset($result[0]) && (int)$result[0]['remote_id'] > 0) { |
|
| 327 | + return $result[0]; |
|
| 328 | + } |
|
| 329 | + |
|
| 330 | + throw new ShareNotFound('share not found in share_external table'); |
|
| 331 | + } |
|
| 332 | + |
|
| 333 | + /** |
|
| 334 | + * add share to the database and return the ID |
|
| 335 | + * |
|
| 336 | + * @param int $itemSource |
|
| 337 | + * @param string $itemType |
|
| 338 | + * @param string $shareWith |
|
| 339 | + * @param string $sharedBy |
|
| 340 | + * @param string $uidOwner |
|
| 341 | + * @param int $permissions |
|
| 342 | + * @param string $token |
|
| 343 | + * @return int |
|
| 344 | + */ |
|
| 345 | + private function addShareToDB($itemSource, $itemType, $shareWith, $sharedBy, $uidOwner, $permissions, $token) { |
|
| 346 | + $qb = $this->dbConnection->getQueryBuilder(); |
|
| 347 | + $qb->insert('share') |
|
| 348 | + ->setValue('share_type', $qb->createNamedParameter(self::SHARE_TYPE_REMOTE)) |
|
| 349 | + ->setValue('item_type', $qb->createNamedParameter($itemType)) |
|
| 350 | + ->setValue('item_source', $qb->createNamedParameter($itemSource)) |
|
| 351 | + ->setValue('file_source', $qb->createNamedParameter($itemSource)) |
|
| 352 | + ->setValue('share_with', $qb->createNamedParameter($shareWith)) |
|
| 353 | + ->setValue('uid_owner', $qb->createNamedParameter($uidOwner)) |
|
| 354 | + ->setValue('uid_initiator', $qb->createNamedParameter($sharedBy)) |
|
| 355 | + ->setValue('permissions', $qb->createNamedParameter($permissions)) |
|
| 356 | + ->setValue('token', $qb->createNamedParameter($token)) |
|
| 357 | + ->setValue('stime', $qb->createNamedParameter(time())); |
|
| 358 | + |
|
| 359 | + /* |
|
| 360 | 360 | * Added to fix https://github.com/owncloud/core/issues/22215 |
| 361 | 361 | * Can be removed once we get rid of ajax/share.php |
| 362 | 362 | */ |
| 363 | - $qb->setValue('file_target', $qb->createNamedParameter('')); |
|
| 364 | - |
|
| 365 | - $qb->execute(); |
|
| 366 | - $id = $qb->getLastInsertId(); |
|
| 367 | - |
|
| 368 | - return (int)$id; |
|
| 369 | - } |
|
| 370 | - |
|
| 371 | - /** |
|
| 372 | - * Update a share |
|
| 373 | - * |
|
| 374 | - * @param IShare $share |
|
| 375 | - * @return IShare The share object |
|
| 376 | - */ |
|
| 377 | - public function update(IShare $share) { |
|
| 378 | - /* |
|
| 363 | + $qb->setValue('file_target', $qb->createNamedParameter('')); |
|
| 364 | + |
|
| 365 | + $qb->execute(); |
|
| 366 | + $id = $qb->getLastInsertId(); |
|
| 367 | + |
|
| 368 | + return (int)$id; |
|
| 369 | + } |
|
| 370 | + |
|
| 371 | + /** |
|
| 372 | + * Update a share |
|
| 373 | + * |
|
| 374 | + * @param IShare $share |
|
| 375 | + * @return IShare The share object |
|
| 376 | + */ |
|
| 377 | + public function update(IShare $share) { |
|
| 378 | + /* |
|
| 379 | 379 | * We allow updating the permissions of federated shares |
| 380 | 380 | */ |
| 381 | - $qb = $this->dbConnection->getQueryBuilder(); |
|
| 382 | - $qb->update('share') |
|
| 383 | - ->where($qb->expr()->eq('id', $qb->createNamedParameter($share->getId()))) |
|
| 384 | - ->set('permissions', $qb->createNamedParameter($share->getPermissions())) |
|
| 385 | - ->set('uid_owner', $qb->createNamedParameter($share->getShareOwner())) |
|
| 386 | - ->set('uid_initiator', $qb->createNamedParameter($share->getSharedBy())) |
|
| 387 | - ->execute(); |
|
| 388 | - |
|
| 389 | - // send the updated permission to the owner/initiator, if they are not the same |
|
| 390 | - if ($share->getShareOwner() !== $share->getSharedBy()) { |
|
| 391 | - $this->sendPermissionUpdate($share); |
|
| 392 | - } |
|
| 393 | - |
|
| 394 | - return $share; |
|
| 395 | - } |
|
| 396 | - |
|
| 397 | - /** |
|
| 398 | - * send the updated permission to the owner/initiator, if they are not the same |
|
| 399 | - * |
|
| 400 | - * @param IShare $share |
|
| 401 | - * @throws ShareNotFound |
|
| 402 | - * @throws \OC\HintException |
|
| 403 | - */ |
|
| 404 | - protected function sendPermissionUpdate(IShare $share) { |
|
| 405 | - $remoteId = $this->getRemoteId($share); |
|
| 406 | - // if the local user is the owner we send the permission change to the initiator |
|
| 407 | - if ($this->userManager->userExists($share->getShareOwner())) { |
|
| 408 | - list(, $remote) = $this->addressHandler->splitUserRemote($share->getSharedBy()); |
|
| 409 | - } else { // ... if not we send the permission change to the owner |
|
| 410 | - list(, $remote) = $this->addressHandler->splitUserRemote($share->getShareOwner()); |
|
| 411 | - } |
|
| 412 | - $this->notifications->sendPermissionChange($remote, $remoteId, $share->getToken(), $share->getPermissions()); |
|
| 413 | - } |
|
| 414 | - |
|
| 415 | - |
|
| 416 | - /** |
|
| 417 | - * update successful reShare with the correct token |
|
| 418 | - * |
|
| 419 | - * @param int $shareId |
|
| 420 | - * @param string $token |
|
| 421 | - */ |
|
| 422 | - protected function updateSuccessfulReShare($shareId, $token) { |
|
| 423 | - $query = $this->dbConnection->getQueryBuilder(); |
|
| 424 | - $query->update('share') |
|
| 425 | - ->where($query->expr()->eq('id', $query->createNamedParameter($shareId))) |
|
| 426 | - ->set('token', $query->createNamedParameter($token)) |
|
| 427 | - ->execute(); |
|
| 428 | - } |
|
| 429 | - |
|
| 430 | - /** |
|
| 431 | - * store remote ID in federated reShare table |
|
| 432 | - * |
|
| 433 | - * @param $shareId |
|
| 434 | - * @param $remoteId |
|
| 435 | - */ |
|
| 436 | - public function storeRemoteId($shareId, $remoteId) { |
|
| 437 | - $query = $this->dbConnection->getQueryBuilder(); |
|
| 438 | - $query->insert('federated_reshares') |
|
| 439 | - ->values( |
|
| 440 | - [ |
|
| 441 | - 'share_id' => $query->createNamedParameter($shareId), |
|
| 442 | - 'remote_id' => $query->createNamedParameter($remoteId), |
|
| 443 | - ] |
|
| 444 | - ); |
|
| 445 | - $query->execute(); |
|
| 446 | - } |
|
| 447 | - |
|
| 448 | - /** |
|
| 449 | - * get share ID on remote server for federated re-shares |
|
| 450 | - * |
|
| 451 | - * @param IShare $share |
|
| 452 | - * @return int |
|
| 453 | - * @throws ShareNotFound |
|
| 454 | - */ |
|
| 455 | - public function getRemoteId(IShare $share) { |
|
| 456 | - $query = $this->dbConnection->getQueryBuilder(); |
|
| 457 | - $query->select('remote_id')->from('federated_reshares') |
|
| 458 | - ->where($query->expr()->eq('share_id', $query->createNamedParameter((int)$share->getId()))); |
|
| 459 | - $data = $query->execute()->fetch(); |
|
| 460 | - |
|
| 461 | - if (!is_array($data) || !isset($data['remote_id'])) { |
|
| 462 | - throw new ShareNotFound(); |
|
| 463 | - } |
|
| 464 | - |
|
| 465 | - return (int)$data['remote_id']; |
|
| 466 | - } |
|
| 467 | - |
|
| 468 | - /** |
|
| 469 | - * @inheritdoc |
|
| 470 | - */ |
|
| 471 | - public function move(IShare $share, $recipient) { |
|
| 472 | - /* |
|
| 381 | + $qb = $this->dbConnection->getQueryBuilder(); |
|
| 382 | + $qb->update('share') |
|
| 383 | + ->where($qb->expr()->eq('id', $qb->createNamedParameter($share->getId()))) |
|
| 384 | + ->set('permissions', $qb->createNamedParameter($share->getPermissions())) |
|
| 385 | + ->set('uid_owner', $qb->createNamedParameter($share->getShareOwner())) |
|
| 386 | + ->set('uid_initiator', $qb->createNamedParameter($share->getSharedBy())) |
|
| 387 | + ->execute(); |
|
| 388 | + |
|
| 389 | + // send the updated permission to the owner/initiator, if they are not the same |
|
| 390 | + if ($share->getShareOwner() !== $share->getSharedBy()) { |
|
| 391 | + $this->sendPermissionUpdate($share); |
|
| 392 | + } |
|
| 393 | + |
|
| 394 | + return $share; |
|
| 395 | + } |
|
| 396 | + |
|
| 397 | + /** |
|
| 398 | + * send the updated permission to the owner/initiator, if they are not the same |
|
| 399 | + * |
|
| 400 | + * @param IShare $share |
|
| 401 | + * @throws ShareNotFound |
|
| 402 | + * @throws \OC\HintException |
|
| 403 | + */ |
|
| 404 | + protected function sendPermissionUpdate(IShare $share) { |
|
| 405 | + $remoteId = $this->getRemoteId($share); |
|
| 406 | + // if the local user is the owner we send the permission change to the initiator |
|
| 407 | + if ($this->userManager->userExists($share->getShareOwner())) { |
|
| 408 | + list(, $remote) = $this->addressHandler->splitUserRemote($share->getSharedBy()); |
|
| 409 | + } else { // ... if not we send the permission change to the owner |
|
| 410 | + list(, $remote) = $this->addressHandler->splitUserRemote($share->getShareOwner()); |
|
| 411 | + } |
|
| 412 | + $this->notifications->sendPermissionChange($remote, $remoteId, $share->getToken(), $share->getPermissions()); |
|
| 413 | + } |
|
| 414 | + |
|
| 415 | + |
|
| 416 | + /** |
|
| 417 | + * update successful reShare with the correct token |
|
| 418 | + * |
|
| 419 | + * @param int $shareId |
|
| 420 | + * @param string $token |
|
| 421 | + */ |
|
| 422 | + protected function updateSuccessfulReShare($shareId, $token) { |
|
| 423 | + $query = $this->dbConnection->getQueryBuilder(); |
|
| 424 | + $query->update('share') |
|
| 425 | + ->where($query->expr()->eq('id', $query->createNamedParameter($shareId))) |
|
| 426 | + ->set('token', $query->createNamedParameter($token)) |
|
| 427 | + ->execute(); |
|
| 428 | + } |
|
| 429 | + |
|
| 430 | + /** |
|
| 431 | + * store remote ID in federated reShare table |
|
| 432 | + * |
|
| 433 | + * @param $shareId |
|
| 434 | + * @param $remoteId |
|
| 435 | + */ |
|
| 436 | + public function storeRemoteId($shareId, $remoteId) { |
|
| 437 | + $query = $this->dbConnection->getQueryBuilder(); |
|
| 438 | + $query->insert('federated_reshares') |
|
| 439 | + ->values( |
|
| 440 | + [ |
|
| 441 | + 'share_id' => $query->createNamedParameter($shareId), |
|
| 442 | + 'remote_id' => $query->createNamedParameter($remoteId), |
|
| 443 | + ] |
|
| 444 | + ); |
|
| 445 | + $query->execute(); |
|
| 446 | + } |
|
| 447 | + |
|
| 448 | + /** |
|
| 449 | + * get share ID on remote server for federated re-shares |
|
| 450 | + * |
|
| 451 | + * @param IShare $share |
|
| 452 | + * @return int |
|
| 453 | + * @throws ShareNotFound |
|
| 454 | + */ |
|
| 455 | + public function getRemoteId(IShare $share) { |
|
| 456 | + $query = $this->dbConnection->getQueryBuilder(); |
|
| 457 | + $query->select('remote_id')->from('federated_reshares') |
|
| 458 | + ->where($query->expr()->eq('share_id', $query->createNamedParameter((int)$share->getId()))); |
|
| 459 | + $data = $query->execute()->fetch(); |
|
| 460 | + |
|
| 461 | + if (!is_array($data) || !isset($data['remote_id'])) { |
|
| 462 | + throw new ShareNotFound(); |
|
| 463 | + } |
|
| 464 | + |
|
| 465 | + return (int)$data['remote_id']; |
|
| 466 | + } |
|
| 467 | + |
|
| 468 | + /** |
|
| 469 | + * @inheritdoc |
|
| 470 | + */ |
|
| 471 | + public function move(IShare $share, $recipient) { |
|
| 472 | + /* |
|
| 473 | 473 | * This function does nothing yet as it is just for outgoing |
| 474 | 474 | * federated shares. |
| 475 | 475 | */ |
| 476 | - return $share; |
|
| 477 | - } |
|
| 478 | - |
|
| 479 | - /** |
|
| 480 | - * Get all children of this share |
|
| 481 | - * |
|
| 482 | - * @param IShare $parent |
|
| 483 | - * @return IShare[] |
|
| 484 | - */ |
|
| 485 | - public function getChildren(IShare $parent) { |
|
| 486 | - $children = []; |
|
| 487 | - |
|
| 488 | - $qb = $this->dbConnection->getQueryBuilder(); |
|
| 489 | - $qb->select('*') |
|
| 490 | - ->from('share') |
|
| 491 | - ->where($qb->expr()->eq('parent', $qb->createNamedParameter($parent->getId()))) |
|
| 492 | - ->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter(self::SHARE_TYPE_REMOTE))) |
|
| 493 | - ->orderBy('id'); |
|
| 494 | - |
|
| 495 | - $cursor = $qb->execute(); |
|
| 496 | - while($data = $cursor->fetch()) { |
|
| 497 | - $children[] = $this->createShareObject($data); |
|
| 498 | - } |
|
| 499 | - $cursor->closeCursor(); |
|
| 500 | - |
|
| 501 | - return $children; |
|
| 502 | - } |
|
| 503 | - |
|
| 504 | - /** |
|
| 505 | - * Delete a share (owner unShares the file) |
|
| 506 | - * |
|
| 507 | - * @param IShare $share |
|
| 508 | - */ |
|
| 509 | - public function delete(IShare $share) { |
|
| 510 | - |
|
| 511 | - list(, $remote) = $this->addressHandler->splitUserRemote($share->getSharedWith()); |
|
| 512 | - |
|
| 513 | - $isOwner = false; |
|
| 514 | - |
|
| 515 | - $this->removeShareFromTable($share); |
|
| 516 | - |
|
| 517 | - // if the local user is the owner we can send the unShare request directly... |
|
| 518 | - if ($this->userManager->userExists($share->getShareOwner())) { |
|
| 519 | - $this->notifications->sendRemoteUnShare($remote, $share->getId(), $share->getToken()); |
|
| 520 | - $this->revokeShare($share, true); |
|
| 521 | - $isOwner = true; |
|
| 522 | - } else { // ... if not we need to correct ID for the unShare request |
|
| 523 | - $remoteId = $this->getRemoteId($share); |
|
| 524 | - $this->notifications->sendRemoteUnShare($remote, $remoteId, $share->getToken()); |
|
| 525 | - $this->revokeShare($share, false); |
|
| 526 | - } |
|
| 527 | - |
|
| 528 | - // send revoke notification to the other user, if initiator and owner are not the same user |
|
| 529 | - if ($share->getShareOwner() !== $share->getSharedBy()) { |
|
| 530 | - $remoteId = $this->getRemoteId($share); |
|
| 531 | - if ($isOwner) { |
|
| 532 | - list(, $remote) = $this->addressHandler->splitUserRemote($share->getSharedBy()); |
|
| 533 | - } else { |
|
| 534 | - list(, $remote) = $this->addressHandler->splitUserRemote($share->getShareOwner()); |
|
| 535 | - } |
|
| 536 | - $this->notifications->sendRevokeShare($remote, $remoteId, $share->getToken()); |
|
| 537 | - } |
|
| 538 | - } |
|
| 539 | - |
|
| 540 | - /** |
|
| 541 | - * in case of a re-share we need to send the other use (initiator or owner) |
|
| 542 | - * a message that the file was unshared |
|
| 543 | - * |
|
| 544 | - * @param IShare $share |
|
| 545 | - * @param bool $isOwner the user can either be the owner or the user who re-sahred it |
|
| 546 | - * @throws ShareNotFound |
|
| 547 | - * @throws \OC\HintException |
|
| 548 | - */ |
|
| 549 | - protected function revokeShare($share, $isOwner) { |
|
| 550 | - // also send a unShare request to the initiator, if this is a different user than the owner |
|
| 551 | - if ($share->getShareOwner() !== $share->getSharedBy()) { |
|
| 552 | - if ($isOwner) { |
|
| 553 | - list(, $remote) = $this->addressHandler->splitUserRemote($share->getSharedBy()); |
|
| 554 | - } else { |
|
| 555 | - list(, $remote) = $this->addressHandler->splitUserRemote($share->getShareOwner()); |
|
| 556 | - } |
|
| 557 | - $remoteId = $this->getRemoteId($share); |
|
| 558 | - $this->notifications->sendRevokeShare($remote, $remoteId, $share->getToken()); |
|
| 559 | - } |
|
| 560 | - } |
|
| 561 | - |
|
| 562 | - /** |
|
| 563 | - * remove share from table |
|
| 564 | - * |
|
| 565 | - * @param IShare $share |
|
| 566 | - */ |
|
| 567 | - public function removeShareFromTable(IShare $share) { |
|
| 568 | - $this->removeShareFromTableById($share->getId()); |
|
| 569 | - } |
|
| 570 | - |
|
| 571 | - /** |
|
| 572 | - * remove share from table |
|
| 573 | - * |
|
| 574 | - * @param string $shareId |
|
| 575 | - */ |
|
| 576 | - private function removeShareFromTableById($shareId) { |
|
| 577 | - $qb = $this->dbConnection->getQueryBuilder(); |
|
| 578 | - $qb->delete('share') |
|
| 579 | - ->where($qb->expr()->eq('id', $qb->createNamedParameter($shareId))); |
|
| 580 | - $qb->execute(); |
|
| 581 | - |
|
| 582 | - $qb->delete('federated_reshares') |
|
| 583 | - ->where($qb->expr()->eq('share_id', $qb->createNamedParameter($shareId))); |
|
| 584 | - $qb->execute(); |
|
| 585 | - } |
|
| 586 | - |
|
| 587 | - /** |
|
| 588 | - * @inheritdoc |
|
| 589 | - */ |
|
| 590 | - public function deleteFromSelf(IShare $share, $recipient) { |
|
| 591 | - // nothing to do here. Technically deleteFromSelf in the context of federated |
|
| 592 | - // shares is a umount of a external storage. This is handled here |
|
| 593 | - // apps/files_sharing/lib/external/manager.php |
|
| 594 | - // TODO move this code over to this app |
|
| 595 | - } |
|
| 596 | - |
|
| 597 | - |
|
| 598 | - public function getSharesInFolder($userId, Folder $node, $reshares) { |
|
| 599 | - $qb = $this->dbConnection->getQueryBuilder(); |
|
| 600 | - $qb->select('*') |
|
| 601 | - ->from('share', 's') |
|
| 602 | - ->andWhere($qb->expr()->orX( |
|
| 603 | - $qb->expr()->eq('item_type', $qb->createNamedParameter('file')), |
|
| 604 | - $qb->expr()->eq('item_type', $qb->createNamedParameter('folder')) |
|
| 605 | - )) |
|
| 606 | - ->andWhere( |
|
| 607 | - $qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_REMOTE)) |
|
| 608 | - ); |
|
| 609 | - |
|
| 610 | - /** |
|
| 611 | - * Reshares for this user are shares where they are the owner. |
|
| 612 | - */ |
|
| 613 | - if ($reshares === false) { |
|
| 614 | - $qb->andWhere($qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId))); |
|
| 615 | - } else { |
|
| 616 | - $qb->andWhere( |
|
| 617 | - $qb->expr()->orX( |
|
| 618 | - $qb->expr()->eq('uid_owner', $qb->createNamedParameter($userId)), |
|
| 619 | - $qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId)) |
|
| 620 | - ) |
|
| 621 | - ); |
|
| 622 | - } |
|
| 623 | - |
|
| 624 | - $qb->innerJoin('s', 'filecache' ,'f', $qb->expr()->eq('s.file_source', 'f.fileid')); |
|
| 625 | - $qb->andWhere($qb->expr()->eq('f.parent', $qb->createNamedParameter($node->getId()))); |
|
| 626 | - |
|
| 627 | - $qb->orderBy('id'); |
|
| 628 | - |
|
| 629 | - $cursor = $qb->execute(); |
|
| 630 | - $shares = []; |
|
| 631 | - while ($data = $cursor->fetch()) { |
|
| 632 | - $shares[$data['fileid']][] = $this->createShareObject($data); |
|
| 633 | - } |
|
| 634 | - $cursor->closeCursor(); |
|
| 635 | - |
|
| 636 | - return $shares; |
|
| 637 | - } |
|
| 638 | - |
|
| 639 | - /** |
|
| 640 | - * @inheritdoc |
|
| 641 | - */ |
|
| 642 | - public function getSharesBy($userId, $shareType, $node, $reshares, $limit, $offset) { |
|
| 643 | - $qb = $this->dbConnection->getQueryBuilder(); |
|
| 644 | - $qb->select('*') |
|
| 645 | - ->from('share'); |
|
| 646 | - |
|
| 647 | - $qb->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter(self::SHARE_TYPE_REMOTE))); |
|
| 648 | - |
|
| 649 | - /** |
|
| 650 | - * Reshares for this user are shares where they are the owner. |
|
| 651 | - */ |
|
| 652 | - if ($reshares === false) { |
|
| 653 | - //Special case for old shares created via the web UI |
|
| 654 | - $or1 = $qb->expr()->andX( |
|
| 655 | - $qb->expr()->eq('uid_owner', $qb->createNamedParameter($userId)), |
|
| 656 | - $qb->expr()->isNull('uid_initiator') |
|
| 657 | - ); |
|
| 658 | - |
|
| 659 | - $qb->andWhere( |
|
| 660 | - $qb->expr()->orX( |
|
| 661 | - $qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId)), |
|
| 662 | - $or1 |
|
| 663 | - ) |
|
| 664 | - ); |
|
| 665 | - } else { |
|
| 666 | - $qb->andWhere( |
|
| 667 | - $qb->expr()->orX( |
|
| 668 | - $qb->expr()->eq('uid_owner', $qb->createNamedParameter($userId)), |
|
| 669 | - $qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId)) |
|
| 670 | - ) |
|
| 671 | - ); |
|
| 672 | - } |
|
| 673 | - |
|
| 674 | - if ($node !== null) { |
|
| 675 | - $qb->andWhere($qb->expr()->eq('file_source', $qb->createNamedParameter($node->getId()))); |
|
| 676 | - } |
|
| 677 | - |
|
| 678 | - if ($limit !== -1) { |
|
| 679 | - $qb->setMaxResults($limit); |
|
| 680 | - } |
|
| 681 | - |
|
| 682 | - $qb->setFirstResult($offset); |
|
| 683 | - $qb->orderBy('id'); |
|
| 684 | - |
|
| 685 | - $cursor = $qb->execute(); |
|
| 686 | - $shares = []; |
|
| 687 | - while($data = $cursor->fetch()) { |
|
| 688 | - $shares[] = $this->createShareObject($data); |
|
| 689 | - } |
|
| 690 | - $cursor->closeCursor(); |
|
| 691 | - |
|
| 692 | - return $shares; |
|
| 693 | - } |
|
| 694 | - |
|
| 695 | - /** |
|
| 696 | - * @inheritdoc |
|
| 697 | - */ |
|
| 698 | - public function getShareById($id, $recipientId = null) { |
|
| 699 | - $qb = $this->dbConnection->getQueryBuilder(); |
|
| 700 | - |
|
| 701 | - $qb->select('*') |
|
| 702 | - ->from('share') |
|
| 703 | - ->where($qb->expr()->eq('id', $qb->createNamedParameter($id))) |
|
| 704 | - ->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter(self::SHARE_TYPE_REMOTE))); |
|
| 705 | - |
|
| 706 | - $cursor = $qb->execute(); |
|
| 707 | - $data = $cursor->fetch(); |
|
| 708 | - $cursor->closeCursor(); |
|
| 709 | - |
|
| 710 | - if ($data === false) { |
|
| 711 | - throw new ShareNotFound(); |
|
| 712 | - } |
|
| 713 | - |
|
| 714 | - try { |
|
| 715 | - $share = $this->createShareObject($data); |
|
| 716 | - } catch (InvalidShare $e) { |
|
| 717 | - throw new ShareNotFound(); |
|
| 718 | - } |
|
| 719 | - |
|
| 720 | - return $share; |
|
| 721 | - } |
|
| 722 | - |
|
| 723 | - /** |
|
| 724 | - * Get shares for a given path |
|
| 725 | - * |
|
| 726 | - * @param \OCP\Files\Node $path |
|
| 727 | - * @return IShare[] |
|
| 728 | - */ |
|
| 729 | - public function getSharesByPath(Node $path) { |
|
| 730 | - $qb = $this->dbConnection->getQueryBuilder(); |
|
| 731 | - |
|
| 732 | - $cursor = $qb->select('*') |
|
| 733 | - ->from('share') |
|
| 734 | - ->andWhere($qb->expr()->eq('file_source', $qb->createNamedParameter($path->getId()))) |
|
| 735 | - ->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter(self::SHARE_TYPE_REMOTE))) |
|
| 736 | - ->execute(); |
|
| 737 | - |
|
| 738 | - $shares = []; |
|
| 739 | - while($data = $cursor->fetch()) { |
|
| 740 | - $shares[] = $this->createShareObject($data); |
|
| 741 | - } |
|
| 742 | - $cursor->closeCursor(); |
|
| 743 | - |
|
| 744 | - return $shares; |
|
| 745 | - } |
|
| 746 | - |
|
| 747 | - /** |
|
| 748 | - * @inheritdoc |
|
| 749 | - */ |
|
| 750 | - public function getSharedWith($userId, $shareType, $node, $limit, $offset) { |
|
| 751 | - /** @var IShare[] $shares */ |
|
| 752 | - $shares = []; |
|
| 753 | - |
|
| 754 | - //Get shares directly with this user |
|
| 755 | - $qb = $this->dbConnection->getQueryBuilder(); |
|
| 756 | - $qb->select('*') |
|
| 757 | - ->from('share'); |
|
| 758 | - |
|
| 759 | - // Order by id |
|
| 760 | - $qb->orderBy('id'); |
|
| 761 | - |
|
| 762 | - // Set limit and offset |
|
| 763 | - if ($limit !== -1) { |
|
| 764 | - $qb->setMaxResults($limit); |
|
| 765 | - } |
|
| 766 | - $qb->setFirstResult($offset); |
|
| 767 | - |
|
| 768 | - $qb->where($qb->expr()->eq('share_type', $qb->createNamedParameter(self::SHARE_TYPE_REMOTE))); |
|
| 769 | - $qb->andWhere($qb->expr()->eq('share_with', $qb->createNamedParameter($userId))); |
|
| 770 | - |
|
| 771 | - // Filter by node if provided |
|
| 772 | - if ($node !== null) { |
|
| 773 | - $qb->andWhere($qb->expr()->eq('file_source', $qb->createNamedParameter($node->getId()))); |
|
| 774 | - } |
|
| 775 | - |
|
| 776 | - $cursor = $qb->execute(); |
|
| 777 | - |
|
| 778 | - while($data = $cursor->fetch()) { |
|
| 779 | - $shares[] = $this->createShareObject($data); |
|
| 780 | - } |
|
| 781 | - $cursor->closeCursor(); |
|
| 782 | - |
|
| 783 | - |
|
| 784 | - return $shares; |
|
| 785 | - } |
|
| 786 | - |
|
| 787 | - /** |
|
| 788 | - * Get a share by token |
|
| 789 | - * |
|
| 790 | - * @param string $token |
|
| 791 | - * @return IShare |
|
| 792 | - * @throws ShareNotFound |
|
| 793 | - */ |
|
| 794 | - public function getShareByToken($token) { |
|
| 795 | - $qb = $this->dbConnection->getQueryBuilder(); |
|
| 796 | - |
|
| 797 | - $cursor = $qb->select('*') |
|
| 798 | - ->from('share') |
|
| 799 | - ->where($qb->expr()->eq('share_type', $qb->createNamedParameter(self::SHARE_TYPE_REMOTE))) |
|
| 800 | - ->andWhere($qb->expr()->eq('token', $qb->createNamedParameter($token))) |
|
| 801 | - ->execute(); |
|
| 802 | - |
|
| 803 | - $data = $cursor->fetch(); |
|
| 804 | - |
|
| 805 | - if ($data === false) { |
|
| 806 | - throw new ShareNotFound('Share not found', $this->l->t('Could not find share')); |
|
| 807 | - } |
|
| 808 | - |
|
| 809 | - try { |
|
| 810 | - $share = $this->createShareObject($data); |
|
| 811 | - } catch (InvalidShare $e) { |
|
| 812 | - throw new ShareNotFound('Share not found', $this->l->t('Could not find share')); |
|
| 813 | - } |
|
| 814 | - |
|
| 815 | - return $share; |
|
| 816 | - } |
|
| 817 | - |
|
| 818 | - /** |
|
| 819 | - * get database row of a give share |
|
| 820 | - * |
|
| 821 | - * @param $id |
|
| 822 | - * @return array |
|
| 823 | - * @throws ShareNotFound |
|
| 824 | - */ |
|
| 825 | - private function getRawShare($id) { |
|
| 826 | - |
|
| 827 | - // Now fetch the inserted share and create a complete share object |
|
| 828 | - $qb = $this->dbConnection->getQueryBuilder(); |
|
| 829 | - $qb->select('*') |
|
| 830 | - ->from('share') |
|
| 831 | - ->where($qb->expr()->eq('id', $qb->createNamedParameter($id))); |
|
| 832 | - |
|
| 833 | - $cursor = $qb->execute(); |
|
| 834 | - $data = $cursor->fetch(); |
|
| 835 | - $cursor->closeCursor(); |
|
| 836 | - |
|
| 837 | - if ($data === false) { |
|
| 838 | - throw new ShareNotFound; |
|
| 839 | - } |
|
| 840 | - |
|
| 841 | - return $data; |
|
| 842 | - } |
|
| 843 | - |
|
| 844 | - /** |
|
| 845 | - * Create a share object from an database row |
|
| 846 | - * |
|
| 847 | - * @param array $data |
|
| 848 | - * @return IShare |
|
| 849 | - * @throws InvalidShare |
|
| 850 | - * @throws ShareNotFound |
|
| 851 | - */ |
|
| 852 | - private function createShareObject($data) { |
|
| 853 | - |
|
| 854 | - $share = new Share($this->rootFolder, $this->userManager); |
|
| 855 | - $share->setId((int)$data['id']) |
|
| 856 | - ->setShareType((int)$data['share_type']) |
|
| 857 | - ->setPermissions((int)$data['permissions']) |
|
| 858 | - ->setTarget($data['file_target']) |
|
| 859 | - ->setMailSend((bool)$data['mail_send']) |
|
| 860 | - ->setToken($data['token']); |
|
| 861 | - |
|
| 862 | - $shareTime = new \DateTime(); |
|
| 863 | - $shareTime->setTimestamp((int)$data['stime']); |
|
| 864 | - $share->setShareTime($shareTime); |
|
| 865 | - $share->setSharedWith($data['share_with']); |
|
| 866 | - |
|
| 867 | - if ($data['uid_initiator'] !== null) { |
|
| 868 | - $share->setShareOwner($data['uid_owner']); |
|
| 869 | - $share->setSharedBy($data['uid_initiator']); |
|
| 870 | - } else { |
|
| 871 | - //OLD SHARE |
|
| 872 | - $share->setSharedBy($data['uid_owner']); |
|
| 873 | - $path = $this->getNode($share->getSharedBy(), (int)$data['file_source']); |
|
| 874 | - |
|
| 875 | - $owner = $path->getOwner(); |
|
| 876 | - $share->setShareOwner($owner->getUID()); |
|
| 877 | - } |
|
| 878 | - |
|
| 879 | - $share->setNodeId((int)$data['file_source']); |
|
| 880 | - $share->setNodeType($data['item_type']); |
|
| 881 | - |
|
| 882 | - $share->setProviderId($this->identifier()); |
|
| 883 | - |
|
| 884 | - return $share; |
|
| 885 | - } |
|
| 886 | - |
|
| 887 | - /** |
|
| 888 | - * Get the node with file $id for $user |
|
| 889 | - * |
|
| 890 | - * @param string $userId |
|
| 891 | - * @param int $id |
|
| 892 | - * @return \OCP\Files\File|\OCP\Files\Folder |
|
| 893 | - * @throws InvalidShare |
|
| 894 | - */ |
|
| 895 | - private function getNode($userId, $id) { |
|
| 896 | - try { |
|
| 897 | - $userFolder = $this->rootFolder->getUserFolder($userId); |
|
| 898 | - } catch (NotFoundException $e) { |
|
| 899 | - throw new InvalidShare(); |
|
| 900 | - } |
|
| 901 | - |
|
| 902 | - $nodes = $userFolder->getById($id); |
|
| 903 | - |
|
| 904 | - if (empty($nodes)) { |
|
| 905 | - throw new InvalidShare(); |
|
| 906 | - } |
|
| 907 | - |
|
| 908 | - return $nodes[0]; |
|
| 909 | - } |
|
| 910 | - |
|
| 911 | - /** |
|
| 912 | - * A user is deleted from the system |
|
| 913 | - * So clean up the relevant shares. |
|
| 914 | - * |
|
| 915 | - * @param string $uid |
|
| 916 | - * @param int $shareType |
|
| 917 | - */ |
|
| 918 | - public function userDeleted($uid, $shareType) { |
|
| 919 | - //TODO: probabaly a good idea to send unshare info to remote servers |
|
| 920 | - |
|
| 921 | - $qb = $this->dbConnection->getQueryBuilder(); |
|
| 922 | - |
|
| 923 | - $qb->delete('share') |
|
| 924 | - ->where($qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_REMOTE))) |
|
| 925 | - ->andWhere($qb->expr()->eq('uid_owner', $qb->createNamedParameter($uid))) |
|
| 926 | - ->execute(); |
|
| 927 | - } |
|
| 928 | - |
|
| 929 | - /** |
|
| 930 | - * This provider does not handle groups |
|
| 931 | - * |
|
| 932 | - * @param string $gid |
|
| 933 | - */ |
|
| 934 | - public function groupDeleted($gid) { |
|
| 935 | - // We don't handle groups here |
|
| 936 | - } |
|
| 937 | - |
|
| 938 | - /** |
|
| 939 | - * This provider does not handle groups |
|
| 940 | - * |
|
| 941 | - * @param string $uid |
|
| 942 | - * @param string $gid |
|
| 943 | - */ |
|
| 944 | - public function userDeletedFromGroup($uid, $gid) { |
|
| 945 | - // We don't handle groups here |
|
| 946 | - } |
|
| 947 | - |
|
| 948 | - /** |
|
| 949 | - * check if users from other Nextcloud instances are allowed to mount public links share by this instance |
|
| 950 | - * |
|
| 951 | - * @return bool |
|
| 952 | - */ |
|
| 953 | - public function isOutgoingServer2serverShareEnabled() { |
|
| 954 | - if ($this->gsConfig->onlyInternalFederation()) { |
|
| 955 | - return false; |
|
| 956 | - } |
|
| 957 | - $result = $this->config->getAppValue('files_sharing', 'outgoing_server2server_share_enabled', 'yes'); |
|
| 958 | - return ($result === 'yes'); |
|
| 959 | - } |
|
| 960 | - |
|
| 961 | - /** |
|
| 962 | - * check if users are allowed to mount public links from other Nextclouds |
|
| 963 | - * |
|
| 964 | - * @return bool |
|
| 965 | - */ |
|
| 966 | - public function isIncomingServer2serverShareEnabled() { |
|
| 967 | - if ($this->gsConfig->onlyInternalFederation()) { |
|
| 968 | - return false; |
|
| 969 | - } |
|
| 970 | - $result = $this->config->getAppValue('files_sharing', 'incoming_server2server_share_enabled', 'yes'); |
|
| 971 | - return ($result === 'yes'); |
|
| 972 | - } |
|
| 973 | - |
|
| 974 | - /** |
|
| 975 | - * Check if querying sharees on the lookup server is enabled |
|
| 976 | - * |
|
| 977 | - * @return bool |
|
| 978 | - */ |
|
| 979 | - public function isLookupServerQueriesEnabled() { |
|
| 980 | - // in a global scale setup we should always query the lookup server |
|
| 981 | - if ($this->gsConfig->isGlobalScaleEnabled()) { |
|
| 982 | - return true; |
|
| 983 | - } |
|
| 984 | - $result = $this->config->getAppValue('files_sharing', 'lookupServerEnabled', 'no'); |
|
| 985 | - return ($result === 'yes'); |
|
| 986 | - } |
|
| 987 | - |
|
| 988 | - |
|
| 989 | - /** |
|
| 990 | - * Check if it is allowed to publish user specific data to the lookup server |
|
| 991 | - * |
|
| 992 | - * @return bool |
|
| 993 | - */ |
|
| 994 | - public function isLookupServerUploadEnabled() { |
|
| 995 | - // in a global scale setup the admin is responsible to keep the lookup server up-to-date |
|
| 996 | - if ($this->gsConfig->isGlobalScaleEnabled()) { |
|
| 997 | - return false; |
|
| 998 | - } |
|
| 999 | - $result = $this->config->getAppValue('files_sharing', 'lookupServerUploadEnabled', 'yes'); |
|
| 1000 | - return ($result === 'yes'); |
|
| 1001 | - } |
|
| 1002 | - |
|
| 1003 | - /** |
|
| 1004 | - * @inheritdoc |
|
| 1005 | - */ |
|
| 1006 | - public function getAccessList($nodes, $currentAccess) { |
|
| 1007 | - $ids = []; |
|
| 1008 | - foreach ($nodes as $node) { |
|
| 1009 | - $ids[] = $node->getId(); |
|
| 1010 | - } |
|
| 1011 | - |
|
| 1012 | - $qb = $this->dbConnection->getQueryBuilder(); |
|
| 1013 | - $qb->select('share_with', 'token', 'file_source') |
|
| 1014 | - ->from('share') |
|
| 1015 | - ->where($qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_REMOTE))) |
|
| 1016 | - ->andWhere($qb->expr()->in('file_source', $qb->createNamedParameter($ids, IQueryBuilder::PARAM_INT_ARRAY))) |
|
| 1017 | - ->andWhere($qb->expr()->orX( |
|
| 1018 | - $qb->expr()->eq('item_type', $qb->createNamedParameter('file')), |
|
| 1019 | - $qb->expr()->eq('item_type', $qb->createNamedParameter('folder')) |
|
| 1020 | - )); |
|
| 1021 | - $cursor = $qb->execute(); |
|
| 1022 | - |
|
| 1023 | - if ($currentAccess === false) { |
|
| 1024 | - $remote = $cursor->fetch() !== false; |
|
| 1025 | - $cursor->closeCursor(); |
|
| 1026 | - |
|
| 1027 | - return ['remote' => $remote]; |
|
| 1028 | - } |
|
| 1029 | - |
|
| 1030 | - $remote = []; |
|
| 1031 | - while ($row = $cursor->fetch()) { |
|
| 1032 | - $remote[$row['share_with']] = [ |
|
| 1033 | - 'node_id' => $row['file_source'], |
|
| 1034 | - 'token' => $row['token'], |
|
| 1035 | - ]; |
|
| 1036 | - } |
|
| 1037 | - $cursor->closeCursor(); |
|
| 1038 | - |
|
| 1039 | - return ['remote' => $remote]; |
|
| 1040 | - } |
|
| 476 | + return $share; |
|
| 477 | + } |
|
| 478 | + |
|
| 479 | + /** |
|
| 480 | + * Get all children of this share |
|
| 481 | + * |
|
| 482 | + * @param IShare $parent |
|
| 483 | + * @return IShare[] |
|
| 484 | + */ |
|
| 485 | + public function getChildren(IShare $parent) { |
|
| 486 | + $children = []; |
|
| 487 | + |
|
| 488 | + $qb = $this->dbConnection->getQueryBuilder(); |
|
| 489 | + $qb->select('*') |
|
| 490 | + ->from('share') |
|
| 491 | + ->where($qb->expr()->eq('parent', $qb->createNamedParameter($parent->getId()))) |
|
| 492 | + ->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter(self::SHARE_TYPE_REMOTE))) |
|
| 493 | + ->orderBy('id'); |
|
| 494 | + |
|
| 495 | + $cursor = $qb->execute(); |
|
| 496 | + while($data = $cursor->fetch()) { |
|
| 497 | + $children[] = $this->createShareObject($data); |
|
| 498 | + } |
|
| 499 | + $cursor->closeCursor(); |
|
| 500 | + |
|
| 501 | + return $children; |
|
| 502 | + } |
|
| 503 | + |
|
| 504 | + /** |
|
| 505 | + * Delete a share (owner unShares the file) |
|
| 506 | + * |
|
| 507 | + * @param IShare $share |
|
| 508 | + */ |
|
| 509 | + public function delete(IShare $share) { |
|
| 510 | + |
|
| 511 | + list(, $remote) = $this->addressHandler->splitUserRemote($share->getSharedWith()); |
|
| 512 | + |
|
| 513 | + $isOwner = false; |
|
| 514 | + |
|
| 515 | + $this->removeShareFromTable($share); |
|
| 516 | + |
|
| 517 | + // if the local user is the owner we can send the unShare request directly... |
|
| 518 | + if ($this->userManager->userExists($share->getShareOwner())) { |
|
| 519 | + $this->notifications->sendRemoteUnShare($remote, $share->getId(), $share->getToken()); |
|
| 520 | + $this->revokeShare($share, true); |
|
| 521 | + $isOwner = true; |
|
| 522 | + } else { // ... if not we need to correct ID for the unShare request |
|
| 523 | + $remoteId = $this->getRemoteId($share); |
|
| 524 | + $this->notifications->sendRemoteUnShare($remote, $remoteId, $share->getToken()); |
|
| 525 | + $this->revokeShare($share, false); |
|
| 526 | + } |
|
| 527 | + |
|
| 528 | + // send revoke notification to the other user, if initiator and owner are not the same user |
|
| 529 | + if ($share->getShareOwner() !== $share->getSharedBy()) { |
|
| 530 | + $remoteId = $this->getRemoteId($share); |
|
| 531 | + if ($isOwner) { |
|
| 532 | + list(, $remote) = $this->addressHandler->splitUserRemote($share->getSharedBy()); |
|
| 533 | + } else { |
|
| 534 | + list(, $remote) = $this->addressHandler->splitUserRemote($share->getShareOwner()); |
|
| 535 | + } |
|
| 536 | + $this->notifications->sendRevokeShare($remote, $remoteId, $share->getToken()); |
|
| 537 | + } |
|
| 538 | + } |
|
| 539 | + |
|
| 540 | + /** |
|
| 541 | + * in case of a re-share we need to send the other use (initiator or owner) |
|
| 542 | + * a message that the file was unshared |
|
| 543 | + * |
|
| 544 | + * @param IShare $share |
|
| 545 | + * @param bool $isOwner the user can either be the owner or the user who re-sahred it |
|
| 546 | + * @throws ShareNotFound |
|
| 547 | + * @throws \OC\HintException |
|
| 548 | + */ |
|
| 549 | + protected function revokeShare($share, $isOwner) { |
|
| 550 | + // also send a unShare request to the initiator, if this is a different user than the owner |
|
| 551 | + if ($share->getShareOwner() !== $share->getSharedBy()) { |
|
| 552 | + if ($isOwner) { |
|
| 553 | + list(, $remote) = $this->addressHandler->splitUserRemote($share->getSharedBy()); |
|
| 554 | + } else { |
|
| 555 | + list(, $remote) = $this->addressHandler->splitUserRemote($share->getShareOwner()); |
|
| 556 | + } |
|
| 557 | + $remoteId = $this->getRemoteId($share); |
|
| 558 | + $this->notifications->sendRevokeShare($remote, $remoteId, $share->getToken()); |
|
| 559 | + } |
|
| 560 | + } |
|
| 561 | + |
|
| 562 | + /** |
|
| 563 | + * remove share from table |
|
| 564 | + * |
|
| 565 | + * @param IShare $share |
|
| 566 | + */ |
|
| 567 | + public function removeShareFromTable(IShare $share) { |
|
| 568 | + $this->removeShareFromTableById($share->getId()); |
|
| 569 | + } |
|
| 570 | + |
|
| 571 | + /** |
|
| 572 | + * remove share from table |
|
| 573 | + * |
|
| 574 | + * @param string $shareId |
|
| 575 | + */ |
|
| 576 | + private function removeShareFromTableById($shareId) { |
|
| 577 | + $qb = $this->dbConnection->getQueryBuilder(); |
|
| 578 | + $qb->delete('share') |
|
| 579 | + ->where($qb->expr()->eq('id', $qb->createNamedParameter($shareId))); |
|
| 580 | + $qb->execute(); |
|
| 581 | + |
|
| 582 | + $qb->delete('federated_reshares') |
|
| 583 | + ->where($qb->expr()->eq('share_id', $qb->createNamedParameter($shareId))); |
|
| 584 | + $qb->execute(); |
|
| 585 | + } |
|
| 586 | + |
|
| 587 | + /** |
|
| 588 | + * @inheritdoc |
|
| 589 | + */ |
|
| 590 | + public function deleteFromSelf(IShare $share, $recipient) { |
|
| 591 | + // nothing to do here. Technically deleteFromSelf in the context of federated |
|
| 592 | + // shares is a umount of a external storage. This is handled here |
|
| 593 | + // apps/files_sharing/lib/external/manager.php |
|
| 594 | + // TODO move this code over to this app |
|
| 595 | + } |
|
| 596 | + |
|
| 597 | + |
|
| 598 | + public function getSharesInFolder($userId, Folder $node, $reshares) { |
|
| 599 | + $qb = $this->dbConnection->getQueryBuilder(); |
|
| 600 | + $qb->select('*') |
|
| 601 | + ->from('share', 's') |
|
| 602 | + ->andWhere($qb->expr()->orX( |
|
| 603 | + $qb->expr()->eq('item_type', $qb->createNamedParameter('file')), |
|
| 604 | + $qb->expr()->eq('item_type', $qb->createNamedParameter('folder')) |
|
| 605 | + )) |
|
| 606 | + ->andWhere( |
|
| 607 | + $qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_REMOTE)) |
|
| 608 | + ); |
|
| 609 | + |
|
| 610 | + /** |
|
| 611 | + * Reshares for this user are shares where they are the owner. |
|
| 612 | + */ |
|
| 613 | + if ($reshares === false) { |
|
| 614 | + $qb->andWhere($qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId))); |
|
| 615 | + } else { |
|
| 616 | + $qb->andWhere( |
|
| 617 | + $qb->expr()->orX( |
|
| 618 | + $qb->expr()->eq('uid_owner', $qb->createNamedParameter($userId)), |
|
| 619 | + $qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId)) |
|
| 620 | + ) |
|
| 621 | + ); |
|
| 622 | + } |
|
| 623 | + |
|
| 624 | + $qb->innerJoin('s', 'filecache' ,'f', $qb->expr()->eq('s.file_source', 'f.fileid')); |
|
| 625 | + $qb->andWhere($qb->expr()->eq('f.parent', $qb->createNamedParameter($node->getId()))); |
|
| 626 | + |
|
| 627 | + $qb->orderBy('id'); |
|
| 628 | + |
|
| 629 | + $cursor = $qb->execute(); |
|
| 630 | + $shares = []; |
|
| 631 | + while ($data = $cursor->fetch()) { |
|
| 632 | + $shares[$data['fileid']][] = $this->createShareObject($data); |
|
| 633 | + } |
|
| 634 | + $cursor->closeCursor(); |
|
| 635 | + |
|
| 636 | + return $shares; |
|
| 637 | + } |
|
| 638 | + |
|
| 639 | + /** |
|
| 640 | + * @inheritdoc |
|
| 641 | + */ |
|
| 642 | + public function getSharesBy($userId, $shareType, $node, $reshares, $limit, $offset) { |
|
| 643 | + $qb = $this->dbConnection->getQueryBuilder(); |
|
| 644 | + $qb->select('*') |
|
| 645 | + ->from('share'); |
|
| 646 | + |
|
| 647 | + $qb->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter(self::SHARE_TYPE_REMOTE))); |
|
| 648 | + |
|
| 649 | + /** |
|
| 650 | + * Reshares for this user are shares where they are the owner. |
|
| 651 | + */ |
|
| 652 | + if ($reshares === false) { |
|
| 653 | + //Special case for old shares created via the web UI |
|
| 654 | + $or1 = $qb->expr()->andX( |
|
| 655 | + $qb->expr()->eq('uid_owner', $qb->createNamedParameter($userId)), |
|
| 656 | + $qb->expr()->isNull('uid_initiator') |
|
| 657 | + ); |
|
| 658 | + |
|
| 659 | + $qb->andWhere( |
|
| 660 | + $qb->expr()->orX( |
|
| 661 | + $qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId)), |
|
| 662 | + $or1 |
|
| 663 | + ) |
|
| 664 | + ); |
|
| 665 | + } else { |
|
| 666 | + $qb->andWhere( |
|
| 667 | + $qb->expr()->orX( |
|
| 668 | + $qb->expr()->eq('uid_owner', $qb->createNamedParameter($userId)), |
|
| 669 | + $qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId)) |
|
| 670 | + ) |
|
| 671 | + ); |
|
| 672 | + } |
|
| 673 | + |
|
| 674 | + if ($node !== null) { |
|
| 675 | + $qb->andWhere($qb->expr()->eq('file_source', $qb->createNamedParameter($node->getId()))); |
|
| 676 | + } |
|
| 677 | + |
|
| 678 | + if ($limit !== -1) { |
|
| 679 | + $qb->setMaxResults($limit); |
|
| 680 | + } |
|
| 681 | + |
|
| 682 | + $qb->setFirstResult($offset); |
|
| 683 | + $qb->orderBy('id'); |
|
| 684 | + |
|
| 685 | + $cursor = $qb->execute(); |
|
| 686 | + $shares = []; |
|
| 687 | + while($data = $cursor->fetch()) { |
|
| 688 | + $shares[] = $this->createShareObject($data); |
|
| 689 | + } |
|
| 690 | + $cursor->closeCursor(); |
|
| 691 | + |
|
| 692 | + return $shares; |
|
| 693 | + } |
|
| 694 | + |
|
| 695 | + /** |
|
| 696 | + * @inheritdoc |
|
| 697 | + */ |
|
| 698 | + public function getShareById($id, $recipientId = null) { |
|
| 699 | + $qb = $this->dbConnection->getQueryBuilder(); |
|
| 700 | + |
|
| 701 | + $qb->select('*') |
|
| 702 | + ->from('share') |
|
| 703 | + ->where($qb->expr()->eq('id', $qb->createNamedParameter($id))) |
|
| 704 | + ->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter(self::SHARE_TYPE_REMOTE))); |
|
| 705 | + |
|
| 706 | + $cursor = $qb->execute(); |
|
| 707 | + $data = $cursor->fetch(); |
|
| 708 | + $cursor->closeCursor(); |
|
| 709 | + |
|
| 710 | + if ($data === false) { |
|
| 711 | + throw new ShareNotFound(); |
|
| 712 | + } |
|
| 713 | + |
|
| 714 | + try { |
|
| 715 | + $share = $this->createShareObject($data); |
|
| 716 | + } catch (InvalidShare $e) { |
|
| 717 | + throw new ShareNotFound(); |
|
| 718 | + } |
|
| 719 | + |
|
| 720 | + return $share; |
|
| 721 | + } |
|
| 722 | + |
|
| 723 | + /** |
|
| 724 | + * Get shares for a given path |
|
| 725 | + * |
|
| 726 | + * @param \OCP\Files\Node $path |
|
| 727 | + * @return IShare[] |
|
| 728 | + */ |
|
| 729 | + public function getSharesByPath(Node $path) { |
|
| 730 | + $qb = $this->dbConnection->getQueryBuilder(); |
|
| 731 | + |
|
| 732 | + $cursor = $qb->select('*') |
|
| 733 | + ->from('share') |
|
| 734 | + ->andWhere($qb->expr()->eq('file_source', $qb->createNamedParameter($path->getId()))) |
|
| 735 | + ->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter(self::SHARE_TYPE_REMOTE))) |
|
| 736 | + ->execute(); |
|
| 737 | + |
|
| 738 | + $shares = []; |
|
| 739 | + while($data = $cursor->fetch()) { |
|
| 740 | + $shares[] = $this->createShareObject($data); |
|
| 741 | + } |
|
| 742 | + $cursor->closeCursor(); |
|
| 743 | + |
|
| 744 | + return $shares; |
|
| 745 | + } |
|
| 746 | + |
|
| 747 | + /** |
|
| 748 | + * @inheritdoc |
|
| 749 | + */ |
|
| 750 | + public function getSharedWith($userId, $shareType, $node, $limit, $offset) { |
|
| 751 | + /** @var IShare[] $shares */ |
|
| 752 | + $shares = []; |
|
| 753 | + |
|
| 754 | + //Get shares directly with this user |
|
| 755 | + $qb = $this->dbConnection->getQueryBuilder(); |
|
| 756 | + $qb->select('*') |
|
| 757 | + ->from('share'); |
|
| 758 | + |
|
| 759 | + // Order by id |
|
| 760 | + $qb->orderBy('id'); |
|
| 761 | + |
|
| 762 | + // Set limit and offset |
|
| 763 | + if ($limit !== -1) { |
|
| 764 | + $qb->setMaxResults($limit); |
|
| 765 | + } |
|
| 766 | + $qb->setFirstResult($offset); |
|
| 767 | + |
|
| 768 | + $qb->where($qb->expr()->eq('share_type', $qb->createNamedParameter(self::SHARE_TYPE_REMOTE))); |
|
| 769 | + $qb->andWhere($qb->expr()->eq('share_with', $qb->createNamedParameter($userId))); |
|
| 770 | + |
|
| 771 | + // Filter by node if provided |
|
| 772 | + if ($node !== null) { |
|
| 773 | + $qb->andWhere($qb->expr()->eq('file_source', $qb->createNamedParameter($node->getId()))); |
|
| 774 | + } |
|
| 775 | + |
|
| 776 | + $cursor = $qb->execute(); |
|
| 777 | + |
|
| 778 | + while($data = $cursor->fetch()) { |
|
| 779 | + $shares[] = $this->createShareObject($data); |
|
| 780 | + } |
|
| 781 | + $cursor->closeCursor(); |
|
| 782 | + |
|
| 783 | + |
|
| 784 | + return $shares; |
|
| 785 | + } |
|
| 786 | + |
|
| 787 | + /** |
|
| 788 | + * Get a share by token |
|
| 789 | + * |
|
| 790 | + * @param string $token |
|
| 791 | + * @return IShare |
|
| 792 | + * @throws ShareNotFound |
|
| 793 | + */ |
|
| 794 | + public function getShareByToken($token) { |
|
| 795 | + $qb = $this->dbConnection->getQueryBuilder(); |
|
| 796 | + |
|
| 797 | + $cursor = $qb->select('*') |
|
| 798 | + ->from('share') |
|
| 799 | + ->where($qb->expr()->eq('share_type', $qb->createNamedParameter(self::SHARE_TYPE_REMOTE))) |
|
| 800 | + ->andWhere($qb->expr()->eq('token', $qb->createNamedParameter($token))) |
|
| 801 | + ->execute(); |
|
| 802 | + |
|
| 803 | + $data = $cursor->fetch(); |
|
| 804 | + |
|
| 805 | + if ($data === false) { |
|
| 806 | + throw new ShareNotFound('Share not found', $this->l->t('Could not find share')); |
|
| 807 | + } |
|
| 808 | + |
|
| 809 | + try { |
|
| 810 | + $share = $this->createShareObject($data); |
|
| 811 | + } catch (InvalidShare $e) { |
|
| 812 | + throw new ShareNotFound('Share not found', $this->l->t('Could not find share')); |
|
| 813 | + } |
|
| 814 | + |
|
| 815 | + return $share; |
|
| 816 | + } |
|
| 817 | + |
|
| 818 | + /** |
|
| 819 | + * get database row of a give share |
|
| 820 | + * |
|
| 821 | + * @param $id |
|
| 822 | + * @return array |
|
| 823 | + * @throws ShareNotFound |
|
| 824 | + */ |
|
| 825 | + private function getRawShare($id) { |
|
| 826 | + |
|
| 827 | + // Now fetch the inserted share and create a complete share object |
|
| 828 | + $qb = $this->dbConnection->getQueryBuilder(); |
|
| 829 | + $qb->select('*') |
|
| 830 | + ->from('share') |
|
| 831 | + ->where($qb->expr()->eq('id', $qb->createNamedParameter($id))); |
|
| 832 | + |
|
| 833 | + $cursor = $qb->execute(); |
|
| 834 | + $data = $cursor->fetch(); |
|
| 835 | + $cursor->closeCursor(); |
|
| 836 | + |
|
| 837 | + if ($data === false) { |
|
| 838 | + throw new ShareNotFound; |
|
| 839 | + } |
|
| 840 | + |
|
| 841 | + return $data; |
|
| 842 | + } |
|
| 843 | + |
|
| 844 | + /** |
|
| 845 | + * Create a share object from an database row |
|
| 846 | + * |
|
| 847 | + * @param array $data |
|
| 848 | + * @return IShare |
|
| 849 | + * @throws InvalidShare |
|
| 850 | + * @throws ShareNotFound |
|
| 851 | + */ |
|
| 852 | + private function createShareObject($data) { |
|
| 853 | + |
|
| 854 | + $share = new Share($this->rootFolder, $this->userManager); |
|
| 855 | + $share->setId((int)$data['id']) |
|
| 856 | + ->setShareType((int)$data['share_type']) |
|
| 857 | + ->setPermissions((int)$data['permissions']) |
|
| 858 | + ->setTarget($data['file_target']) |
|
| 859 | + ->setMailSend((bool)$data['mail_send']) |
|
| 860 | + ->setToken($data['token']); |
|
| 861 | + |
|
| 862 | + $shareTime = new \DateTime(); |
|
| 863 | + $shareTime->setTimestamp((int)$data['stime']); |
|
| 864 | + $share->setShareTime($shareTime); |
|
| 865 | + $share->setSharedWith($data['share_with']); |
|
| 866 | + |
|
| 867 | + if ($data['uid_initiator'] !== null) { |
|
| 868 | + $share->setShareOwner($data['uid_owner']); |
|
| 869 | + $share->setSharedBy($data['uid_initiator']); |
|
| 870 | + } else { |
|
| 871 | + //OLD SHARE |
|
| 872 | + $share->setSharedBy($data['uid_owner']); |
|
| 873 | + $path = $this->getNode($share->getSharedBy(), (int)$data['file_source']); |
|
| 874 | + |
|
| 875 | + $owner = $path->getOwner(); |
|
| 876 | + $share->setShareOwner($owner->getUID()); |
|
| 877 | + } |
|
| 878 | + |
|
| 879 | + $share->setNodeId((int)$data['file_source']); |
|
| 880 | + $share->setNodeType($data['item_type']); |
|
| 881 | + |
|
| 882 | + $share->setProviderId($this->identifier()); |
|
| 883 | + |
|
| 884 | + return $share; |
|
| 885 | + } |
|
| 886 | + |
|
| 887 | + /** |
|
| 888 | + * Get the node with file $id for $user |
|
| 889 | + * |
|
| 890 | + * @param string $userId |
|
| 891 | + * @param int $id |
|
| 892 | + * @return \OCP\Files\File|\OCP\Files\Folder |
|
| 893 | + * @throws InvalidShare |
|
| 894 | + */ |
|
| 895 | + private function getNode($userId, $id) { |
|
| 896 | + try { |
|
| 897 | + $userFolder = $this->rootFolder->getUserFolder($userId); |
|
| 898 | + } catch (NotFoundException $e) { |
|
| 899 | + throw new InvalidShare(); |
|
| 900 | + } |
|
| 901 | + |
|
| 902 | + $nodes = $userFolder->getById($id); |
|
| 903 | + |
|
| 904 | + if (empty($nodes)) { |
|
| 905 | + throw new InvalidShare(); |
|
| 906 | + } |
|
| 907 | + |
|
| 908 | + return $nodes[0]; |
|
| 909 | + } |
|
| 910 | + |
|
| 911 | + /** |
|
| 912 | + * A user is deleted from the system |
|
| 913 | + * So clean up the relevant shares. |
|
| 914 | + * |
|
| 915 | + * @param string $uid |
|
| 916 | + * @param int $shareType |
|
| 917 | + */ |
|
| 918 | + public function userDeleted($uid, $shareType) { |
|
| 919 | + //TODO: probabaly a good idea to send unshare info to remote servers |
|
| 920 | + |
|
| 921 | + $qb = $this->dbConnection->getQueryBuilder(); |
|
| 922 | + |
|
| 923 | + $qb->delete('share') |
|
| 924 | + ->where($qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_REMOTE))) |
|
| 925 | + ->andWhere($qb->expr()->eq('uid_owner', $qb->createNamedParameter($uid))) |
|
| 926 | + ->execute(); |
|
| 927 | + } |
|
| 928 | + |
|
| 929 | + /** |
|
| 930 | + * This provider does not handle groups |
|
| 931 | + * |
|
| 932 | + * @param string $gid |
|
| 933 | + */ |
|
| 934 | + public function groupDeleted($gid) { |
|
| 935 | + // We don't handle groups here |
|
| 936 | + } |
|
| 937 | + |
|
| 938 | + /** |
|
| 939 | + * This provider does not handle groups |
|
| 940 | + * |
|
| 941 | + * @param string $uid |
|
| 942 | + * @param string $gid |
|
| 943 | + */ |
|
| 944 | + public function userDeletedFromGroup($uid, $gid) { |
|
| 945 | + // We don't handle groups here |
|
| 946 | + } |
|
| 947 | + |
|
| 948 | + /** |
|
| 949 | + * check if users from other Nextcloud instances are allowed to mount public links share by this instance |
|
| 950 | + * |
|
| 951 | + * @return bool |
|
| 952 | + */ |
|
| 953 | + public function isOutgoingServer2serverShareEnabled() { |
|
| 954 | + if ($this->gsConfig->onlyInternalFederation()) { |
|
| 955 | + return false; |
|
| 956 | + } |
|
| 957 | + $result = $this->config->getAppValue('files_sharing', 'outgoing_server2server_share_enabled', 'yes'); |
|
| 958 | + return ($result === 'yes'); |
|
| 959 | + } |
|
| 960 | + |
|
| 961 | + /** |
|
| 962 | + * check if users are allowed to mount public links from other Nextclouds |
|
| 963 | + * |
|
| 964 | + * @return bool |
|
| 965 | + */ |
|
| 966 | + public function isIncomingServer2serverShareEnabled() { |
|
| 967 | + if ($this->gsConfig->onlyInternalFederation()) { |
|
| 968 | + return false; |
|
| 969 | + } |
|
| 970 | + $result = $this->config->getAppValue('files_sharing', 'incoming_server2server_share_enabled', 'yes'); |
|
| 971 | + return ($result === 'yes'); |
|
| 972 | + } |
|
| 973 | + |
|
| 974 | + /** |
|
| 975 | + * Check if querying sharees on the lookup server is enabled |
|
| 976 | + * |
|
| 977 | + * @return bool |
|
| 978 | + */ |
|
| 979 | + public function isLookupServerQueriesEnabled() { |
|
| 980 | + // in a global scale setup we should always query the lookup server |
|
| 981 | + if ($this->gsConfig->isGlobalScaleEnabled()) { |
|
| 982 | + return true; |
|
| 983 | + } |
|
| 984 | + $result = $this->config->getAppValue('files_sharing', 'lookupServerEnabled', 'no'); |
|
| 985 | + return ($result === 'yes'); |
|
| 986 | + } |
|
| 987 | + |
|
| 988 | + |
|
| 989 | + /** |
|
| 990 | + * Check if it is allowed to publish user specific data to the lookup server |
|
| 991 | + * |
|
| 992 | + * @return bool |
|
| 993 | + */ |
|
| 994 | + public function isLookupServerUploadEnabled() { |
|
| 995 | + // in a global scale setup the admin is responsible to keep the lookup server up-to-date |
|
| 996 | + if ($this->gsConfig->isGlobalScaleEnabled()) { |
|
| 997 | + return false; |
|
| 998 | + } |
|
| 999 | + $result = $this->config->getAppValue('files_sharing', 'lookupServerUploadEnabled', 'yes'); |
|
| 1000 | + return ($result === 'yes'); |
|
| 1001 | + } |
|
| 1002 | + |
|
| 1003 | + /** |
|
| 1004 | + * @inheritdoc |
|
| 1005 | + */ |
|
| 1006 | + public function getAccessList($nodes, $currentAccess) { |
|
| 1007 | + $ids = []; |
|
| 1008 | + foreach ($nodes as $node) { |
|
| 1009 | + $ids[] = $node->getId(); |
|
| 1010 | + } |
|
| 1011 | + |
|
| 1012 | + $qb = $this->dbConnection->getQueryBuilder(); |
|
| 1013 | + $qb->select('share_with', 'token', 'file_source') |
|
| 1014 | + ->from('share') |
|
| 1015 | + ->where($qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_REMOTE))) |
|
| 1016 | + ->andWhere($qb->expr()->in('file_source', $qb->createNamedParameter($ids, IQueryBuilder::PARAM_INT_ARRAY))) |
|
| 1017 | + ->andWhere($qb->expr()->orX( |
|
| 1018 | + $qb->expr()->eq('item_type', $qb->createNamedParameter('file')), |
|
| 1019 | + $qb->expr()->eq('item_type', $qb->createNamedParameter('folder')) |
|
| 1020 | + )); |
|
| 1021 | + $cursor = $qb->execute(); |
|
| 1022 | + |
|
| 1023 | + if ($currentAccess === false) { |
|
| 1024 | + $remote = $cursor->fetch() !== false; |
|
| 1025 | + $cursor->closeCursor(); |
|
| 1026 | + |
|
| 1027 | + return ['remote' => $remote]; |
|
| 1028 | + } |
|
| 1029 | + |
|
| 1030 | + $remote = []; |
|
| 1031 | + while ($row = $cursor->fetch()) { |
|
| 1032 | + $remote[$row['share_with']] = [ |
|
| 1033 | + 'node_id' => $row['file_source'], |
|
| 1034 | + 'token' => $row['token'], |
|
| 1035 | + ]; |
|
| 1036 | + } |
|
| 1037 | + $cursor->closeCursor(); |
|
| 1038 | + |
|
| 1039 | + return ['remote' => $remote]; |
|
| 1040 | + } |
|
| 1041 | 1041 | } |