12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244 |
- <?php
- namespace OCA\ShareByMail;
- use OC\Share20\DefaultShareProvider;
- use OC\Share20\Exception\InvalidShare;
- use OC\Share20\Share;
- use OC\User\NoUserException;
- use OCA\ShareByMail\Settings\SettingsManager;
- use OCP\Activity\IManager;
- use OCP\DB\QueryBuilder\IQueryBuilder;
- use OCP\Defaults;
- use OCP\EventDispatcher\IEventDispatcher;
- use OCP\Files\Folder;
- use OCP\Files\IRootFolder;
- use OCP\Files\Node;
- use OCP\HintException;
- use OCP\IConfig;
- use OCP\IDBConnection;
- use OCP\IL10N;
- use OCP\IURLGenerator;
- use OCP\IUser;
- use OCP\IUserManager;
- use OCP\Mail\IMailer;
- use OCP\Security\Events\GenerateSecurePasswordEvent;
- use OCP\Security\IHasher;
- use OCP\Security\ISecureRandom;
- use OCP\Security\PasswordContext;
- use OCP\Share\Exceptions\GenericShareException;
- use OCP\Share\Exceptions\ShareNotFound;
- use OCP\Share\IAttributes;
- use OCP\Share\IManager as IShareManager;
- use OCP\Share\IShare;
- use OCP\Share\IShareProviderWithNotification;
- use OCP\Util;
- use Psr\Log\LoggerInterface;
- class ShareByMailProvider extends DefaultShareProvider implements IShareProviderWithNotification {
-
- public function identifier(): string {
- return 'ocMailShare';
- }
- public function __construct(
- private IConfig $config,
- private IDBConnection $dbConnection,
- private ISecureRandom $secureRandom,
- private IUserManager $userManager,
- private IRootFolder $rootFolder,
- private IL10N $l,
- private LoggerInterface $logger,
- private IMailer $mailer,
- private IURLGenerator $urlGenerator,
- private IManager $activityManager,
- private SettingsManager $settingsManager,
- private Defaults $defaults,
- private IHasher $hasher,
- private IEventDispatcher $eventDispatcher,
- private IShareManager $shareManager,
- ) {
- }
-
- public function create(IShare $share): IShare {
- $shareWith = $share->getSharedWith();
-
-
- $alreadyShared = $this->getSharedWith($shareWith, IShare::TYPE_EMAIL, $share->getNode(), 1, 0);
- if ($shareWith !== '' && !empty($alreadyShared)) {
- $message = 'Sharing %1$s failed, because this item is already shared with the account %2$s';
- $message_t = $this->l->t('Sharing %1$s failed, because this item is already shared with the account %2$s', [$share->getNode()->getName(), $shareWith]);
- $this->logger->debug(sprintf($message, $share->getNode()->getName(), $shareWith), ['app' => 'Federated File Sharing']);
- throw new \Exception($message_t);
- }
-
-
- $password = $share->getPassword() ?: '';
- $passwordEnforced = $this->shareManager->shareApiLinkEnforcePassword();
- if ($passwordEnforced && empty($password)) {
- $password = $this->autoGeneratePassword($share);
- }
- if (!empty($password)) {
- $share->setPassword($this->hasher->hash($password));
- }
- $shareId = $this->createMailShare($share);
- $this->createShareActivity($share);
- $data = $this->getRawShare($shareId);
-
-
-
- if (!empty($password)) {
- $data['password'] = $password;
- }
- return $this->createShareObject($data);
- }
-
- protected function autoGeneratePassword(IShare $share): string {
- $initiatorUser = $this->userManager->get($share->getSharedBy());
- $initiatorEMailAddress = ($initiatorUser instanceof IUser) ? $initiatorUser->getEMailAddress() : null;
- $allowPasswordByMail = $this->settingsManager->sendPasswordByMail();
- if ($initiatorEMailAddress === null && !$allowPasswordByMail) {
- throw new \Exception(
- $this->l->t('We cannot send you the auto-generated password. Please set a valid email address in your personal settings and try again.')
- );
- }
- $passwordEvent = new GenerateSecurePasswordEvent(PasswordContext::SHARING);
- $this->eventDispatcher->dispatchTyped($passwordEvent);
- $password = $passwordEvent->getPassword();
- if ($password === null) {
- $password = $this->secureRandom->generate(8, ISecureRandom::CHAR_HUMAN_READABLE);
- }
- return $password;
- }
-
- protected function createShareActivity(IShare $share, string $type = 'share'): void {
- $userFolder = $this->rootFolder->getUserFolder($share->getSharedBy());
- $this->publishActivity(
- $type === 'share' ? Activity::SUBJECT_SHARED_EMAIL_SELF : Activity::SUBJECT_UNSHARED_EMAIL_SELF,
- [$userFolder->getRelativePath($share->getNode()->getPath()), $share->getSharedWith()],
- $share->getSharedBy(),
- $share->getNode()->getId(),
- (string)$userFolder->getRelativePath($share->getNode()->getPath())
- );
- if ($share->getShareOwner() !== $share->getSharedBy()) {
- $ownerFolder = $this->rootFolder->getUserFolder($share->getShareOwner());
- $fileId = $share->getNode()->getId();
- $nodes = $ownerFolder->getById($fileId);
- $ownerPath = $nodes[0]->getPath();
- $this->publishActivity(
- $type === 'share' ? Activity::SUBJECT_SHARED_EMAIL_BY : Activity::SUBJECT_UNSHARED_EMAIL_BY,
- [$ownerFolder->getRelativePath($ownerPath), $share->getSharedWith(), $share->getSharedBy()],
- $share->getShareOwner(),
- $fileId,
- (string)$ownerFolder->getRelativePath($ownerPath)
- );
- }
- }
-
- protected function createPasswordSendActivity(IShare $share, string $sharedWith, bool $sendToSelf): void {
- $userFolder = $this->rootFolder->getUserFolder($share->getSharedBy());
- if ($sendToSelf) {
- $this->publishActivity(
- Activity::SUBJECT_SHARED_EMAIL_PASSWORD_SEND_SELF,
- [$userFolder->getRelativePath($share->getNode()->getPath())],
- $share->getSharedBy(),
- $share->getNode()->getId(),
- (string)$userFolder->getRelativePath($share->getNode()->getPath())
- );
- } else {
- $this->publishActivity(
- Activity::SUBJECT_SHARED_EMAIL_PASSWORD_SEND,
- [$userFolder->getRelativePath($share->getNode()->getPath()), $sharedWith],
- $share->getSharedBy(),
- $share->getNode()->getId(),
- (string)$userFolder->getRelativePath($share->getNode()->getPath())
- );
- }
- }
-
- protected function publishActivity(string $subject, array $parameters, string $affectedUser, int $fileId, string $filePath): void {
- $event = $this->activityManager->generateEvent();
- $event->setApp('sharebymail')
- ->setType('shared')
- ->setSubject($subject, $parameters)
- ->setAffectedUser($affectedUser)
- ->setObject('files', $fileId, $filePath);
- $this->activityManager->publish($event);
- }
-
- protected function createMailShare(IShare $share): int {
- $share->setToken($this->generateToken());
- return $this->addShareToDB(
- $share->getNodeId(),
- $share->getNodeType(),
- $share->getSharedWith(),
- $share->getSharedBy(),
- $share->getShareOwner(),
- $share->getPermissions(),
- $share->getToken(),
- $share->getPassword(),
- $share->getPasswordExpirationTime(),
- $share->getSendPasswordByTalk(),
- $share->getHideDownload(),
- $share->getLabel(),
- $share->getExpirationDate(),
- $share->getNote(),
- $share->getAttributes(),
- $share->getMailSend(),
- );
- }
-
- public function sendMailNotification(IShare $share): bool {
- $shareId = $share->getId();
- $emails = $this->getSharedWithEmails($share);
- $validEmails = array_filter($emails, function (string $email) {
- return $this->mailer->validateMailAddress($email);
- });
- if (count($validEmails) === 0) {
- $this->removeShareFromTable((int)$shareId);
- $e = new HintException('Failed to send share by mail. Could not find a valid email address: ' . join(', ', $emails),
- $this->l->t('Failed to send share by email. Got an invalid email address'));
- $this->logger->error('Failed to send share by mail. Could not find a valid email address ' . join(', ', $emails), [
- 'app' => 'sharebymail',
- 'exception' => $e,
- ]);
- }
- try {
- $this->sendEmail($share, $validEmails);
-
- if ($share->getPassword() !== null) {
-
-
-
-
-
- $passwordExpire = $this->config->getSystemValue('sharing.enable_mail_link_password_expiration', false);
- $passwordEnforced = $this->shareManager->shareApiLinkEnforcePassword();
- if ($passwordExpire === false || $share->getSendPasswordByTalk()) {
- $send = $this->sendPassword($share, $share->getPassword(), $validEmails);
- if ($passwordEnforced && $send === false) {
- $this->sendPasswordToOwner($share, $share->getPassword());
- }
- }
- }
- return true;
- } catch (HintException $hintException) {
- $this->logger->error('Failed to send share by mail.', [
- 'app' => 'sharebymail',
- 'exception' => $hintException,
- ]);
- $this->removeShareFromTable((int)$shareId);
- throw $hintException;
- } catch (\Exception $e) {
- $this->logger->error('Failed to send share by mail.', [
- 'app' => 'sharebymail',
- 'exception' => $e,
- ]);
- $this->removeShareFromTable((int)$shareId);
- throw new HintException(
- 'Failed to send share by mail',
- $this->l->t('Failed to send share by email'),
- 0,
- $e,
- );
- }
- return false;
- }
-
- protected function sendEmail(IShare $share, array $emails): void {
- $link = $this->urlGenerator->linkToRouteAbsolute('files_sharing.sharecontroller.showShare', [
- 'token' => $share->getToken()
- ]);
- $expiration = $share->getExpirationDate();
- $filename = $share->getNode()->getName();
- $initiator = $share->getSharedBy();
- $note = $share->getNote();
- $shareWith = $share->getSharedWith();
- $initiatorUser = $this->userManager->get($initiator);
- $initiatorDisplayName = ($initiatorUser instanceof IUser) ? $initiatorUser->getDisplayName() : $initiator;
- $message = $this->mailer->createMessage();
- $emailTemplate = $this->mailer->createEMailTemplate('sharebymail.RecipientNotification', [
- 'filename' => $filename,
- 'link' => $link,
- 'initiator' => $initiatorDisplayName,
- 'expiration' => $expiration,
- 'shareWith' => $shareWith,
- 'note' => $note
- ]);
- $emailTemplate->setSubject($this->l->t('%1$s shared %2$s with you', [$initiatorDisplayName, $filename]));
- $emailTemplate->addHeader();
- $emailTemplate->addHeading($this->l->t('%1$s shared %2$s with you', [$initiatorDisplayName, $filename]), false);
- if ($note !== '') {
- $emailTemplate->addBodyListItem(
- htmlspecialchars($note),
- $this->l->t('Note:'),
- $this->getAbsoluteImagePath('caldav/description.png'),
- $note
- );
- }
- if ($expiration !== null) {
- $dateString = (string)$this->l->l('date', $expiration, ['width' => 'medium']);
- $emailTemplate->addBodyListItem(
- $this->l->t('This share is valid until %s at midnight', [$dateString]),
- $this->l->t('Expiration:'),
- $this->getAbsoluteImagePath('caldav/time.png'),
- );
- }
- $emailTemplate->addBodyText(
- $this->l->t('Click the button below to open it.')
- );
- $emailTemplate->addBodyButton(
- $this->l->t('Open %s', [$filename]),
- $link
- );
-
- if (count($emails) > 1) {
-
- $message->setBcc($emails);
- } else {
- $message->setTo($emails);
- }
-
- $instanceName = $this->defaults->getName();
- $senderName = $instanceName;
- if ($this->settingsManager->replyToInitiator()) {
- $senderName = $this->l->t(
- '%1$s via %2$s',
- [
- $initiatorDisplayName,
- $instanceName
- ]
- );
- }
- $message->setFrom([Util::getDefaultEmailAddress($instanceName) => $senderName]);
-
-
- if ($initiatorUser && $this->settingsManager->replyToInitiator()) {
- $initiatorEmail = $initiatorUser->getEMailAddress();
- if ($initiatorEmail !== null) {
- $message->setReplyTo([$initiatorEmail => $initiatorDisplayName]);
- $emailTemplate->addFooter($instanceName . ($this->defaults->getSlogan() !== '' ? ' - ' . $this->defaults->getSlogan() : ''));
- } else {
- $emailTemplate->addFooter();
- }
- } else {
- $emailTemplate->addFooter();
- }
- $message->useTemplate($emailTemplate);
- $failedRecipients = $this->mailer->send($message);
- if (!empty($failedRecipients)) {
- $this->logger->error('Share notification mail could not be sent to: ' . implode(', ', $failedRecipients));
- return;
- }
- }
-
- protected function sendPassword(IShare $share, string $password, array $emails): bool {
- $filename = $share->getNode()->getName();
- $initiator = $share->getSharedBy();
- $shareWith = $share->getSharedWith();
- if ($password === '' || $this->settingsManager->sendPasswordByMail() === false || $share->getSendPasswordByTalk()) {
- return false;
- }
- $initiatorUser = $this->userManager->get($initiator);
- $initiatorDisplayName = ($initiatorUser instanceof IUser) ? $initiatorUser->getDisplayName() : $initiator;
- $initiatorEmailAddress = ($initiatorUser instanceof IUser) ? $initiatorUser->getEMailAddress() : null;
- $plainBodyPart = $this->l->t("%1\$s shared %2\$s with you.\nYou should have already received a separate mail with a link to access it.\n", [$initiatorDisplayName, $filename]);
- $htmlBodyPart = $this->l->t('%1$s shared %2$s with you. You should have already received a separate mail with a link to access it.', [$initiatorDisplayName, $filename]);
- $message = $this->mailer->createMessage();
- $emailTemplate = $this->mailer->createEMailTemplate('sharebymail.RecipientPasswordNotification', [
- 'filename' => $filename,
- 'password' => $password,
- 'initiator' => $initiatorDisplayName,
- 'initiatorEmail' => $initiatorEmailAddress,
- 'shareWith' => $shareWith,
- ]);
- $emailTemplate->setSubject($this->l->t('Password to access %1$s shared to you by %2$s', [$filename, $initiatorDisplayName]));
- $emailTemplate->addHeader();
- $emailTemplate->addHeading($this->l->t('Password to access %s', [$filename]), false);
- $emailTemplate->addBodyText(htmlspecialchars($htmlBodyPart), $plainBodyPart);
- $emailTemplate->addBodyText($this->l->t('It is protected with the following password:'));
- $emailTemplate->addBodyText($password);
- if ($this->config->getSystemValue('sharing.enable_mail_link_password_expiration', false) === true) {
- $expirationTime = new \DateTime();
- $expirationInterval = $this->config->getSystemValue('sharing.mail_link_password_expiration_interval', 3600);
- $expirationTime = $expirationTime->add(new \DateInterval('PT' . $expirationInterval . 'S'));
- $emailTemplate->addBodyText($this->l->t('This password will expire at %s', [$expirationTime->format('r')]));
- }
-
- if (count($emails) > 1) {
-
- $message->setBcc($emails);
- } else {
- $message->setTo($emails);
- }
-
- $instanceName = $this->defaults->getName();
- $senderName = $instanceName;
- if ($this->settingsManager->replyToInitiator()) {
- $senderName = $this->l->t(
- '%1$s via %2$s',
- [
- $initiatorDisplayName,
- $instanceName
- ]
- );
- }
- $message->setFrom([Util::getDefaultEmailAddress($instanceName) => $senderName]);
-
-
- if ($initiatorUser && $this->settingsManager->replyToInitiator()) {
- $initiatorEmail = $initiatorUser->getEMailAddress();
- if ($initiatorEmail !== null) {
- $message->setReplyTo([$initiatorEmail => $initiatorDisplayName]);
- $emailTemplate->addFooter($instanceName . ($this->defaults->getSlogan() !== '' ? ' - ' . $this->defaults->getSlogan() : ''));
- } else {
- $emailTemplate->addFooter();
- }
- } else {
- $emailTemplate->addFooter();
- }
- $message->useTemplate($emailTemplate);
- $failedRecipients = $this->mailer->send($message);
- if (!empty($failedRecipients)) {
- $this->logger->error('Share password mail could not be sent to: ' . implode(', ', $failedRecipients));
- return false;
- }
- $this->createPasswordSendActivity($share, $shareWith, false);
- return true;
- }
- protected function sendNote(IShare $share): void {
- $recipient = $share->getSharedWith();
- $filename = $share->getNode()->getName();
- $initiator = $share->getSharedBy();
- $note = $share->getNote();
- $initiatorUser = $this->userManager->get($initiator);
- $initiatorDisplayName = ($initiatorUser instanceof IUser) ? $initiatorUser->getDisplayName() : $initiator;
- $initiatorEmailAddress = ($initiatorUser instanceof IUser) ? $initiatorUser->getEMailAddress() : null;
- $plainHeading = $this->l->t('%1$s shared %2$s with you and wants to add:', [$initiatorDisplayName, $filename]);
- $htmlHeading = $this->l->t('%1$s shared %2$s with you and wants to add', [$initiatorDisplayName, $filename]);
- $message = $this->mailer->createMessage();
- $emailTemplate = $this->mailer->createEMailTemplate('shareByMail.sendNote');
- $emailTemplate->setSubject($this->l->t('%s added a note to a file shared with you', [$initiatorDisplayName]));
- $emailTemplate->addHeader();
- $emailTemplate->addHeading(htmlspecialchars($htmlHeading), $plainHeading);
- $emailTemplate->addBodyText(htmlspecialchars($note), $note);
- $link = $this->urlGenerator->linkToRouteAbsolute('files_sharing.sharecontroller.showShare',
- ['token' => $share->getToken()]);
- $emailTemplate->addBodyButton(
- $this->l->t('Open %s', [$filename]),
- $link
- );
-
- $instanceName = $this->defaults->getName();
- $senderName = $instanceName;
- if ($this->settingsManager->replyToInitiator()) {
- $senderName = $this->l->t(
- '%1$s via %2$s',
- [
- $initiatorDisplayName,
- $instanceName
- ]
- );
- }
- $message->setFrom([Util::getDefaultEmailAddress($instanceName) => $senderName]);
- if ($this->settingsManager->replyToInitiator() && $initiatorEmailAddress !== null) {
- $message->setReplyTo([$initiatorEmailAddress => $initiatorDisplayName]);
- $emailTemplate->addFooter($instanceName . ' - ' . $this->defaults->getSlogan());
- } else {
- $emailTemplate->addFooter();
- }
- $message->setTo([$recipient]);
- $message->useTemplate($emailTemplate);
- $this->mailer->send($message);
- }
-
- protected function sendPasswordToOwner(IShare $share, string $password): bool {
- $filename = $share->getNode()->getName();
- $initiator = $this->userManager->get($share->getSharedBy());
- $initiatorEMailAddress = ($initiator instanceof IUser) ? $initiator->getEMailAddress() : null;
- $initiatorDisplayName = ($initiator instanceof IUser) ? $initiator->getDisplayName() : $share->getSharedBy();
- $shareWith = $share->getSharedWith();
- if ($initiatorEMailAddress === null) {
- throw new \Exception(
- $this->l->t('We cannot send you the auto-generated password. Please set a valid email address in your personal settings and try again.')
- );
- }
- $bodyPart = $this->l->t('You just shared %1$s with %2$s. The share was already sent to the recipient. Due to the security policies defined by the administrator of %3$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()]);
- $message = $this->mailer->createMessage();
- $emailTemplate = $this->mailer->createEMailTemplate('sharebymail.OwnerPasswordNotification', [
- 'filename' => $filename,
- 'password' => $password,
- 'initiator' => $initiatorDisplayName,
- 'initiatorEmail' => $initiatorEMailAddress,
- 'shareWith' => $shareWith,
- ]);
- $emailTemplate->setSubject($this->l->t('Password to access %1$s shared by you with %2$s', [$filename, $shareWith]));
- $emailTemplate->addHeader();
- $emailTemplate->addHeading($this->l->t('Password to access %s', [$filename]), false);
- $emailTemplate->addBodyText($bodyPart);
- $emailTemplate->addBodyText($this->l->t('This is the password:'));
- $emailTemplate->addBodyText($password);
- if ($this->config->getSystemValue('sharing.enable_mail_link_password_expiration', false) === true) {
- $expirationTime = new \DateTime();
- $expirationInterval = $this->config->getSystemValue('sharing.mail_link_password_expiration_interval', 3600);
- $expirationTime = $expirationTime->add(new \DateInterval('PT' . $expirationInterval . 'S'));
- $emailTemplate->addBodyText($this->l->t('This password will expire at %s', [$expirationTime->format('r')]));
- }
- $emailTemplate->addBodyText($this->l->t('You can choose a different password at any time in the share dialog.'));
- $emailTemplate->addFooter();
- $instanceName = $this->defaults->getName();
- $senderName = $this->l->t(
- '%1$s via %2$s',
- [
- $initiatorDisplayName,
- $instanceName
- ]
- );
- $message->setFrom([Util::getDefaultEmailAddress($instanceName) => $senderName]);
- $message->setTo([$initiatorEMailAddress => $initiatorDisplayName]);
- $message->useTemplate($emailTemplate);
- $this->mailer->send($message);
- $this->createPasswordSendActivity($share, $shareWith, true);
- return true;
- }
- private function getAbsoluteImagePath(string $path):string {
- return $this->urlGenerator->getAbsoluteURL(
- $this->urlGenerator->imagePath('core', $path)
- );
- }
-
- protected function generateToken(int $size = 15): string {
- $token = $this->secureRandom->generate($size, ISecureRandom::CHAR_HUMAN_READABLE);
- return $token;
- }
-
- public function getChildren(IShare $parent): array {
- $children = [];
- $qb = $this->dbConnection->getQueryBuilder();
- $qb->select('*')
- ->from('share')
- ->where($qb->expr()->eq('parent', $qb->createNamedParameter($parent->getId())))
- ->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_EMAIL)))
- ->orderBy('id');
- $cursor = $qb->executeQuery();
- while ($data = $cursor->fetch()) {
- $children[] = $this->createShareObject($data);
- }
- $cursor->closeCursor();
- return $children;
- }
-
- protected function addShareToDB(
- ?int $itemSource,
- ?string $itemType,
- ?string $shareWith,
- ?string $sharedBy,
- ?string $uidOwner,
- ?int $permissions,
- ?string $token,
- ?string $password,
- ?\DateTimeInterface $passwordExpirationTime,
- ?bool $sendPasswordByTalk,
- ?bool $hideDownload,
- ?string $label,
- ?\DateTimeInterface $expirationTime,
- ?string $note = '',
- ?IAttributes $attributes = null,
- ?bool $mailSend = true,
- ): int {
- $qb = $this->dbConnection->getQueryBuilder();
- $qb->insert('share')
- ->setValue('share_type', $qb->createNamedParameter(IShare::TYPE_EMAIL))
- ->setValue('item_type', $qb->createNamedParameter($itemType))
- ->setValue('item_source', $qb->createNamedParameter($itemSource))
- ->setValue('file_source', $qb->createNamedParameter($itemSource))
- ->setValue('share_with', $qb->createNamedParameter($shareWith))
- ->setValue('uid_owner', $qb->createNamedParameter($uidOwner))
- ->setValue('uid_initiator', $qb->createNamedParameter($sharedBy))
- ->setValue('permissions', $qb->createNamedParameter($permissions))
- ->setValue('token', $qb->createNamedParameter($token))
- ->setValue('password', $qb->createNamedParameter($password))
- ->setValue('password_expiration_time', $qb->createNamedParameter($passwordExpirationTime, IQueryBuilder::PARAM_DATETIME_MUTABLE))
- ->setValue('password_by_talk', $qb->createNamedParameter($sendPasswordByTalk, IQueryBuilder::PARAM_BOOL))
- ->setValue('stime', $qb->createNamedParameter(time()))
- ->setValue('hide_download', $qb->createNamedParameter((int)$hideDownload, IQueryBuilder::PARAM_INT))
- ->setValue('label', $qb->createNamedParameter($label))
- ->setValue('note', $qb->createNamedParameter($note))
- ->setValue('mail_send', $qb->createNamedParameter((int)$mailSend, IQueryBuilder::PARAM_INT));
-
- $shareAttributes = $this->formatShareAttributes($attributes);
- $qb->setValue('attributes', $qb->createNamedParameter($shareAttributes));
- if ($expirationTime !== null) {
- $qb->setValue('expiration', $qb->createNamedParameter($expirationTime, IQueryBuilder::PARAM_DATETIME_MUTABLE));
- }
- $qb->executeStatement();
- return $qb->getLastInsertId();
- }
-
- public function update(IShare $share, ?string $plainTextPassword = null): IShare {
- $originalShare = $this->getShareById($share->getId());
-
- $validPassword = $plainTextPassword !== null && $plainTextPassword !== '';
- if ($validPassword && ($originalShare->getPassword() !== $share->getPassword() ||
- ($originalShare->getSendPasswordByTalk() && !$share->getSendPasswordByTalk()))) {
- $emails = $this->getSharedWithEmails($share);
- $validEmails = array_filter($emails, function ($email) {
- return $this->mailer->validateMailAddress($email);
- });
- $this->sendPassword($share, $plainTextPassword, $validEmails);
- }
- $shareAttributes = $this->formatShareAttributes($share->getAttributes());
-
- $qb = $this->dbConnection->getQueryBuilder();
- $qb->update('share')
- ->where($qb->expr()->eq('id', $qb->createNamedParameter($share->getId())))
- ->set('item_source', $qb->createNamedParameter($share->getNodeId()))
- ->set('file_source', $qb->createNamedParameter($share->getNodeId()))
- ->set('share_with', $qb->createNamedParameter($share->getSharedWith()))
- ->set('permissions', $qb->createNamedParameter($share->getPermissions()))
- ->set('uid_owner', $qb->createNamedParameter($share->getShareOwner()))
- ->set('uid_initiator', $qb->createNamedParameter($share->getSharedBy()))
- ->set('password', $qb->createNamedParameter($share->getPassword()))
- ->set('password_expiration_time', $qb->createNamedParameter($share->getPasswordExpirationTime(), IQueryBuilder::PARAM_DATETIME_MUTABLE))
- ->set('label', $qb->createNamedParameter($share->getLabel()))
- ->set('password_by_talk', $qb->createNamedParameter($share->getSendPasswordByTalk(), IQueryBuilder::PARAM_BOOL))
- ->set('expiration', $qb->createNamedParameter($share->getExpirationDate(), IQueryBuilder::PARAM_DATETIME_MUTABLE))
- ->set('note', $qb->createNamedParameter($share->getNote()))
- ->set('hide_download', $qb->createNamedParameter((int)$share->getHideDownload(), IQueryBuilder::PARAM_INT))
- ->set('attributes', $qb->createNamedParameter($shareAttributes))
- ->set('mail_send', $qb->createNamedParameter((int)$share->getMailSend(), IQueryBuilder::PARAM_INT))
- ->set('reminder_sent', $qb->createNamedParameter($share->getReminderSent(), IQueryBuilder::PARAM_BOOL))
- ->executeStatement();
- if ($originalShare->getNote() !== $share->getNote() && $share->getNote() !== '') {
- $this->sendNote($share);
- }
- return $share;
- }
-
- public function move(IShare $share, $recipient): IShare {
-
- return $share;
- }
-
- public function delete(IShare $share): void {
- try {
- $this->createShareActivity($share, 'unshare');
- } catch (\Exception $e) {
- }
- $this->removeShareFromTable((int)$share->getId());
- }
-
- public function deleteFromSelf(IShare $share, $recipient): void {
-
- }
- public function restore(IShare $share, string $recipient): IShare {
- throw new GenericShareException('not implemented');
- }
-
- public function getSharesBy($userId, $shareType, $node, $reshares, $limit, $offset): array {
- $qb = $this->dbConnection->getQueryBuilder();
- $qb->select('*')
- ->from('share');
- $qb->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_EMAIL)));
-
- if ($reshares === false) {
-
- $or1 = $qb->expr()->andX(
- $qb->expr()->eq('uid_owner', $qb->createNamedParameter($userId)),
- $qb->expr()->isNull('uid_initiator')
- );
- $qb->andWhere(
- $qb->expr()->orX(
- $qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId)),
- $or1
- )
- );
- } elseif ($node === null) {
- $qb->andWhere(
- $qb->expr()->orX(
- $qb->expr()->eq('uid_owner', $qb->createNamedParameter($userId)),
- $qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId))
- )
- );
- }
- if ($node !== null) {
- $qb->andWhere($qb->expr()->eq('file_source', $qb->createNamedParameter($node->getId())));
- }
- if ($limit !== -1) {
- $qb->setMaxResults($limit);
- }
- $qb->setFirstResult($offset);
- $qb->orderBy('id');
- $cursor = $qb->executeQuery();
- $shares = [];
- while ($data = $cursor->fetch()) {
- $shares[] = $this->createShareObject($data);
- }
- $cursor->closeCursor();
- return $shares;
- }
-
- public function getShareById($id, $recipientId = null): IShare {
- $qb = $this->dbConnection->getQueryBuilder();
- $qb->select('*')
- ->from('share')
- ->where($qb->expr()->eq('id', $qb->createNamedParameter($id)))
- ->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_EMAIL)));
- $cursor = $qb->executeQuery();
- $data = $cursor->fetch();
- $cursor->closeCursor();
- if ($data === false) {
- throw new ShareNotFound();
- }
- try {
- $share = $this->createShareObject($data);
- } catch (InvalidShare $e) {
- throw new ShareNotFound();
- }
- return $share;
- }
-
- public function getSharesByPath(Node $path): array {
- $qb = $this->dbConnection->getQueryBuilder();
- $cursor = $qb->select('*')
- ->from('share')
- ->andWhere($qb->expr()->eq('file_source', $qb->createNamedParameter($path->getId())))
- ->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_EMAIL)))
- ->executeQuery();
- $shares = [];
- while ($data = $cursor->fetch()) {
- $shares[] = $this->createShareObject($data);
- }
- $cursor->closeCursor();
- return $shares;
- }
-
- public function getSharedWith($userId, $shareType, $node, $limit, $offset): array {
-
- $shares = [];
-
- $qb = $this->dbConnection->getQueryBuilder();
- $qb->select('*')
- ->from('share');
-
- $qb->orderBy('id');
-
- if ($limit !== -1) {
- $qb->setMaxResults($limit);
- }
- $qb->setFirstResult($offset);
- $qb->where($qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_EMAIL)));
- $qb->andWhere($qb->expr()->eq('share_with', $qb->createNamedParameter($userId)));
-
- if ($node !== null) {
- $qb->andWhere($qb->expr()->eq('file_source', $qb->createNamedParameter($node->getId())));
- }
- $cursor = $qb->executeQuery();
- while ($data = $cursor->fetch()) {
- $shares[] = $this->createShareObject($data);
- }
- $cursor->closeCursor();
- return $shares;
- }
-
- public function getShareByToken($token): IShare {
- $qb = $this->dbConnection->getQueryBuilder();
- $cursor = $qb->select('*')
- ->from('share')
- ->where($qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_EMAIL)))
- ->andWhere($qb->expr()->eq('token', $qb->createNamedParameter($token)))
- ->executeQuery();
- $data = $cursor->fetch();
- if ($data === false) {
- throw new ShareNotFound('Share not found', $this->l->t('Could not find share'));
- }
- try {
- $share = $this->createShareObject($data);
- } catch (InvalidShare $e) {
- throw new ShareNotFound('Share not found', $this->l->t('Could not find share'));
- }
- return $share;
- }
-
- protected function removeShareFromTable(int $shareId): void {
- $qb = $this->dbConnection->getQueryBuilder();
- $qb->delete('share')
- ->where($qb->expr()->eq('id', $qb->createNamedParameter($shareId)));
- $qb->executeStatement();
- }
-
- protected function createShareObject(array $data): IShare {
- $share = new Share($this->rootFolder, $this->userManager);
- $share->setId((int)$data['id'])
- ->setShareType((int)$data['share_type'])
- ->setPermissions((int)$data['permissions'])
- ->setTarget($data['file_target'])
- ->setMailSend((bool)$data['mail_send'])
- ->setNote($data['note'])
- ->setToken($data['token']);
- $shareTime = new \DateTime();
- $shareTime->setTimestamp((int)$data['stime']);
- $share->setShareTime($shareTime);
- $share->setSharedWith($data['share_with'] ?? '');
- $share->setPassword($data['password']);
- $passwordExpirationTime = \DateTime::createFromFormat('Y-m-d H:i:s', $data['password_expiration_time'] ?? '');
- $share->setPasswordExpirationTime($passwordExpirationTime !== false ? $passwordExpirationTime : null);
- $share->setLabel($data['label']);
- $share->setSendPasswordByTalk((bool)$data['password_by_talk']);
- $share->setHideDownload((bool)$data['hide_download']);
- $share->setReminderSent((bool)$data['reminder_sent']);
- if ($data['uid_initiator'] !== null) {
- $share->setShareOwner($data['uid_owner']);
- $share->setSharedBy($data['uid_initiator']);
- } else {
-
- $share->setSharedBy($data['uid_owner']);
- $path = $this->getNode($share->getSharedBy(), (int)$data['file_source']);
- $owner = $path->getOwner();
- $share->setShareOwner($owner->getUID());
- }
- if ($data['expiration'] !== null) {
- $expiration = \DateTime::createFromFormat('Y-m-d H:i:s', $data['expiration']);
- if ($expiration !== false) {
- $share->setExpirationDate($expiration);
- }
- }
- $share = $this->updateShareAttributes($share, $data['attributes']);
- $share->setNodeId((int)$data['file_source']);
- $share->setNodeType($data['item_type']);
- $share->setProviderId($this->identifier());
- return $share;
- }
-
- private function getNode(string $userId, int $id): Node {
- try {
- $userFolder = $this->rootFolder->getUserFolder($userId);
- } catch (NoUserException $e) {
- throw new InvalidShare();
- }
- $nodes = $userFolder->getById($id);
- if (empty($nodes)) {
- throw new InvalidShare();
- }
- return $nodes[0];
- }
-
- public function userDeleted($uid, $shareType): void {
- $qb = $this->dbConnection->getQueryBuilder();
- $qb->delete('share')
- ->where($qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_EMAIL)))
- ->andWhere($qb->expr()->eq('uid_owner', $qb->createNamedParameter($uid)))
- ->executeStatement();
- }
-
- public function groupDeleted($gid): void {
- }
-
- public function userDeletedFromGroup($uid, $gid): void {
- }
-
- protected function getRawShare(int $id): array {
-
- $qb = $this->dbConnection->getQueryBuilder();
- $qb->select('*')
- ->from('share')
- ->where($qb->expr()->eq('id', $qb->createNamedParameter($id)));
- $cursor = $qb->executeQuery();
- $data = $cursor->fetch();
- $cursor->closeCursor();
- if ($data === false) {
- throw new ShareNotFound;
- }
- return $data;
- }
- public function getSharesInFolder($userId, Folder $node, $reshares, $shallow = true): array {
- $qb = $this->dbConnection->getQueryBuilder();
- $qb->select('*')
- ->from('share', 's')
- ->andWhere($qb->expr()->orX(
- $qb->expr()->eq('item_type', $qb->createNamedParameter('file')),
- $qb->expr()->eq('item_type', $qb->createNamedParameter('folder'))
- ))
- ->andWhere(
- $qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_EMAIL))
- );
-
- if ($reshares === false) {
- $qb->andWhere($qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId)));
- } else {
- $qb->andWhere(
- $qb->expr()->orX(
- $qb->expr()->eq('uid_owner', $qb->createNamedParameter($userId)),
- $qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId))
- )
- );
- }
- $qb->innerJoin('s', 'filecache', 'f', $qb->expr()->eq('s.file_source', 'f.fileid'));
- $qb->andWhere($qb->expr()->eq('f.parent', $qb->createNamedParameter($node->getId())));
- $qb->orderBy('id');
- $cursor = $qb->executeQuery();
- $shares = [];
- while ($data = $cursor->fetch()) {
- $shares[$data['fileid']][] = $this->createShareObject($data);
- }
- $cursor->closeCursor();
- return $shares;
- }
-
- public function getAccessList($nodes, $currentAccess): array {
- $ids = [];
- foreach ($nodes as $node) {
- $ids[] = $node->getId();
- }
- $qb = $this->dbConnection->getQueryBuilder();
- $qb->select('share_with', 'file_source', 'token')
- ->from('share')
- ->where($qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_EMAIL)))
- ->andWhere($qb->expr()->in('file_source', $qb->createNamedParameter($ids, IQueryBuilder::PARAM_INT_ARRAY)))
- ->andWhere($qb->expr()->orX(
- $qb->expr()->eq('item_type', $qb->createNamedParameter('file')),
- $qb->expr()->eq('item_type', $qb->createNamedParameter('folder'))
- ));
- $cursor = $qb->executeQuery();
- $public = false;
- $mail = [];
- while ($row = $cursor->fetch()) {
- $public = true;
- if ($currentAccess === false) {
- $mail[] = $row['share_with'];
- } else {
- $mail[$row['share_with']] = [
- 'node_id' => $row['file_source'],
- 'token' => $row['token']
- ];
- }
- }
- $cursor->closeCursor();
- return ['public' => $public, 'mail' => $mail];
- }
- public function getAllShares(): iterable {
- $qb = $this->dbConnection->getQueryBuilder();
- $qb->select('*')
- ->from('share')
- ->where(
- $qb->expr()->orX(
- $qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_EMAIL))
- )
- );
- $cursor = $qb->executeQuery();
- while ($data = $cursor->fetch()) {
- try {
- $share = $this->createShareObject($data);
- } catch (InvalidShare $e) {
- continue;
- } catch (ShareNotFound $e) {
- continue;
- }
- yield $share;
- }
- $cursor->closeCursor();
- }
-
- protected function getSharedWithEmails(IShare $share): array {
- $attributes = $share->getAttributes();
- if ($attributes === null) {
- return [$share->getSharedWith()];
- }
- $emails = $attributes->getAttribute('shareWith', 'emails');
- if (isset($emails) && is_array($emails) && !empty($emails)) {
- return $emails;
- }
- return [$share->getSharedWith()];
- }
- }
|