/** * Convert an IShare to an array for OCS output * * @param IShare $share * @return array */ protected function formatShare($share) { $result = ['id' => $share->getId(), 'share_type' => $share->getShareType(), 'uid_owner' => $share->getSharedBy()->getUID(), 'displayname_owner' => $share->getSharedBy()->getDisplayName(), 'permissions' => $share->getPermissions(), 'stime' => $share->getShareTime(), 'parent' => $share->getParent(), 'expiration' => null, 'token' => null]; $path = $share->getPath(); $result['path'] = $this->userFolder->getRelativePath($path->getPath()); if ($path instanceof \OCP\Files\Folder) { $result['item_type'] = 'folder'; } else { $result['item_type'] = 'file'; } $result['storage_id'] = $path->getStorage()->getId(); $result['storage'] = \OC\Files\Cache\Storage::getNumericStorageId($path->getStorage()->getId()); $result['item_source'] = $path->getId(); $result['file_source'] = $path->getId(); $result['file_parent'] = $path->getParent()->getId(); $result['file_target'] = $share->getTarget(); if ($share->getShareType() === \OCP\Share::SHARE_TYPE_USER) { $sharedWith = $share->getSharedWith(); $result['share_with'] = $sharedWith->getUID(); $result['share_with_displayname'] = $sharedWith->getDisplayName(); } else { if ($share->getShareType() === \OCP\Share::SHARE_TYPE_GROUP) { $sharedWith = $share->getSharedWith(); $result['share_with'] = $sharedWith->getGID(); $result['share_with_displayname'] = $sharedWith->getGID(); } else { if ($share->getShareType() === \OCP\Share::SHARE_TYPE_LINK) { $result['share_with'] = $share->getPassword(); $result['share_with_displayname'] = $share->getPassword(); $result['token'] = $share->getToken(); $result['url'] = $this->urlGenerator->linkToRouteAbsolute('files_sharing.sharecontroller.showShare', ['token' => $share->getToken()]); $expiration = $share->getExpirationDate(); if ($expiration !== null) { $result['expiration'] = $expiration->format('Y-m-d 00:00:00'); } } else { if ($share->getShareType() === \OCP\Share::SHARE_TYPE_REMOTE) { $result['share_with'] = $share->getSharedWith(); $result['share_with_displayname'] = $share->getSharedWith(); $result['token'] = $share->getToken(); } } } } $result['mail_send'] = $share->getMailSend() ? 1 : 0; return $result; }
/** * Verify the password of a public share * * @param IShare $share * @param string $password * @return bool */ public function checkPassword(IShare $share, $password) { if ($share->getShareType() !== \OCP\Share::SHARE_TYPE_LINK) { //TODO maybe exception? return false; } if ($password === null || $share->getPassword() === null) { return false; } $newHash = ''; if (!$this->hasher->verify($password, $share->getPassword(), $newHash)) { return false; } if (!empty($newHash)) { //TODO update hash! } return true; }
/** * @param IShare $share * @return bool */ protected function canAccessShare(IShare $share) { // A file with permissions 0 can't be accessed by us. So Don't show it if ($share->getPermissions() === 0) { return false; } // Owner of the file and the sharer of the file can always get share if ($share->getShareOwner() === $this->currentUser || $share->getSharedBy() === $this->currentUser) { return true; } // If the share is shared with you (or a group you are a member of) if ($share->getShareType() === \OCP\Share::SHARE_TYPE_USER && $share->getSharedWith() === $this->currentUser) { return true; } if ($share->getShareType() === \OCP\Share::SHARE_TYPE_GROUP && $share->getSharedWith()->inGroup($this->currentUser)) { return true; } return false; }
/** * Share a path * * @param IShare $share * @return IShare The share object * @throws ShareNotFound * @throws \Exception */ public function create(IShare $share) { $qb = $this->dbConn->getQueryBuilder(); $qb->insert('share'); $qb->setValue('share_type', $qb->createNamedParameter($share->getShareType())); if ($share->getShareType() === \OCP\Share::SHARE_TYPE_USER) { //Set the UID of the user we share with $qb->setValue('share_with', $qb->createNamedParameter($share->getSharedWith()->getUID())); } else { if ($share->getShareType() === \OCP\Share::SHARE_TYPE_GROUP) { //Set the GID of the group we share with $qb->setValue('share_with', $qb->createNamedParameter($share->getSharedWith()->getGID())); } else { if ($share->getShareType() === \OCP\Share::SHARE_TYPE_LINK) { //Set the token of the share $qb->setValue('token', $qb->createNamedParameter($share->getToken())); //If a password is set store it if ($share->getPassword() !== null) { $qb->setValue('share_with', $qb->createNamedParameter($share->getPassword())); } //If an expiration date is set store it if ($share->getExpirationDate() !== null) { $qb->setValue('expiration', $qb->createNamedParameter($share->getExpirationDate(), 'datetime')); } } else { throw new \Exception('invalid share type!'); } } } // Set what is shares $qb->setValue('item_type', $qb->createParameter('itemType')); if ($share->getPath() instanceof \OCP\Files\File) { $qb->setParameter('itemType', 'file'); } else { $qb->setParameter('itemType', 'folder'); } // Set the file id $qb->setValue('item_source', $qb->createNamedParameter($share->getPath()->getId())); $qb->setValue('file_source', $qb->createNamedParameter($share->getPath()->getId())); // set the permissions $qb->setValue('permissions', $qb->createNamedParameter($share->getPermissions())); // Set who created this share $qb->setValue('uid_initiator', $qb->createNamedParameter($share->getSharedBy()->getUID())); // Set who is the owner of this file/folder (and this the owner of the share) $qb->setValue('uid_owner', $qb->createNamedParameter($share->getShareOwner()->getUID())); // Set the file target $qb->setValue('file_target', $qb->createNamedParameter($share->getTarget())); // Set the time this share was created $qb->setValue('stime', $qb->createNamedParameter(time())); // insert the data and fetch the id of the share $this->dbConn->beginTransaction(); $qb->execute(); $id = $this->dbConn->lastInsertId('*PREFIX*share'); $this->dbConn->commit(); // Now fetch the inserted share and create a complete share object $qb = $this->dbConn->getQueryBuilder(); $qb->select('*')->from('*PREFIX*share')->where($qb->expr()->eq('id', $qb->createNamedParameter($id))); $cursor = $qb->execute(); $data = $cursor->fetch(); $cursor->closeCursor(); if ($data === false) { throw new ShareNotFound(); } $share = $this->createShare($data); return $share; }
/** * Check for generic requirements before creating a share * * @param IShare $share * @throws \Exception */ protected function generalCreateChecks(IShare $share) { if ($share->getShareType() === \OCP\Share::SHARE_TYPE_USER) { // We expect a valid user as sharedWith for user shares if (!$share->getSharedWith() instanceof \OCP\IUser) { throw new \InvalidArgumentException('SharedWith should be an IUser'); } } else { if ($share->getShareType() === \OCP\Share::SHARE_TYPE_GROUP) { // We expect a valid group as sharedWith for group shares if (!$share->getSharedWith() instanceof \OCP\IGroup) { throw new \InvalidArgumentException('SharedWith should be an IGroup'); } } else { if ($share->getShareType() === \OCP\Share::SHARE_TYPE_LINK) { if ($share->getSharedWith() !== null) { throw new \InvalidArgumentException('SharedWith should be empty'); } } else { // We can't handle other types yet throw new \InvalidArgumentException('unkown share type'); } } } // Verify the initiator of the share is et if ($share->getSharedBy() === null) { throw new \InvalidArgumentException('SharedBy should be set'); } // Cannot share with yourself if ($share->getSharedWith() === $share->getSharedBy()) { throw new \InvalidArgumentException('Can\'t share with yourself'); } // The path should be set if ($share->getPath() === null) { throw new \InvalidArgumentException('Path should be set'); } // And it should be a file or a folder if (!$share->getPath() instanceof \OCP\Files\File && !$share->getPath() instanceof \OCP\Files\Folder) { throw new \InvalidArgumentException('Path should be either a file or a folder'); } // Check if we actually have share permissions if (!$share->getPath()->isShareable()) { $message_t = $this->l->t('You are not allowed to share %s', [$share->getPath()->getPath()]); throw new HintException($message_t, $message_t, 404); } // Permissions should be set if ($share->getPermissions() === null) { throw new \InvalidArgumentException('A share requires permissions'); } // Check that we do not share with more permissions than we have if ($share->getPermissions() & ~$share->getPath()->getPermissions()) { $message_t = $this->l->t('Cannot increase permissions of %s', [$share->getPath()->getPath()]); throw new HintException($message_t, $message_t, 404); } // Check that read permissions are always set if (($share->getPermissions() & \OCP\Constants::PERMISSION_READ) === 0) { throw new \InvalidArgumentException('Shares need at least read permissions'); } }
/** * Unshare a share from the recipient. If this is a group share * this means we need a special entry in the share db. * * @param IShare $share * @param IUser $recipient * @throws BackendError * @throws ProviderException */ public function deleteFromSelf(IShare $share, IUser $recipient) { if ($share->getShareType() === \OCP\Share::SHARE_TYPE_GROUP) { /** @var IGroup $group */ $group = $share->getSharedWith(); if (!$group->inGroup($recipient)) { throw new ProviderException('Recipient not in receiving group'); } // Try to fetch user specific share $qb = $this->dbConn->getQueryBuilder(); $stmt = $qb->select('*')->from('share')->where($qb->expr()->eq('share_type', $qb->createNamedParameter(self::SHARE_TYPE_USERGROUP)))->andWhere($qb->expr()->eq('share_with', $qb->createNamedParameter($recipient->getUID())))->andWhere($qb->expr()->eq('parent', $qb->createNamedParameter($share->getId())))->execute(); $data = $stmt->fetch(); /* * Check if there already is a user specific group share. * If there is update it (if required). */ if ($data === false) { $qb = $this->dbConn->getQueryBuilder(); $type = $share->getPath() instanceof \OCP\Files\File ? 'file' : 'folder'; //Insert new share $qb->insert('share')->values(['share_type' => $qb->createNamedParameter(self::SHARE_TYPE_USERGROUP), 'share_with' => $qb->createNamedParameter($recipient->getUID()), 'uid_owner' => $qb->createNamedParameter($share->getShareOwner()->getUID()), 'uid_initiator' => $qb->createNamedParameter($share->getSharedBy()->getUID()), 'parent' => $qb->createNamedParameter($share->getId()), 'item_type' => $qb->createNamedParameter($type), 'item_source' => $qb->createNamedParameter($share->getPath()->getId()), 'file_source' => $qb->createNamedParameter($share->getPath()->getId()), 'file_target' => $qb->createNamedParameter($share->getTarget()), 'permissions' => $qb->createNamedParameter(0), 'stime' => $qb->createNamedParameter($share->getSharetime())])->execute(); } else { if ($data['permissions'] !== 0) { // Update existing usergroup share $qb = $this->dbConn->getQueryBuilder(); $qb->update('share')->set('permissions', $qb->createNamedParameter(0))->where($qb->expr()->eq('id', $qb->createNamedParameter($data['id'])))->execute(); } } } else { if ($share->getShareType() === \OCP\Share::SHARE_TYPE_USER) { if ($share->getSharedWith() !== $recipient) { throw new ProviderException('Recipient does not match'); } // We can just delete user and link shares $this->delete($share); } else { throw new ProviderException('Invalid shareType'); } } }
/** * Delete all the children of this share * * @param IShare $share * @return IShare[] List of deleted shares */ protected function deleteChildren(IShare $share) { $deletedShares = []; $provider = $this->factory->getProviderForType($share->getShareType()); foreach ($provider->getChildren($share) as $child) { $deletedChildren = $this->deleteChildren($child); $deletedShares = array_merge($deletedShares, $deletedChildren); $provider->delete($child); $deletedShares[] = $child; } return $deletedShares; }