/** * Enter description here... * */ public function stream_close() { if ($this->fp !== null) { fclose($this->fp); if (self::$linkNode !== null) { ConfService::loadDriverForRepository(self::$linkNode->getRepository()); } } }
/** * @param AJXP_Node $node * @param string $cacheType * @param string $details * @return string */ public static function computeIdForNode($node, $cacheType, $details = '') { $repo = $node->getRepository(); if ($repo == null) { return "failed-id"; } $scope = $repo->securityScope(); $additional = ""; if ($scope === "USER") { $additional = AuthService::getLoggedUser()->getId() . "@"; } else { if ($scope == "GROUP") { $additional = ltrim(str_replace("/", "__", AuthService::getLoggedUser()->getGroupPath()), "__") . "@"; } } $scheme = parse_url($node->getUrl(), PHP_URL_SCHEME); return str_replace($scheme . "://", $cacheType . "://" . $additional, $node->getUrl()) . ($details ? "##" . $details : ""); }
/** * @param AJXP_Node $oldNode * @param AJXP_Node $newNode * @param bool $copy */ public function updateNodesIndex($oldNode = null, $newNode = null, $copy = false) { if (!dibi::isConnected()) { dibi::connect($this->sqlDriver); } //$this->logInfo("Syncable index", array($oldNode == null?'null':$oldNode->getUrl(), $newNode == null?'null':$newNode->getUrl())); try { if ($newNode != null && $this->excludeNode($newNode)) { // CREATE if ($oldNode == null) { AJXP_Logger::debug("Ignoring " . $newNode->getUrl() . " for indexation"); return; } else { AJXP_Logger::debug("Target node is excluded, see it as a deletion: " . $newNode->getUrl()); $newNode = null; } } if ($newNode == null) { $repoId = $this->computeIdentifier($oldNode->getRepository(), $oldNode->getUser()); // DELETE $this->logDebug('DELETE', $oldNode->getUrl()); dibi::query("DELETE FROM [ajxp_index] WHERE [node_path] LIKE %like~ AND [repository_identifier] = %s", SystemTextEncoding::toUTF8($oldNode->getPath()), $repoId); } else { if ($oldNode == null || $copy) { // CREATE $stat = stat($newNode->getUrl()); $newNode->setLeaf(!($stat['mode'] & 040000)); $this->logDebug('INSERT', $newNode->getUrl()); dibi::query("INSERT INTO [ajxp_index]", array("node_path" => SystemTextEncoding::toUTF8($newNode->getPath()), "bytesize" => $stat["size"], "mtime" => $stat["mtime"], "md5" => $newNode->isLeaf() ? md5_file($newNode->getUrl()) : "directory", "repository_identifier" => $repoId = $this->computeIdentifier($newNode->getRepository(), $newNode->getUser()))); } else { $repoId = $this->computeIdentifier($oldNode->getRepository(), $oldNode->getUser()); if ($oldNode->getPath() == $newNode->getPath()) { // CONTENT CHANGE clearstatcache(); $stat = stat($newNode->getUrl()); $this->logDebug("Content changed", "current stat size is : " . $stat["size"]); $this->logDebug('UPDATE CONTENT', $newNode->getUrl()); dibi::query("UPDATE [ajxp_index] SET ", array("bytesize" => $stat["size"], "mtime" => $stat["mtime"], "md5" => md5_file($newNode->getUrl())), "WHERE [node_path] = %s AND [repository_identifier] = %s", SystemTextEncoding::toUTF8($oldNode->getPath()), $repoId); try { $rowCount = dibi::getAffectedRows(); if ($rowCount === 0) { $this->logError(__FUNCTION__, "There was an update event on a non-indexed node (" . $newNode->getPath() . "), creating index entry!"); $this->updateNodesIndex(null, $newNode, false); } } catch (Exception $e) { } } else { // PATH CHANGE ONLY $newNode->loadNodeInfo(); if ($newNode->isLeaf()) { $this->logDebug('UPDATE LEAF PATH', $newNode->getUrl()); dibi::query("UPDATE [ajxp_index] SET ", array("node_path" => SystemTextEncoding::toUTF8($newNode->getPath())), "WHERE [node_path] = %s AND [repository_identifier] = %s", SystemTextEncoding::toUTF8($oldNode->getPath()), $repoId); try { $rowCount = dibi::getAffectedRows(); if ($rowCount === 0) { $this->logError(__FUNCTION__, "There was an update event on a non-indexed node (" . $newNode->getPath() . "), creating index entry!"); $this->updateNodesIndex(null, $newNode, false); } } catch (Exception $e) { } } else { $this->logDebug('UPDATE FOLDER PATH', $newNode->getUrl()); dibi::query("UPDATE [ajxp_index] SET [node_path]=REPLACE( REPLACE(CONCAT('\$\$\$',[node_path]), CONCAT('\$\$\$', %s), CONCAT('\$\$\$', %s)) , '\$\$\$', '') ", $oldNode->getPath(), $newNode->getPath(), "WHERE [node_path] LIKE %like~ AND [repository_identifier] = %s", SystemTextEncoding::toUTF8($oldNode->getPath()), $repoId); try { $rowCount = dibi::getAffectedRows(); if ($rowCount === 0) { $this->logError(__FUNCTION__, "There was an update event on a non-indexed folder (" . $newNode->getPath() . "), relaunching a recursive indexation!"); AJXP_Controller::findActionAndApply("index", array("file" => $newNode->getPath()), array()); } } catch (Exception $e) { } } } } } } catch (Exception $e) { AJXP_Logger::error("[meta.syncable]", "Exception", $e->getTraceAsString()); AJXP_Logger::error("[meta.syncable]", "Indexation", $e->getMessage()); } }
/** * @param String $watchType * @param String $currentUserId * @param AJXP_Node $node * @param array|bool $watchMeta * @param array|bool $usersMeta * @return array */ private function loadWatchesFromMeta($watchType, $currentUserId, $node, $watchMeta = false, $usersMeta = false) { $IDS = array(); if ($usersMeta !== false) { if ($watchType == self::$META_WATCH_CHANGE && isset($usersMeta[self::$META_WATCH_USERS_CHANGE])) { $usersMeta = $usersMeta[self::$META_WATCH_USERS_CHANGE]; } else { if ($watchType == self::$META_WATCH_READ && isset($usersMeta[self::$META_WATCH_USERS_READ])) { $usersMeta = $usersMeta[self::$META_WATCH_USERS_READ]; } else { $usersMeta = null; } } } if (!empty($watchMeta) && is_array($watchMeta)) { foreach ($watchMeta as $id => $type) { if ($type == $watchType || $type == self::$META_WATCH_BOTH) { $IDS[] = $id; } } } if (!empty($usersMeta) && is_array($usersMeta)) { foreach ($usersMeta as $id => $targetUsers) { if (in_array($currentUserId, $targetUsers)) { $IDS[] = $id; } } } if (count($IDS)) { $changes = false; foreach ($IDS as $index => $id) { if ($currentUserId == $id && !AJXP_SERVER_DEBUG) { // In non-debug mode, do not send notifications to watcher! unset($IDS[$index]); continue; } if (!AuthService::userExists($id)) { unset($IDS[$index]); if (is_array($watchMeta)) { $changes = true; $watchMeta[$id] = AJXP_VALUE_CLEAR; } } else { // Make sure the user is still authorized on this node, otherwise remove it. $uObject = ConfService::getConfStorageImpl()->createUserObject($id); $acl = $uObject->mergedRole->getAcl($node->getRepositoryId()); $isOwner = $node->getRepository()->getOwner() == $uObject->getId(); if (!$isOwner && (empty($acl) || strpos($acl, "r") === FALSE)) { unset($IDS[$index]); if (is_array($watchMeta)) { $changes = true; $watchMeta[$id] = AJXP_VALUE_CLEAR; } } } } if ($changes) { $node->setMetadata(self::$META_WATCH_NAMESPACE, $watchMeta, false, AJXP_METADATA_SCOPE_REPOSITORY); } } return $IDS; }
/** * * @param AJXP_Node $node * @param int $depth * @throws Exception */ public function recursiveIndexation($node, $depth = 0) { $repository = $node->getRepository(); $user = $node->getUser(); $messages = ConfService::getMessages(); if ($user == null && AuthService::usersEnabled()) { $user = AuthService::getLoggedUser(); } if ($depth == 0) { $this->logDebug("Starting indexation - node.index.recursive.start - " . memory_get_usage(true) . " - " . $node->getUrl()); $this->setIndexStatus("RUNNING", str_replace("%s", $node->getPath(), $messages["core.index.8"]), $repository, $user); AJXP_Controller::applyHook("node.index.recursive.start", array($node)); } else { if ($this->isInterruptRequired($repository, $user)) { $this->logDebug("Interrupting indexation! - node.index.recursive.end - " . $node->getUrl()); AJXP_Controller::applyHook("node.index.recursive.end", array($node)); $this->releaseStatus($repository, $user); throw new Exception("User interrupted"); } } if (!ConfService::currentContextIsCommandLine()) { @set_time_limit(120); } $url = $node->getUrl(); $this->logDebug("Indexing Node parent node " . $url); $this->setIndexStatus("RUNNING", str_replace("%s", $node->getPath(), $messages["core.index.8"]), $repository, $user); try { AJXP_Controller::applyHook("node.index", array($node)); } catch (Exception $e) { $this->logDebug("Error Indexing Node " . $url . " (" . $e->getMessage() . ")"); } $handle = opendir($url); if ($handle !== false) { while (($child = readdir($handle)) != false) { if ($child[0] == ".") { continue; } $childNode = new AJXP_Node(rtrim($url, "/") . "/" . $child); $childUrl = $childNode->getUrl(); if (is_dir($childUrl)) { $this->logDebug("Entering recursive indexation for " . $childUrl); $this->recursiveIndexation($childNode, $depth + 1); } else { try { $this->logDebug("Indexing Node " . $childUrl); AJXP_Controller::applyHook("node.index", array($childNode)); } catch (Exception $e) { $this->logDebug("Error Indexing Node " . $childUrl . " (" . $e->getMessage() . ")"); } } } closedir($handle); } else { $this->logDebug("Cannot open {$url}!!"); } if ($depth == 0) { $this->logDebug("End indexation - node.index.recursive.end - " . memory_get_usage(true) . " - " . $node->getUrl()); $this->setIndexStatus("RUNNING", "Indexation finished, cleaning...", $repository, $user); AJXP_Controller::applyHook("node.index.recursive.end", array($node)); $this->releaseStatus($repository, $user); $this->logDebug("End indexation - After node.index.recursive.end - " . memory_get_usage(true) . " - " . $node->getUrl()); } }
/** * Hook node.change * @param AJXP_Node $oldNode * @param AJXP_Node $newNode * @param bool $copy */ public function updateNodeSharedData($oldNode = null, $newNode = null, $copy = false) { if ($oldNode == null || $copy) { // Create or copy, do nothing return; } if ($oldNode != null && $newNode != null && $oldNode->getUrl() == $newNode->getUrl()) { // Same path => must be a content update, do nothing return; } $this->logDebug("Should update node"); $delete = false; if ($newNode == null) { $delete = true; } else { $repo = $newNode->getRepository(); $recycle = $repo->getOption("RECYCLE_BIN"); if (!empty($recycle) && strpos($newNode->getPath(), $recycle) === 1) { $delete = true; } } $shareStore = $this->getShareStore(); $modifiedNodes = $shareStore->moveSharesFromMetaRecursive($oldNode, $delete, $oldNode->getPath(), $newNode != null ? $newNode->getPath() : null); // Force switching back to correct driver! if ($modifiedNodes > 0) { $oldNode->getRepository()->driverInstance = null; $oldNode->setDriver(null); $oldNode->getDriver(); } return; }
public static function getNodes($checkStats = false, $touch = true) { if (isset(self::$output)) { return self::$output; } $mess = ConfService::getMessages(); $repos = ConfService::getAccessibleRepositories(); $output = array(); $touchReposIds = array(); foreach ($repos as $repo) { if (!$repo->hasOwner() || !$repo->hasContentFilter()) { continue; } $repoId = $repo->getId(); if (strpos("ocs_remote_share_", $repoId) !== 0) { $touchReposIds[] = $repoId; } $url = "pydio://" . $repoId . "/"; $meta = array("shared_repository_id" => $repoId, "ajxp_description" => "File shared by " . $repo->getOwner() . " " . AJXP_Utils::relativeDate($repo->getOption("CREATION_TIME"), $mess), "share_meta_type" => 1); $cFilter = $repo->getContentFilter(); $filter = $cFilter instanceof ContentFilter ? array_keys($cFilter->filters)[0] : $cFilter; if (!is_array($filter)) { $label = basename($filter); } else { $label = $repo->getDisplay(); } if (strpos($repoId, "ocs_remote_share") !== 0) { // FOR REMOTE SHARES, DO NOT APPEND THE DOCUMENTNAME, WE STAT THE ROOT DIRECTLY $url .= $label; } $status = null; $remoteShare = null; $name = pathinfo($label, PATHINFO_FILENAME); $ext = pathinfo($label, PATHINFO_EXTENSION); $node = new AJXP_Node($url); $node->setLabel($label); if ($checkStats) { $node->getRepository()->driverInstance = null; try { ConfService::loadDriverForRepository($node->getRepository()); } catch (Exception $e) { $ext = "error"; $meta["ajxp_mime"] = "error"; } $node->getRepository()->detectStreamWrapper(true); $stat = @stat($url); if ($stat === false) { $ext = "error"; $meta["ajxp_mime"] = "error"; $meta["share_meta_type"] = 2; } else { if (strpos($repoId, "ocs_remote_share_") === 0) { // Check Status $linkId = str_replace("ocs_remote_share_", "", $repoId); $ocsStore = new \Pydio\OCS\Model\SQLStore(); $remoteShare = $ocsStore->remoteShareById($linkId); $status = $remoteShare->getStatus(); if ($status == OCS_INVITATION_STATUS_PENDING) { $stat = stat(AJXP_Utils::getAjxpTmpDir()); $ext = "invitation"; $meta["ajxp_mime"] = "invitation"; $meta["share_meta_type"] = 0; } else { $meta["remote_share_accepted"] = "true"; } $meta["remote_share_id"] = $remoteShare->getId(); } } if ($ext == "invitation") { $label .= " (" . $mess["inbox_driver.4"] . ")"; } else { if ($ext == "error") { $label .= " (" . $mess["inbox_driver.5"] . ")"; } } if (is_array($stat) && AuthService::getLoggedUser() != null) { $acl = AuthService::getLoggedUser()->mergedRole->getAcl($repoId); if ($acl == "r") { self::disableWriteInStat($stat); } } } $index = 0; $suffix = ""; while (isset($output[$name . $suffix . "." . $ext])) { $index++; $suffix = " ({$index})"; } $output[$name . $suffix . "." . $ext] = ["label" => $label, "url" => $url, "remote_share" => $remoteShare, "meta" => $meta]; if (isset($stat)) { $output[$name . $suffix . "." . $ext]['stat'] = $stat; } } ConfService::loadDriverForRepository(ConfService::getRepository()); self::$output = $output; if ($touch) { if (count($touchReposIds) && AuthService::getLoggedUser() != null) { $uPref = AuthService::getLoggedUser()->getPref("repository_last_connected"); if (empty($uPref)) { $uPref = array(); } foreach ($touchReposIds as $rId) { $uPref[$rId] = time(); } AuthService::getLoggedUser()->setPref("repository_last_connected", $uPref); } } return $output; }
public function loadUserAlerts($actionName, $httpVars, $fileVars) { if (!$this->eventStore) { return; } $u = AuthService::getLoggedUser(); $userId = $u->getId(); $repositoryFilter = null; if (isset($httpVars["repository_id"]) && $u->mergedRole->canRead($httpVars["repository_id"])) { $repositoryFilter = $httpVars["repository_id"]; } if ($repositoryFilter == null) { $repositoryFilter = ConfService::getRepository()->getId(); } $res = $this->eventStore->loadAlerts($userId, $repositoryFilter); if (!count($res)) { return; } // Recompute children notifs $format = $httpVars["format"]; $skipContainingTags = isset($httpVars["skip_container_tags"]); $mess = ConfService::getMessages(); if (!$skipContainingTags) { if ($format == "html") { echo "<h2>" . $mess["notification_center.3"] . "</h2>"; echo "<ul class='notification_list'>"; } else { AJXP_XMLWriter::header(); } } $parentRepository = ConfService::getRepositoryById($repositoryFilter); $parentRoot = $parentRepository->getOption("PATH"); $cumulated = array(); foreach ($res as $notification) { if ($format == "html") { echo "<li>"; echo $notification->getDescriptionLong(true); echo "</li>"; } else { $node = $notification->getNode(); $path = $node->getPath(); $nodeRepo = $node->getRepository(); if ($nodeRepo != null && $nodeRepo->hasParent() && $nodeRepo->getParentId() == $repositoryFilter) { $currentRoot = $nodeRepo->getOption("PATH"); $contentFilter = $nodeRepo->getContentFilter(); if (isset($contentFilter)) { $nodePath = $contentFilter->filterExternalPath($node->getPath()); if ($nodePath == "/") { $k = array_keys($contentFilter->filters); $nodePath = $k[0]; } } else { $nodePath = $node->getPath(); } $relative = rtrim(substr($currentRoot, strlen($parentRoot)), "/") . rtrim($nodePath, "/"); $parentNodeURL = $node->getScheme() . "://" . $repositoryFilter . $relative; $this->logDebug("action.share", "Recompute alert to " . $parentNodeURL); $node = new AJXP_Node($parentNodeURL); } if (isset($cumulated[$path])) { $cumulated[$path]->event_occurence++; continue; } try { $node->loadNodeInfo(); } catch (Exception $e) { if ($notification->alert_id) { $this->eventStore->dismissAlertById($notification->alert_id); } continue; } $node->event_is_alert = true; $node->event_description = ucfirst($notification->getDescriptionBlock()) . " " . $mess["notification.tpl.block.user_link"] . " " . $notification->getAuthorLabel(); $node->event_description_long = $notification->getDescriptionLong(true); $node->event_date = SystemTextEncoding::fromUTF8(AJXP_Utils::relativeDate($notification->getDate(), $mess)); $node->event_type = "alert"; $node->alert_id = $notification->alert_id; if ($node->getRepository() != null) { $node->repository_id = '' . $node->getRepository()->getId(); if ($node->repository_id != $repositoryFilter && $node->getRepository()->getDisplay() != null) { $node->event_repository_label = "[" . $node->getRepository()->getDisplay() . "]"; } } else { $node->event_repository_label = "[N/A]"; } $node->event_author = $notification->getAuthor(); $node->event_occurence = 1; $cumulated[$path] = $node; } } $index = 1; foreach ($cumulated as $nodeToSend) { $nodeOcc = $nodeToSend->event_occurence > 1 ? "(" . $nodeToSend->event_occurence . ")" : ""; if (isset($httpVars["merge_description"]) && $httpVars["merge_description"] == "true") { if (isset($httpVars["description_as_label"]) && $httpVars["description_as_label"] == "true") { $nodeToSend->setLabel($nodeToSend->event_description . " " . $nodeOcc . " " . $nodeToSend->event_date); } else { $nodeToSend->setLabel(basename($nodeToSend->getPath()) . " " . $nodeOcc . " " . " <small class='notif_desc'>" . $nodeToSend->event_description . " " . $nodeToSend->event_date . "</small>"); } } else { $nodeToSend->setLabel(basename($nodeToSend->getPath()) . $nodeOcc); } // Replace PATH $nodeToSend->real_path = $path; //$url = parse_url($nodeToSend->getUrl()); //$nodeToSend->setUrl($url["scheme"]."://".$url["host"]."/alert_".$index); $index++; AJXP_XMLWriter::renderAjxpNode($nodeToSend); } if (!$skipContainingTags) { if ($format == "html") { echo "</ul>"; } else { AJXP_XMLWriter::close(); } } }
/** * @param AJXP_Node $oldNode * @param AJXP_Node $newNode * @param bool $copy */ public function updateNodeSharedData($oldNode = null, $newNode = null, $copy = false) { if ($oldNode != null && !$copy) { $this->logDebug("Should update node"); $delete = false; if ($newNode == null) { $delete = true; } else { $repo = $newNode->getRepository(); $recycle = $repo->getOption("RECYCLE_BIN"); if (!empty($recycle) && strpos($newNode->getPath(), $recycle) === 1) { $delete = true; } } $this->getSharesFromMeta($oldNode, $shares, true); if (empty($shares)) { return; } $newShares = array(); foreach ($shares as $id => $data) { $type = $data["type"]; if ($delete) { $this->getShareStore()->deleteShare($type, $id); continue; } if ($type == "minisite") { $share = $this->getShareStore()->loadShare($id); $repo = ConfService::getRepositoryById($share["REPOSITORY"]); } else { if ($type == "repository") { $repo = ConfService::getRepositoryById($id); } else { if ($type == "file") { $publicLink = $this->getShareStore()->loadShare($id); } } } if (isset($repo)) { $cFilter = $repo->getContentFilter(); $path = $repo->getOption("PATH", true); $save = false; if (isset($cFilter)) { $cFilter->movePath($oldNode->getPath(), $newNode->getPath()); $repo->setContentFilter($cFilter); $save = true; } else { if (!empty($path)) { $path = str_replace($oldNode->getPath(), $newNode->getPath(), $path); $repo->addOption("PATH", $path); $save = true; } } if ($save) { ConfService::getConfStorageImpl()->saveRepository($repo, true); $newShares[$id] = $data; } } else { if (isset($publicLink["FILE_PATH"])) { $publicLink["FILE_PATH"] = str_replace($oldNode->getPath(), $newNode->getPath(), $publicLink["FILE_PATH"]); $this->getShareStore()->deleteShare("file", $id); $this->getShareStore()->storeShare($newNode->getRepositoryId(), $publicLink, "file", $id); $newShares[$id] = $data; } } } $oldNode->removeMetadata("ajxp_shared", true, AJXP_METADATA_SCOPE_REPOSITORY, true); if ($newNode != null && count($newShares)) { $newNode->setMetadata("ajxp_shared", array("shares" => $newShares), true, AJXP_METADATA_SCOPE_REPOSITORY, true); } } }
/** * @param AJXP_Node $oldNode * @param AJXP_Node $newNode * @param bool $copy */ public function updateNodesIndex($oldNode = null, $newNode = null, $copy = false) { require_once AJXP_BIN_FOLDER . "/dibi.compact.php"; try { if ($newNode == null) { $repoId = $this->computeIdentifier($oldNode->getRepository()); // DELETE dibi::query("DELETE FROM [ajxp_index] WHERE [node_path] LIKE %like~ AND [repository_identifier] = %s", $oldNode->getPath(), $repoId); } else { if ($oldNode == null) { // CREATE $stat = stat($newNode->getUrl()); $res = dibi::query("INSERT INTO [ajxp_index]", array("node_path" => $newNode->getPath(), "bytesize" => $stat["size"], "mtime" => $stat["mtime"], "md5" => $newNode->isLeaf() ? md5_file($newNode->getUrl()) : "directory", "repository_identifier" => $repoId = $this->computeIdentifier($newNode->getRepository()))); } else { $repoId = $this->computeIdentifier($oldNode->getRepository()); if ($oldNode->getPath() == $newNode->getPath()) { // CONTENT CHANGE clearstatcache(); $stat = stat($newNode->getUrl()); $this->logDebug("Content changed", "current stat size is : " . $stat["size"]); dibi::query("UPDATE [ajxp_index] SET ", array("bytesize" => $stat["size"], "mtime" => $stat["mtime"], "md5" => md5_file($newNode->getUrl())), "WHERE [node_path] = %s AND [repository_identifier] = %s", $oldNode->getPath(), $repoId); } else { // PATH CHANGE ONLY $newNode->loadNodeInfo(); if ($newNode->isLeaf()) { dibi::query("UPDATE [ajxp_index] SET ", array("node_path" => $newNode->getPath()), "WHERE [node_path] = %s AND [repository_identifier] = %s", $oldNode->getPath(), $repoId); } else { dibi::query("UPDATE [ajxp_index] SET [node_path]=REPLACE( REPLACE(CONCAT('\$\$\$',[node_path]), CONCAT('\$\$\$', %s), CONCAT('\$\$\$', %s)) , '\$\$\$', '') ", $oldNode->getPath(), $newNode->getPath(), "WHERE [node_path] LIKE %like~ AND [repository_identifier] = %s", $oldNode->getPath(), $repoId); } } } } } catch (Exception $e) { AJXP_Logger::error("[meta.syncable]", "Indexation", $e->getMessage()); } }