/** * @param array $httpVars * @param ShareLink $shareObject * @param bool $update * @param null $guestUserPass * @return array * @throws Exception */ public function prepareSharedUserEntry($httpVars, &$shareObject, $update, $guestUserPass = null) { $userPass = null; $forcePassword = $this->options["SHARE_FORCE_PASSWORD"]; if ($forcePassword && (isset($httpVars["create_guest_user"]) && $httpVars["create_guest_user"] == "true" && empty($guestUserPass) || isset($httpVars["guest_user_id"]) && isset($guestUserPass) && strlen($guestUserPass) == 0)) { $mess = ConfService::getMessages(); throw new Exception($mess["share_center.175"]); } if ($update) { // THIS IS AN EXISTING SHARE // FIND SHARE AND EXISTING HIDDEN USER ID if ($shareObject->isAttachedToRepository()) { $existingRepo = $shareObject->getRepository(); $this->store->testUserCanEditShare($existingRepo->getOwner(), $existingRepo->options); } $uniqueUser = $shareObject->getUniqueUser(); if ($guestUserPass !== null && strlen($guestUserPass)) { $userPass = $guestUserPass; $shareObject->setUniqueUser($uniqueUser, true); } else { if (!$shareObject->shouldRequirePassword() || $guestUserPass !== null && $guestUserPass == "") { $shareObject->setUniqueUser($uniqueUser, false); } } if ($update && $forcePassword && !$shareObject instanceof \Pydio\OCS\Model\TargettedLink && !$shareObject->shouldRequirePassword() && empty($guestUserPass)) { $mess = ConfService::getMessages(); throw new Exception($mess["share_center.175"]); } } else { $update = false; $shareObject->createHiddenUserId($this->options["SHARED_USERS_TMP_PREFIX"], !empty($guestUserPass)); if (!empty($guestUserPass)) { $userPass = $guestUserPass; } else { $userPass = $shareObject->createHiddenUserPassword(); } $uniqueUser = $shareObject->getUniqueUser(); } $hiddenUserEntry = $this->createHiddenUserEntry($httpVars, $uniqueUser, $userPass, $update); if (empty($hiddenUserEntry["RIGHT"])) { $mess = ConfService::getMessages(); throw new Exception($mess["share_center.58"]); } $hiddenUserEntry["DISABLE_DOWNLOAD"] = $shareObject->disableDownload(); if ($shareObject instanceof \Pydio\OCS\Model\TargettedLink) { $hiddenUserEntry["REMOTE"] = true; } return $hiddenUserEntry; }
/** * @param PublicAccessManager $publicAccessManager * @param array $messages * @return mixed * @throws Exception */ public function getJsonData($publicAccessManager, $messages) { $storedData = $this->internal; $minisiteIsPublic = isset($storedData["PRELOG_USER"]); $dlDisabled = isset($storedData["DOWNLOAD_DISABLED"]) && $storedData["DOWNLOAD_DISABLED"] === true; $shareMeta = isset($this->additionalMeta) ? $this->additionalMeta : array(); $internalUserId = isset($storedData["PRELOG_USER"]) ? $storedData["PRELOG_USER"] : $storedData["PRESET_LOGIN"]; if (empty($internalUserId)) { throw new Exception("Oups, link " . $this->getHash() . " has no internal user id, this is not normal."); } $jsonData = array("public" => $minisiteIsPublic ? "true" : "false", "disable_download" => $dlDisabled, "hash" => $this->getHash(), "hash_is_shorten" => isset($shareMeta["short_form_url"]) || isset($this->internal["SHORT_FORM_URL"]), "internal_user_id" => $internalUserId); if (!isset($storedData["TARGET"]) || $storedData["TARGET"] == "public") { if (isset($shareMeta["short_form_url"])) { $jsonData["public_link"] = $shareMeta["short_form_url"]; } else { if (isset($this->internal["SHORT_FORM_URL"])) { $jsonData["public_link"] = $this->getShortFormUrl(); } else { $jsonData["public_link"] = $publicAccessManager->buildPublicLink($this->getHash()); } } } if (!empty($storedData["DOWNLOAD_LIMIT"]) && !$dlDisabled) { $jsonData["download_counter"] = $this->store->getCurrentDownloadCounter($this->getHash()); $jsonData["download_limit"] = $storedData["DOWNLOAD_LIMIT"]; } if (!empty($storedData["EXPIRE_TIME"])) { $delta = $storedData["EXPIRE_TIME"] - time(); $days = round($delta / (60 * 60 * 24)); $jsonData["expire_time"] = date($messages["date_format"], $storedData["EXPIRE_TIME"]); $jsonData["expire_after"] = $days; } else { $jsonData["expire_after"] = 0; } $jsonData["is_expired"] = $this->store->isShareExpired($this->getHash(), $storedData); if (isset($storedData["AJXP_TEMPLATE_NAME"])) { $jsonData["minisite_layout"] = $storedData["AJXP_TEMPLATE_NAME"]; } if (!$minisiteIsPublic) { $jsonData["has_password"] = true; } foreach ($this->store->modifiableShareKeys as $key) { if (isset($storedData[$key])) { $jsonData[$key] = $storedData[$key]; } } return $jsonData; }
/** * @param ShareCenter $shareCenter * @param ShareStore $shareStore * @param ShareRightsManager $shareRightManager */ public static function migrateLegacyMeta($shareCenter, $shareStore, $shareRightManager, $dryRun = true) { $metaStoreDir = AJXP_DATA_PATH . "/plugins/metastore.serial"; $publicFolder = ConfService::getCoreConf("PUBLIC_DOWNLOAD_FOLDER"); $metastores = glob($metaStoreDir . "/ajxp_meta_0"); if ($dryRun) { print "RUNNING A DRY RUN FOR META MIGRATION"; } foreach ($metastores as $store) { if (strpos($store, ".bak") !== false) { continue; } // Backup store if (!$dryRun) { copy($store, $store . ".bak"); } $data = unserialize(file_get_contents($store)); foreach ($data as $filePath => &$metadata) { foreach ($metadata as $userName => &$meta) { if (!AuthService::userExists($userName)) { continue; } $userObject = ConfService::getConfStorageImpl()->createUserObject($userName); if (isset($meta["ajxp_shared"]) && isset($meta["ajxp_shared"]["element"])) { print "\n\nItem {$filePath} requires upgrade :"; $share = $meta["ajxp_shared"]; $element = $meta["ajxp_shared"]["element"]; if (is_array($element)) { $element = array_shift(array_keys($element)); } // Take the first one only $legacyLinkFile = $publicFolder . "/" . $element . ".php"; if (file_exists($legacyLinkFile)) { // Load file, move it to DB and move the meta $publiclet = $shareStore->loadShare($element); rename($legacyLinkFile, $legacyLinkFile . ".migrated"); if (isset($share["minisite"])) { print "\n--Migrate legacy minisite to new minisite?"; try { $sharedRepoId = $publiclet["REPOSITORY"]; $sharedRepo = ConfService::getRepositoryById($sharedRepoId); if ($sharedRepo == null) { print "\n--ERROR: Cannot find repository with id " . $sharedRepoId; continue; } $shareLink = new ShareLink($shareStore, $publiclet); $user = $shareLink->getUniqueUser(); if (AuthService::userExists($user)) { $userObject = ConfService::getConfStorageImpl()->createUserObject($user); $userObject->setHidden(true); print "\n--Should set existing user {$user} as hidden"; if (!$dryRun) { $userObject->save(); } } $shareLink->parseHttpVars(["custom_handle" => $element]); $shareLink->setParentRepositoryId($sharedRepo->getParentId()); print "\n--Creating the following share object"; print_r($shareLink->getJsonData($shareCenter->getPublicAccessManager(), ConfService::getMessages())); if (!$dryRun) { $shareLink->save(); } $meta["ajxp_shared"] = ["shares" => [$element => ["type" => "minisite"], $sharedRepoId => ["type" => "repository"]]]; } catch (Exception $e) { print "\n-- Error " . $e->getMessage(); } } else { print "\n--Should migrate legacy link to new minisite with ContentFilter"; try { $link = new ShareLink($shareStore); $link->setOwnerId($userName); $parameters = array("custom_handle" => $element, "simple_right_download" => true); if (isset($publiclet["EXPIRE_TIME"])) { $parameters["expiration"] = $publiclet["EXPIRE_TIME"]; } if (isset($publiclet["DOWNLOAD_LIMIT"])) { $parameters["downloadlimit"] = $publiclet["DOWNLOAD_LIMIT"]; } $link->parseHttpVars($parameters); $parentRepositoryObject = $publiclet["REPOSITORY"]; $driverInstance = AJXP_PluginsService::findPlugin("access", $parentRepositoryObject->getAccessType()); if (empty($driverInstance)) { print "\n-- ERROR: Cannot find driver instance!"; continue; } $options = $driverInstance->makeSharedRepositoryOptions(["file" => "/"], $parentRepositoryObject); $options["SHARE_ACCESS"] = "private"; $newRepo = $parentRepositoryObject->createSharedChild(basename($filePath), $options, $parentRepositoryObject->getId(), $userObject->getId(), null); $gPath = $userObject->getGroupPath(); if (!empty($gPath) && !ConfService::getCoreConf("CROSSUSERS_ALLGROUPS", "conf")) { $newRepo->setGroupPath($gPath); } $newRepo->setDescription(""); // Smells like dirty hack! $newRepo->options["PATH"] = SystemTextEncoding::fromStorageEncoding($newRepo->options["PATH"]); $newRepo->setContentFilter(new ContentFilter([new AJXP_Node("pydio://" . $parentRepositoryObject->getId() . $filePath)])); if (!$dryRun) { ConfService::addRepository($newRepo); } $hiddenUserEntry = $shareRightManager->prepareSharedUserEntry(["simple_right_read" => true, "simple_right_download" => true], $link, false, null); $selection = new UserSelection($parentRepositoryObject, []); $selection->addFile($filePath); if (!$dryRun) { $shareRightManager->assignSharedRepositoryPermissions($parentRepositoryObject, $newRepo, false, [$hiddenUserEntry["ID"] => $hiddenUserEntry], [], $selection); } $link->setParentRepositoryId($parentRepositoryObject->getId()); $link->attachToRepository($newRepo->getId()); print "\n-- Should save following LINK: "; print_r($link->getJsonData($shareCenter->getPublicAccessManager(), ConfService::getMessages())); if (!$dryRun) { $hash = $link->save(); } // UPDATE METADATA $meta["ajxp_shared"] = ["shares" => [$element => array("type" => "minisite")]]; } catch (Exception $e) { print "\n-- ERROR: " . $e->getMessage(); } } if ($dryRun) { rename($legacyLinkFile . ".migrated", $legacyLinkFile); } continue; } else { // // File does not exists, remove meta // unset($meta["ajxp_shared"]); } $repo = ConfService::getRepositoryById($element); if ($repo !== null) { print "\n--Shared repository: just metadata"; // Shared repo, migrating the meta should be enough $meta["ajxp_shared"] = array("shares" => [$element => array("type" => "repository")]); } } } } print "\n\n SHOULD NOW UPDATE METADATA WITH FOLLOWING :"; print_r($data); if (!$dryRun) { file_put_contents($store, serialize($data)); } } }
/** * @param AJXP_Node $node * @param array $shares * @param bool $clearIfEmpty */ public function getSharesFromMeta($node, &$shares, $clearIfEmpty = false) { $meta = $this->getNodeMeta($node); // NEW FORMAT if (isset($meta["shares"])) { $shares = array(); $update = false; foreach ($meta["shares"] as $hashOrRepoId => $shareData) { $type = $shareData["type"]; if (is_array($type)) { $shareData["type"] = $type[0]; } if (!$clearIfEmpty || $this->shareStore->shareExists($shareData["type"], $hashOrRepoId)) { $shares[$hashOrRepoId] = $shareData; } else { $update = true; } } if ($update && !count($shares)) { $this->clearNodeMeta($node); } return; } // OLD FORMAT if (isset($meta["minisite"])) { $type = "minisite"; } else { $type = "detect"; } $els = array(); if (is_string($meta["element"])) { $els[] = $meta["element"]; } else { if (is_array($meta["element"])) { $els = $meta["element"]; } } if ($clearIfEmpty) { $update = false; $shares = array(); foreach ($els as $hashOrRepoId => $additionalData) { if (is_string($additionalData)) { $hashOrRepoId = $additionalData; $additionalData = array(); } if ($type == "detect") { if (ConfService::getRepositoryById($hashOrRepoId) != null) { $type = "repository"; } else { $type = "file"; } } if ($this->shareStore->shareExists($type, $hashOrRepoId)) { $shares[$hashOrRepoId] = array_merge($additionalData, array("type" => $type)); } else { $update = true; } } if ($update && !count($shares)) { $this->clearNodeMeta($node); } } else { $shares = $els; } }
/** * @param String $shareId * @param Array $shareData * @param AJXP_Node $node * @throws Exception * @return array|bool */ public function shareToJson($shareId, $shareData, $node = null) { $messages = ConfService::getMessages(); $jsonData = array(); $elementWatch = false; if ($shareData["type"] == "file") { $pData = $this->getShareStore()->loadShare($shareId); if (!count($pData)) { return false; } foreach ($this->getShareStore()->modifiableShareKeys as $key) { if (isset($pData[$key])) { $shareData[$key] = $pData[$key]; } } if ($pData["OWNER_ID"] != AuthService::getLoggedUser()->getId() && !AuthService::getLoggedUser()->isAdmin()) { throw new Exception($messages["share_center.48"]); } if (isset($shareData["short_form_url"])) { $link = $shareData["short_form_url"]; } else { $link = $this->buildPublicletLink($shareId); } if ($this->watcher != false && $node != null) { $result = array(); $elementWatch = $this->watcher->hasWatchOnNode($node, AuthService::getLoggedUser()->getId(), MetaWatchRegister::$META_WATCH_USERS_NAMESPACE, $result); if ($elementWatch && !in_array($shareId, $result)) { $elementWatch = false; } } $jsonData = array_merge(array("element_id" => $shareId, "publiclet_link" => $link, "download_counter" => $this->getShareStore()->getCurrentDownloadCounter($shareId), "download_limit" => $pData["DOWNLOAD_LIMIT"], "expire_time" => $pData["EXPIRE_TIME"] != 0 ? date($messages["date_format"], $pData["EXPIRE_TIME"]) : 0, "has_password" => !empty($pData["PASSWORD"]), "element_watch" => $elementWatch, "is_expired" => $this->shareStore->isShareExpired($shareId, $pData)), $shareData); } else { if ($shareData["type"] == "minisite" || $shareData["type"] == "repository") { $repoId = $shareId; if (strpos($repoId, "repo-") === 0) { // Legacy $repoId = str_replace("repo-", "", $repoId); $shareData["type"] = "repository"; } $minisite = $shareData["type"] == "minisite"; $minisiteIsPublic = false; $dlDisabled = false; $minisiteLink = ''; if ($minisite) { $minisiteData = $this->getShareStore()->loadShare($shareId); $repoId = $minisiteData["REPOSITORY"]; $minisiteIsPublic = isset($minisiteData["PRELOG_USER"]); $dlDisabled = isset($minisiteData["DOWNLOAD_DISABLED"]) && $minisiteData["DOWNLOAD_DISABLED"] === true; if (isset($shareData["short_form_url"])) { $minisiteLink = $shareData["short_form_url"]; } else { $minisiteLink = $this->buildPublicletLink($shareId); } } $notExistsData = array("error" => true, "repositoryId" => $repoId, "users_number" => 0, "label" => "Error - Cannot find shared data", "description" => "Cannot find repository", "entries" => array(), "element_watch" => false, "repository_url" => ""); $repo = ConfService::getRepositoryById($repoId); if ($repoId == null || $repo == null && $node != null) { if ($minisite) { $this->removeShareFromMeta($node, $shareId); } return $notExistsData; } else { if (!AuthService::getLoggedUser()->isAdmin() && $repo->getOwner() != AuthService::getLoggedUser()->getId()) { return $notExistsData; } } if ($this->watcher != false && $node != null) { $elementWatch = $this->watcher->hasWatchOnNode(new AJXP_Node($this->baseProtocol . "://" . $repoId . "/"), AuthService::getLoggedUser()->getId(), MetaWatchRegister::$META_WATCH_NAMESPACE); } if ($node != null) { $sharedEntries = $this->computeSharedRepositoryAccessRights($repoId, true, $node->getUrl()); } else { $sharedEntries = $this->computeSharedRepositoryAccessRights($repoId, true, null); } $cFilter = $repo->getContentFilter(); if (!empty($cFilter)) { $cFilter = $cFilter->toArray(); } $jsonData = array("repositoryId" => $repoId, "users_number" => AuthService::countUsersForRepository($repoId), "label" => $repo->getDisplay(), "description" => $repo->getDescription(), "entries" => $sharedEntries, "element_watch" => $elementWatch, "repository_url" => AJXP_Utils::detectServerURL(true) . "?goto=" . $repo->getSlug() . "/", "content_filter" => $cFilter); if (isset($minisiteData)) { if (!empty($minisiteData["DOWNLOAD_LIMIT"]) && !$dlDisabled) { $jsonData["download_counter"] = $this->getShareStore()->getCurrentDownloadCounter($shareId); $jsonData["download_limit"] = $minisiteData["DOWNLOAD_LIMIT"]; } if (!empty($minisiteData["EXPIRE_TIME"])) { $delta = $minisiteData["EXPIRE_TIME"] - time(); $days = round($delta / (60 * 60 * 24)); $jsonData["expire_time"] = date($messages["date_format"], $minisiteData["EXPIRE_TIME"]); $jsonData["expire_after"] = $days; } else { $jsonData["expire_after"] = 0; } $jsonData["is_expired"] = $this->shareStore->isShareExpired($shareId, $minisiteData); if (isset($minisiteData["AJXP_TEMPLATE_NAME"])) { $jsonData["minisite_layout"] = $minisiteData["AJXP_TEMPLATE_NAME"]; } if (!$minisiteIsPublic) { $jsonData["has_password"] = true; } $jsonData["minisite"] = array("public" => $minisiteIsPublic ? "true" : "false", "public_link" => $minisiteLink, "disable_download" => $dlDisabled, "hash" => $shareId, "hash_is_shorten" => isset($shareData["short_form_url"])); foreach ($this->getShareStore()->modifiableShareKeys as $key) { if (isset($minisiteData[$key])) { $jsonData[$key] = $minisiteData[$key]; } } } } } return $jsonData; }
/** * Authenticates the user based on the current request. * * If authentication is successful, true must be returned. * If authentication fails, an exception must be thrown. * * @param DAV\Server $server * @param string $realm * @throws DAV\Exception\NotAuthenticated * @return bool */ public function authenticate(DAV\Server $server, $realm) { $auth = new BasicAuthNoPass(); $auth->setHTTPRequest($server->httpRequest); $auth->setHTTPResponse($server->httpResponse); $auth->setRealm($realm); $userpass = $auth->getUserPass(); if (!$userpass) { $auth->requireLogin(); throw new DAV\Exception\NotAuthenticated('No basic authentication headers were found'); } // Authenticates the user $token = $userpass[0]; $shareStore = new \ShareStore(\ConfService::getCoreConf("PUBLIC_DOWNLOAD_FOLDER")); $shareData = $shareStore->loadShare($token); if (is_array($shareData)) { $this->shareData = $shareData; } else { $auth->requireLogin(); throw new DAV\Exception\NotAuthenticated('Username or password does not match'); } if (!$this->validateUserPass($userpass[0], $userpass[1])) { $auth->requireLogin(); throw new DAV\Exception\NotAuthenticated('Username or password does not match'); } $repositoryId = $this->shareData["REPOSITORY"]; $repository = \ConfService::getRepositoryById($repositoryId); if ($repository == null) { $repository = \ConfService::getRepositoryByAlias($repositoryId); } if ($repository == null) { throw new DAV\Exception\NotAuthenticated('Username cannot access any repository'); } else { $this->rootCollection->updateRepository($repository); } $this->currentUser = $userpass[0]; return true; }
/** * Not used for the moment * This will expose folder as /dav/FolderName and file as /dav/FileName.txt * * @param $baseUri * @return \AJXP_Sabre_Collection|SharingCollection * @throws \Exception */ protected function initCollectionForFileOrFolderAsUniqueItem(&$baseUri) { try { $testBackend = new BasicAuthNoPass(); $userPass = $testBackend->getUserPass(); if (isset($userPass[0])) { $shareStore = new \ShareStore(\ConfService::getCoreConf("PUBLIC_DOWNLOAD_FOLDER")); $shareData = $shareStore->loadShare($userPass[0]); if (isset($shareData) && isset($shareData["REPOSITORY"])) { $repo = \ConfService::getRepositoryById($shareData["REPOSITORY"]); if (!empty($repo) && !$repo->hasContentFilter()) { $baseDir = basename($repo->getOption("PATH")); } } } } catch (\Exception $e) { } $rootCollection = new \AJXP_Sabre_Collection("/", null, null); if (isset($baseDir)) { $currentPath = parse_url($_SERVER["REQUEST_URI"], PHP_URL_PATH); if ($currentPath == $baseUri || $currentPath == $baseUri . "/") { $rootCollection = new SharingCollection("/", null, null); } else { $baseUri .= "/{$baseDir}"; } } return $rootCollection; }