diff --git a/core/src/plugins/access.inbox/class.inboxAccessDriver.php b/core/src/plugins/access.inbox/class.inboxAccessDriver.php new file mode 100644 index 0000000000..0378c2a461 --- /dev/null +++ b/core/src/plugins/access.inbox/class.inboxAccessDriver.php @@ -0,0 +1,54 @@ + + * This file is part of Pydio. + * + * Pydio is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Pydio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with Pydio. If not, see . + * + * The latest code can be found at . + */ + +defined('AJXP_EXEC') or die('Access not allowed'); + + +class inboxAccessDriver extends fsAccessDriver +{ + public function initRepository() + { + $this->detectStreamWrapper(true); + $this->urlBase = "pydio://".$this->repository->getId(); + } + + public function loadNodeInfo(&$ajxpNode, $parentNode = false, $details = false) + { + $mess = ConfService::getMessages(); + parent::loadNodeInfo($ajxpNode, $parentNode, $details); + if(!$ajxpNode->isRoot()){ + $targetUrl = inboxAccessWrapper::translateURL($ajxpNode->getUrl()); + $repoId = parse_url($targetUrl, PHP_URL_HOST); + $r = ConfService::getRepositoryById($repoId); + $owner = $r->getOwner(); + $leaf = $ajxpNode->isLeaf(); + $meta = array( + "shared_repository_id" => $repoId, + "ajxp_description" => ($leaf?"File":"Folder")." shared by ".$owner. " ". AJXP_Utils::relativeDate($r->getOption("CREATION_TIME"), $mess) + ); + if(!$leaf){ + $meta["ajxp_mime"] = "shared_folder"; + } + $ajxpNode->mergeMetadata($meta); + } + } + +} \ No newline at end of file diff --git a/core/src/plugins/access.inbox/class.inboxAccessWrapper.php b/core/src/plugins/access.inbox/class.inboxAccessWrapper.php new file mode 100644 index 0000000000..082326f1d9 --- /dev/null +++ b/core/src/plugins/access.inbox/class.inboxAccessWrapper.php @@ -0,0 +1,406 @@ + + * This file is part of Pydio. + * + * Pydio is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Pydio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with Pydio. If not, see . + * + * The latest code can be found at . + */ + +defined('AJXP_EXEC') or die('Access not allowed'); + + +class inboxAccessWrapper implements AjxpWrapper +{ + private $nodes; + private $index; + + /** + * @var Resource + */ + private $fp; + /** + * @var AJXP_Node + */ + private static $linkNode; + + private static $output; + + protected static function getNodes(){ + if(isSet(self::$output)){ + return self::$output; + } + $repos = ConfService::getAccessibleRepositories(); + self::$output = array(); + foreach($repos as $repo){ + if(!$repo->hasParent()){ + continue; + } + if($repo->hasContentFilter()){ + $cFilter = $repo->getContentFilter(); + $filter = array_keys($cFilter->filters)[0]; + self::$output[basename($filter)] = "pydio://".$repo->getId()."/".basename($filter); + }else{ + $label = $repo->getDisplay(); + self::$output[$label] = "pydio://".$repo->getId()."/"; + } + } + return self::$output; + } + + public function dir_opendir($path, $options) + { + $this->nodes = self::getNodes(); + $this->index = 0; + return true; + } + + public function dir_readdir() + { + $entry = false; + if($this->index < count($this->nodes)){ + $keys = array_keys($this->nodes); + $entry = basename($keys[$this->index]); + } + $this->index++; + return $entry; + } + + public static function translateURL($path){ + $pydioScheme = false; + self::$linkNode = null; + $nodePath = parse_url($path, PHP_URL_PATH); + $nodes = self::getNodes(); + $url = $nodes[ltrim($nodePath, "/")]; + $scheme = parse_url($url, PHP_URL_SCHEME); + if($scheme == "pydio"){ + self::$linkNode = new AJXP_Node($path); + $pydioScheme = true; + } + if(empty($nodePath)){ + return AJXP_Utils::getAjxpTmpDir(); + } + if($pydioScheme){ + $node = new AJXP_Node($url); + ConfService::loadDriverForRepository($node->getRepository()); + $node->getRepository()->detectStreamWrapper(true); + } + return $url; + } + + /** + * Get a "usable" reference to a file : the real file or a tmp copy. + * + * @param string $path + * @param bool $persistent + * @return string + */ + public static function getRealFSReference($path, $persistent = false) + { + $url = self::translateURL($path); + if(self::$linkNode !== null){ + $isRemote = AJXP_MetaStreamWrapper::wrapperIsRemote($url); + $realFilePointer = AJXP_MetaStreamWrapper::getRealFSReference($url, true); + if(!$isRemote){ + $tmpname = tempnam(AJXP_Utils::getAjxpTmpDir(), "real-file-inbox-pointer"); + copy($realFilePointer, $tmpname); + $realFilePointer = $tmpname; + } + ConfService::loadDriverForRepository(self::$linkNode->getRepository()); + return $realFilePointer; + }else{ + $tmpname = tempnam(AJXP_Utils::getAjxpTmpDir(), "real-file-inbox-pointer"); + $source = fopen($url, "r"); + $dest = fopen($tmpname, "w"); + stream_copy_to_stream($source, $dest); + return $tmpname; + } + + } + + /** + * Read a file (by chunks) and copy the data directly inside the given stream. + * + * @param string $path + * @param resource $stream + */ + public static function copyFileInStream($path, $stream) + { + $url = self::translateURL($path); + $wrapperClass = AJXP_MetaStreamWrapper::actualRepositoryWrapperClass(parse_url($url, PHP_URL_HOST)); + call_user_func(array($wrapperClass, "copyFileInStream"), $url, $stream); + if(self::$linkNode !== null){ + ConfService::loadDriverForRepository(self::$linkNode->getRepository()); + } + } + + /** + * Chmod implementation for this type of access. + * + * @param string $path + * @param number $chmodValue + */ + public static function changeMode($path, $chmodValue) + { + // TODO: Implement changeMode() method. + } + + /** + * Describe whether the current wrapper operates on a remote server or not. + * @static + * @return boolean + */ + public static function isRemote() + { + return true; + } + + /** + * Describe whether the current wrapper can rewind a stream or not. + * @param String $url Url of the resource + * @static + * @return boolean + */ + public static function isSeekable($url) + { + return true; + } + + /** + * + * + * @return bool + */ + public function dir_closedir() + { + $this->index = 0; + } + + /** + * Enter description here... + * + * @return bool + */ + public function dir_rewinddir() + { + $this->index = 0; + } + + /** + * Enter description here... + * + * @param string $path + * @param int $mode + * @param int $options + * @return bool + */ + public function mkdir($path, $mode, $options) + { + return false; + } + + /** + * Enter description here... + * + * @param string $path_from + * @param string $path_to + * @return bool + */ + public function rename($path_from, $path_to) + { + return false; + } + + /** + * Enter description here... + * + * @param string $path + * @param int $options + * @return bool + */ + public function rmdir($path, $options) + { + return false; + } + + /** + * Enter description here... + * + */ + public function stream_close() + { + if($this->fp !== null){ + fclose($this->fp); + if(self::$linkNode !== null){ + ConfService::loadDriverForRepository(self::$linkNode->getRepository()); + } + } + } + + /** + * Enter description here... + * + * @return bool + */ + public function stream_eof() + { + if(is_resource($this->fp)){ + return feof($this->fp); + } + return false; + } + + /** + * Enter description here... + * + * @return bool + */ + public function stream_flush() + { + if($this->fp !== null){ + return fflush($this->fp); + } + return null; + } + + /** + * Enter description here... + * + * @param string $path + * @param string $mode + * @param int $options + * @param string &$opened_path + * @return bool + */ + public function stream_open($path, $mode, $options, &$opened_path) + { + $this->fp = fopen(self::translateURL($path), $mode, $options); + return true; + } + + /** + * Enter description here... + * + * @param int $count + * @return string + */ + public function stream_read($count) + { + if($this->fp !== null){ + return fread($this->fp, $count); + } + return null; + } + + /** + * Enter description here... + * + * @param int $offset + * @param int $whence = SEEK_SET + * @return bool + */ + public function stream_seek($offset, $whence = SEEK_SET) + { + if($this->fp !== null){ + return fseek($this->fp, $offset, $whence); + } + return null; + } + + /** + * Enter description here... + * + * @return array + */ + public function stream_stat() + { + if($this->fp !== null){ + return fstat($this->fp); + } + return false; + } + + /** + * Enter description here... + * + * @return int + */ + public function stream_tell() + { + if($this->fp !== null){ + return ftell($this->fp); + } + return null; + } + + /** + * Enter description here... + * + * @param string $data + * @return int + */ + public function stream_write($data) + { + if($this->fp !== null){ + return fwrite($this->fp, $data); + } + return 0; + } + + /** + * Enter description here... + * + * @param string $path + * @return bool + */ + public function unlink($path) + { + // TODO: Implement unlink() method. + } + + /** + * Enter description here... + * + * @param string $path + * @param int $flags + * @return array + */ + public function url_stat($path, $flags) + { + $origRepo = parse_url($path, PHP_URL_HOST); + $url = self::translateURL($path); + $targetRepo = parse_url($path, PHP_URL_PATH); + $stat = stat($url); + if($targetRepo != $origRepo){ + $stat["rdev"] = $stat[6] = $targetRepo; + } + if(self::$linkNode !== null){ + ConfService::loadDriverForRepository(self::$linkNode->getRepository()); + } + $this->disableWriteInStat($stat); + return $stat; + } + + /** + * @param array $stat + */ + protected function disableWriteInStat(&$stat){ + $octRights = decoct($stat["mode"]); + $last = (strlen($octRights)) - 1; + $octRights[$last] = $octRights[$last-1] = $octRights[$last-2] = 5; + $stat["mode"] = $stat[2] = octdec($octRights); + } + +} \ No newline at end of file diff --git a/core/src/plugins/access.inbox/manifest.xml b/core/src/plugins/access.inbox/manifest.xml new file mode 100644 index 0000000000..b476da8c33 --- /dev/null +++ b/core/src/plugins/access.inbox/manifest.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +