/** * Executes the command logic with the specified RPC parameters. * * @param Object $params Command parameters sent from client. * @return Object Result object to be passed back to client. */ public function execute($params) { $toPath = $params->to; $ext = MOXMAN_Util_PathUtils::getExtension($toPath); if ($ext !== 'zip') { $toPath .= '.zip'; } $toFile = MOXMAN::getFile($toPath); $config = $toFile->getConfig(); if ($config->get('general.demo')) { throw new MOXMAN_Exception("This action is restricted in demo mode.", MOXMAN_Exception::DEMO_MODE); } if (!$toFile->canWrite()) { throw new MOXMAN_Exception("No write access to file: " . $toFile->getPublicPath(), MOXMAN_Exception::NO_WRITE_ACCESS); } $zipWriter = new MOXMAN_Zip_ZipWriter(array("compressionLevel" => 5)); $filter = MOXMAN_Vfs_BasicFileFilter::createFromConfig($config); $path = $params->path; foreach ($params->names as $name) { $fromFile = MOXMAN::getFile(MOXMAN_Util_PathUtils::combine($path, $name)); $this->addZipFiles($fromFile, $fromFile->getParent(), $filter, $zipWriter); } $stream = $toFile->open(MOXMAN_Vfs_IFileStream::WRITE); if ($stream) { $stream->write($zipWriter->toString()); $stream->close(); } $this->fireFileAction(MOXMAN_Core_FileActionEventArgs::ADD, $toFile); return $this->fileToJson($toFile); }
/** * Process a request using the specified context. * * @param MOXMAN_Http_Context $httpContext Context instance to pass to use for the handler. */ public function processRequest(MOXMAN_Http_Context $httpContext) { $request = $httpContext->getRequest(); $response = $httpContext->getResponse(); $path = $request->get("path"); $names = explode('/', $request->get("names", "")); $zipName = $request->get("zipname", "files.zip"); if (count($names) === 1) { $file = MOXMAN::getFile(MOXMAN_Util_PathUtils::combine($path, $names[0])); $filter = MOXMAN_Vfs_CombinedFileFilter::createFromConfig(MOXMAN::getFile($path)->getConfig(), "download"); if (!$filter->accept($file)) { throw new MOXMAN_Exception("Invalid file name for: " . $file->getPublicPath(), MOXMAN_Exception::INVALID_FILE_NAME); } if ($file->isFile()) { $response->sendFile($file, true); return; } } // Download multiple files as zip $zipWriter = new MOXMAN_Zip_ZipWriter(array("compressionLevel" => 0)); // Setup download headers $response->disableCache(); $response->setHeader("Content-type", "application/octet-stream"); $response->setHeader("Content-Disposition", 'attachment; filename="' . $zipName . '"'); $filter = MOXMAN_Vfs_CombinedFileFilter::createFromConfig(MOXMAN::getFile($path)->getConfig(), "download"); // Combine files to zip foreach ($names as $name) { $fromFile = MOXMAN::getFile(MOXMAN_Util_PathUtils::combine($path, $name)); $this->addZipFiles($fromFile, $fromFile->getParent(), $filter, $zipWriter); } $response->sendContent($zipWriter->toString()); }
/** * Initializes the storage instance. * * @param MOXMAN_Util_Config $config Config instance. * @param int $type Storage type to use, can be any of the type constants. * @param string $name Name of the user/group if those types are used or an empty string. */ public function initialize($config, $type, $name) { $this->config = $config; $this->type = $type; $this->name = $name; $this->storagePath = MOXMAN_Util_PathUtils::combine($config->get("storage.path"), ($name ? $type . "." . $name : $type) . ".json"); }
/** * Sends the specified file with the correct mime type back to the browser. * This method gets called from the client side using the stream file. * * @param MOXMAN_Http_Context $httpContext Context instance to pass to use for the handler. */ public function processRequest(MOXMAN_Http_Context $httpContext) { $request = $httpContext->getRequest(); $response = $httpContext->getResponse(); try { $file = MOXMAN::getFile($request->get("path")); } catch (Exception $e) { $response->setStatus("500", "Could not resolve path: " . $request->get("path")); if (MOXMAN::getLogger()) { MOXMAN::getLogger()->debug("Could not resolve path: " . $request->get("path")); } return; } // Create thumbnail if ($request->get("thumb")) { try { $file = $this->plugin->createThumbnail($file); } catch (Exception $e) { $response->setStatus("500", "Could not generate thumbnail."); $response->sendContent("Could not generate thumbnail."); return; } } // Fire before stream event $args = new MOXMAN_Vfs_StreamEventArgs($httpContext, $file); $this->plugin->fire("BeforeStream", $args); $file = $args->getFile(); // Stream temp file if it exists if ($tempName = $request->get("tempname")) { $ext = MOXMAN_Util_PathUtils::getExtension($file->getName()); $tempName = "mcic_" . md5(session_id() . $file->getName()) . "." . $ext; $tempFilePath = MOXMAN_Util_PathUtils::combine(MOXMAN_Util_PathUtils::getTempDir(), $tempName); if (file_exists($tempFilePath)) { $response->sendLocalFile($tempFilePath); return; } } $url = $file->getUrl(); if ($url && !$request->get("stream", false)) { $response->redirect($url); } else { // Force 48h cache time $offset = 48 * 60 * 60; $response->setHeader("Cache-Control", "max-age=" . $offset); $response->setHeader("Date", gmdate("D, d M Y H:i:s", time() + $offset) . " GMT"); $response->setHeader("Expires", gmdate("D, d M Y H:i:s", time() + $offset) . " GMT"); $response->setHeader("Pragma", "public"); $response->sendFile($file); } }
/** * Returns a file object out of the specified URL. * * @param string Absolute URL for the specified file. * @return MOXMAN_Vfs_IFile File that got resolved or null if it wasn't found. */ public function getFile($url) { $file = null; $prefix = $this->fileSystem->getBucketOption("urlprefix"); $prefix = preg_replace('/^https?:\\/\\//', '//', $prefix); $url = preg_replace('/^https?:\\/\\//', '//', $url); if (strpos($url, $prefix) === 0) { $bucketKey = $this->fileSystem->getBucketOption("key"); $path = urldecode(substr($url, strlen($prefix))); $filePath = MOXMAN_Util_PathUtils::combine("s3://" . $bucketKey, $path); if (MOXMAN_Util_PathUtils::isChildOf($filePath, $this->fileSystem->getRootPath())) { return $this->fileSystem->getFile($filePath); } } return $file; }
/** * Returns a file object out of the specified URL. * * @param string Absolute URL for the specified file. * @return MOXMAN_Vfs_IFile File that got resolved or null if it wasn't found. */ public function getFile($url) { $file = null; $prefix = $this->fileSystem->getContainerOption("urlprefix"); $containerName = $this->fileSystem->getContainerOption("name"); $containerKey = $this->fileSystem->getContainerOption("key"); $match = MOXMAN_Util_PathUtils::combine($prefix, $containerName); if (strpos($url, $match) === 0) { $bucketpath = MOXMAN_Util_PathUtils::combine($prefix, $containerName); $filePath = MOXMAN_Util_PathUtils::combine("azure://" . $containerKey, substr($url, strlen($bucketpath))); if (MOXMAN_Util_PathUtils::isChildOf($filePath, $this->fileSystem->getRootPath())) { return $this->fileSystem->getFile($filePath); } } return $file; }
/** * Returns a file object out of the specified URL. * * @param string Absolute URL for the specified file. * @return MOXMAN_Vfs_IFile File that got resolved or null if it wasn't found. */ public function getFile($url) { $config = $this->fileSystem->getConfig(); $file = null; // Get config items $wwwroot = $config->get("filesystem.local.wwwroot"); $prefix = $config->get("filesystem.local.urlprefix"); $paths = MOXMAN_Util_PathUtils::getSitePaths(); // No wwwroot specified try to figure out a wwwroot if (!$wwwroot) { $wwwroot = $paths["wwwroot"]; } else { // Force the www root to an absolute file system path $wwwroot = MOXMAN_Util_PathUtils::toAbsolute(MOXMAN_ROOT, $wwwroot); } // Add prefix to URL if ($prefix == "") { $prefix = MOXMAN_Util_PathUtils::combine("{proto}://{host}", $paths["prefix"]); } // Replace protocol if (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == "on") { $prefix = str_replace("{proto}", "https", $prefix); } else { $prefix = str_replace("{proto}", "http", $prefix); } // Replace host/port $prefix = str_replace("{host}", $_SERVER['HTTP_HOST'], $prefix); $prefix = str_replace("{port}", $_SERVER['SERVER_PORT'], $prefix); // Remove prefix from url if ($prefix && strpos($url, $prefix) === 0) { $url = substr($url, strlen($prefix)); } // Parse url and check if path part of the URL is within the root of the file system $url = parse_url($url); if (isset($url["path"])) { $path = MOXMAN_Util_PathUtils::combine($wwwroot, $url["path"]); if (MOXMAN_Util_PathUtils::isChildOf($path, $this->fileSystem->getRootPath())) { // Crop away root path part and glue it back on again since the case might be different // For example: c:/inetpub/wwwroot and C:/InetPub/WWWRoot this will force it into the // valid fileSystem root path prefix $path = substr($path, strlen($this->fileSystem->getRootPath())); $path = MOXMAN_Util_PathUtils::combine($this->fileSystem->getRootPath(), $path); $file = $this->fileSystem->getFile($path); } } return $file; }
public static function locate($optionName, $pathLocations) { $rootPath = MOXMAN_ROOT; $fullPath = MOXMAN::getConfig()->get($optionName); if ($fullPath) { return $fullPath; } while ($rootPath) { foreach ($pathLocations as $path) { $fullPath = MOXMAN_Util_PathUtils::combine($rootPath, $path); if (file_exists($fullPath)) { return $fullPath; } } if (dirname($rootPath) === $rootPath) { break; } $rootPath = dirname($rootPath); } throw new MOXMAN_Exception("Error could not locate library/framework. Please configure: " . $optionName); }
/** * Returns an URL for the specified file object. * * @param MOXMAN_Vfs_IFile $file File to get the absolute URL for. * @return String Absolute URL for the specified file. */ public function getUrl(MOXMAN_Vfs_IFile $file) { $config = $file->getConfig(); // Get config items $wwwroot = $config->get("filesystem.local.wwwroot"); $prefix = $config->get("filesystem.local.urlprefix"); $suffix = $config->get("filesystem.local.urlsuffix"); $paths = MOXMAN_Util_PathUtils::getSitePaths(); // No wwwroot specified try to figure out a wwwroot if (!$wwwroot) { $wwwroot = $paths["wwwroot"]; } else { // Force the www root to an absolute file system path $wwwroot = MOXMAN_Util_PathUtils::toAbsolute(MOXMAN_ROOT, $wwwroot); } // Add prefix to URL if ($prefix == "") { $prefix = MOXMAN_Util_PathUtils::combine("{proto}://{host}", $paths["prefix"]); } // Replace protocol if (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == "on") { $prefix = str_replace("{proto}", "https", $prefix); } else { $prefix = str_replace("{proto}", "http", $prefix); } // Replace host/port $prefix = str_replace("{host}", $_SERVER['HTTP_HOST'], $prefix); $prefix = str_replace("{port}", $_SERVER['SERVER_PORT'], $prefix); // Insert path into URL $url = substr($file->getPath(), strlen($wwwroot)); $url = MOXMAN_Util_PathUtils::combine($prefix, $url); // Add suffix to URL if ($suffix) { $url .= $suffix; } return $url; }
/** @ignore */ private function copyDir($from, $to) { $fromPathRoot = $from->getPath(); $files = $this->getFiles($fromPathRoot); foreach ($files as $fromPath) { $toPath = MOXMAN_Util_PathUtils::combine($to->getPath(), substr($fromPath, strlen($fromPathRoot))); if (is_file($fromPath)) { if ($to instanceof MOXMAN_Vfs_Local_File) { copy($fromPath, $toPath); } else { $to->getFileSystem()->getFile($toPath)->importFrom($fromPath); } } else { if ($to instanceof MOXMAN_Vfs_Local_File) { MOXMAN_Util_PathUtils::verifyPath($toPath, true, "dir"); mkdir($toPath); } else { $to->getFileSystem()->getFile($toPath)->mkdir(); } } } }
/** * Executes the save command logic with the specified RPC parameters. * * @param Object $params Command parameters sent from client. * @return Object Result object to be passed back to client. */ private function save($params) { $file = MOXMAN::getFile($params->path); $config = $file->getConfig(); if ($config->get("general.demo")) { throw new MOXMAN_Exception("This action is restricted in demo mode.", MOXMAN_Exception::DEMO_MODE); } if (!$file->canWrite()) { throw new MOXMAN_Exception("No write access to file: " . $file->getPublicPath(), MOXMAN_Exception::NO_WRITE_ACCESS); } $filter = MOXMAN_Vfs_CombinedFileFilter::createFromConfig($config, "edit"); if ($filter->accept($file) !== MOXMAN_Vfs_CombinedFileFilter::ACCEPTED) { throw new MOXMAN_Exception("Invalid file name for: " . $file->getPublicPath(), MOXMAN_Exception::INVALID_FILE_NAME); } // Import temp file as target file if (isset($params->tempname)) { $tempFilePath = MOXMAN_Util_PathUtils::combine(MOXMAN_Util_PathUtils::getTempDir(), $params->tempname); $file->importFrom($tempFilePath); } MOXMAN::getFileSystemManager()->removeLocalTempFile($file); $this->fireFileAction(MOXMAN_Core_FileActionEventArgs::ADD, $file); return parent::fileToJson($file, true); }
/** * Lists files in the specified path and returns an array with stat info details. * * @param String $path Path to list files in. * @return Array Array with stat info name/value arrays. */ private function getFileList($path) { $files = array(); $prefix = $path === "/" ? "" : substr($path, 1) . "/"; $xml = $this->sendXmlRequest(array("query" => array("comp" => "list", "restype" => "container", "prefix" => $prefix, "delimiter" => "/", "maxresults" => 99999))); // List dirs if (isset($xml->Blobs->BlobPrefix)) { foreach ($xml->Blobs->BlobPrefix as $blobPrefix) { if ($prefix != $blobPrefix->Name) { $stat = array("name" => basename($blobPrefix->Name), "isdir" => true, "size" => 0, "mdate" => 0); $path = MOXMAN_Util_PathUtils::combine($path, $stat["name"]); $files[] = $stat; } } } // List files if (isset($xml->Blobs->Blob)) { foreach ($xml->Blobs->Blob as $blob) { if ($prefix != $blob->Name) { $stat = array("name" => basename($blob->Name), "isdir" => false, "size" => intval($blob->Properties->{"Content-Length"}), "mdate" => strtotime($blob->Properties->{"Last-Modified"})); $path = MOXMAN_Util_PathUtils::combine($path, $stat["name"]); $files[] = $stat; } } } return $files; }
/** * Returns the URL of the memory file. * * @return String Memory file URL. */ public function getUrl() { return MOXMAN_Util_PathUtils::combine("http://memory", $this->getPath()); }
/** * Returns the public path for a file. A public path is a path that is safe * to pass to the client side since it doesn't show the systems full path. * * @return String Public path for the file to be passed out to the client. */ public function getPublicPath() { if (!$this->publicPath) { // Use absolute path if debug mode is enabled or user_friendly_paths is off /*if (!$this->fileSystem->getConfig()->get("general.user_friendly_paths")) { return $this->getPath(); }*/ $rootName = $this->fileSystem->getRootName(); $this->publicPath = MOXMAN_Util_PathUtils::combine($rootName !== "/" ? "/" . $rootName : $rootName, substr($this->path, strlen($this->fileSystem->getRootPath()))); } return $this->publicPath; }
/** * Converts a file instance to a JSON serializable object. * * @param MOXMAN_Vfs_IFile $file File to convert into JSON format. * @param Boolean $meta State if the meta data should be returned or not. * @return stdClass JSON serializable object. */ public static function fileToJson($file, $meta = false) { $config = $file->getConfig(); $renameFilter = MOXMAN_Vfs_CombinedFileFilter::createFromConfig($config, "rename"); $editFilter = MOXMAN_Vfs_CombinedFileFilter::createFromConfig($config, "edit"); $viewFilter = MOXMAN_Vfs_CombinedFileFilter::createFromConfig($config, "view"); $result = (object) array("path" => $file->getPublicPath(), "size" => $file->getSize(), "lastModified" => $file->getLastModified(), "isFile" => $file->isFile(), "canRead" => $file->canRead(), "canWrite" => $file->canWrite(), "canEdit" => $file->isFile() && $editFilter->accept($file) === MOXMAN_Vfs_IFileFilter::ACCEPTED, "canRename" => $renameFilter->accept($file) === MOXMAN_Vfs_IFileFilter::ACCEPTED, "canView" => $file->isFile() && $viewFilter->accept($file) === MOXMAN_Vfs_IFileFilter::ACCEPTED, "canPreview" => $file->isFile() && MOXMAN_Media_ImageAlter::canEdit($file), "exists" => $file->exists()); if ($meta) { $metaData = $file->getMetaData(); //$args = $this->fireCustomInfo(MOXMAN_Core_CustomInfoEventArgs::INSERT_TYPE, $file); $metaData = (object) $metaData->getAll(); if ($file instanceof MOXMAN_Vfs_Local_File && MOXMAN_Media_ImageAlter::canEdit($file)) { $thumbnailFolderPath = MOXMAN_Util_PathUtils::combine($file->getParent(), $config->get('thumbnail.folder')); $thumbnailFile = MOXMAN::getFile($thumbnailFolderPath, $config->get('thumbnail.prefix') . $file->getName()); // TODO: Implement stat info cache layer here $info = MOXMAN_Media_MediaInfo::getInfo($file); $metaData->width = $info["width"]; $metaData->height = $info["height"]; if ($thumbnailFile->exists()) { $metaData->thumb_url = $thumbnailFile->getUrl(); $info = MOXMAN_Media_MediaInfo::getInfo($thumbnailFile); $metaData->thumb_width = $info["width"]; $metaData->thumb_height = $info["height"]; } } $metaData->url = $file->getUrl(); $result->meta = $metaData; } return $result; }
/** * Executes the command logic with the specified RPC parameters. * * @param Object $params Command parameters sent from client. * @return Object Result object to be passed back to client. */ public function execute($params) { $url = isset($params->url) ? $params->url : ""; $path = isset($params->path) ? $params->path : "{default}"; $lastPath = isset($params->lastPath) ? $params->lastPath : ""; $offset = isset($params->offset) ? $params->offset : 0; $length = isset($params->length) ? $params->length : null; $orderBy = isset($params->orderBy) ? $params->orderBy : "name"; $desc = isset($params->desc) ? $params->desc : false; // Result URL to closest file $file = null; if ($url) { try { $file = MOXMAN::getFile($url); } catch (MOXMAN_Exception $e) { // Might throw exception ignore it $file = null; } if ($file) { if ($file->exists()) { $urlFile = $file; } while (!$file->exists() || !$file->isDirectory()) { $file = $file->getParentFile(); } } } // Resolve lastPath input if ($lastPath && !$file) { try { $file = MOXMAN::getFile($lastPath); } catch (MOXMAN_Exception $e) { // Might throw exception ignore it $file = null; } if ($file) { while (!$file->exists() || !$file->isDirectory()) { $file = $file->getParentFile(); } } } $file = $file ? $file : MOXMAN::getFile($path); // Force update on cached file info if (isset($params->force) && $params->force) { MOXMAN_Vfs_Cache_FileInfoStorage::getInstance()->updateFileList($file); } if (!$file->isDirectory()) { throw new MOXMAN_Exception("Path isn't a directory: " . $file->getPublicPath(), MOXMAN_Exception::INVALID_FILE_TYPE); } $config = $file->getConfig(); // Setup input file filter $paramsFileFilter = new MOXMAN_Vfs_BasicFileFilter(); if (isset($params->include_directory_pattern) && $params->include_directory_pattern) { $paramsFileFilter->setIncludeDirectoryPattern($params->include_directory_pattern); } if (isset($params->exclude_directory_pattern) && $params->exclude_directory_pattern) { $paramsFileFilter->setExcludeDirectoryPattern($params->exclude_directory_pattern); } if (isset($params->include_file_pattern) && $params->include_file_pattern) { $paramsFileFilter->setIncludeFilePattern($params->include_file_pattern); } if (isset($params->exclude_file_pattern) && $params->exclude_file_pattern) { $paramsFileFilter->setExcludeFilePattern($params->exclude_file_pattern); } if (isset($params->extensions) && $params->extensions) { $paramsFileFilter->setIncludeExtensions($params->extensions); } if (isset($params->filter) && $params->filter != null) { $paramsFileFilter->setIncludeWildcardPattern($params->filter); } if (isset($params->only_dirs) && $params->only_dirs === true) { $paramsFileFilter->setOnlyDirs(true); } if (isset($params->only_files) && $params->only_files === true) { $paramsFileFilter->setOnlyFiles(true); } // Setup file filter $configuredFilter = new MOXMAN_Vfs_BasicFileFilter(); $configuredFilter->setIncludeDirectoryPattern($config->get('filesystem.include_directory_pattern')); $configuredFilter->setExcludeDirectoryPattern($config->get('filesystem.exclude_directory_pattern')); $configuredFilter->setIncludeFilePattern($config->get('filesystem.include_file_pattern')); $configuredFilter->setExcludeFilePattern($config->get('filesystem.exclude_file_pattern')); $configuredFilter->setIncludeExtensions($config->get('filesystem.extensions')); // Setup combined filter $combinedFilter = new MOXMAN_Vfs_CombinedFileFilter(); $combinedFilter->addFilter($paramsFileFilter); $combinedFilter->addFilter($configuredFilter); $files = $file->listFilesFiltered($combinedFilter)->limit($offset, $length)->orderBy($orderBy, $desc); $args = $this->fireFilesAction(MOXMAN_Vfs_FileActionEventArgs::LIST_FILES, $file, $files); $files = $args->getFileList(); $renameFilter = MOXMAN_Vfs_BasicFileFilter::createFromConfig($file->getConfig(), "rename"); $editFilter = MOXMAN_Vfs_BasicFileFilter::createFromConfig($file->getConfig(), "edit"); $viewFilter = MOXMAN_Vfs_BasicFileFilter::createFromConfig($file->getConfig(), "view"); // List thumbnails and make lookup table $thumbnails = array(); $thumbnailFolder = $config->get("thumbnail.folder"); $thumbnailPrefix = $config->get("thumbnail.prefix"); if ($config->get('thumbnail.enabled')) { $thumbFolderFile = MOXMAN::getFile($file->getPath(), $thumbnailFolder); // Force update on cached file info if (isset($params->force) && $params->force) { MOXMAN_Vfs_Cache_FileInfoStorage::getInstance()->updateFileList($thumbFolderFile); } if ($file instanceof MOXMAN_Vfs_Local_File === false) { $hasThumbnails = false; foreach ($files as $subFile) { if (MOXMAN_Media_ImageAlter::canEdit($subFile)) { $hasThumbnails = true; break; } } if ($hasThumbnails) { $thumbFiles = $thumbFolderFile->listFilesFiltered($combinedFilter)->limit($offset, $length)->orderBy($orderBy, $desc); foreach ($thumbFiles as $thumbFile) { $thumbnails[$thumbFile->getName()] = true; } } } else { // Stat individual files on local fs faster than listing 1000 files $fileSystem = $thumbFolderFile->getFileSystem(); foreach ($files as $subFile) { if (MOXMAN_Media_ImageAlter::canEdit($subFile)) { $thumbFile = $fileSystem->getFile(MOXMAN_Util_PathUtils::combine($thumbFolderFile->getPath(), $thumbnailPrefix . $subFile->getName())); if ($thumbFile->exists()) { $thumbnails[$thumbFile->getName()] = true; } } } } } $result = (object) array("columns" => array("name", "size", "modified", "attrs", "info"), "config" => $this->getPublicConfig($file), "file" => $this->fileToJson($file, true), "urlFile" => isset($urlFile) ? $this->fileToJson($urlFile, true) : null, "data" => array(), "url" => $file->getUrl(), "thumbnailFolder" => $thumbnailFolder, "thumbnailPrefix" => $thumbnailPrefix, "total" => $files->getCount()); foreach ($files as $subFile) { $attrs = $subFile->isDirectory() ? "d" : "-"; $attrs .= $subFile->canRead() ? "r" : "-"; $attrs .= $subFile->canWrite() ? "w" : "-"; $attrs .= $renameFilter->accept($subFile) ? "r" : "-"; $attrs .= $subFile->isFile() && $editFilter->accept($subFile) ? "e" : "-"; $attrs .= $subFile->isFile() && $viewFilter->accept($subFile) ? "v" : "-"; $attrs .= $subFile->isFile() && MOXMAN_Media_ImageAlter::canEdit($subFile) ? "p" : "-"; $attrs .= isset($thumbnails[$thumbnailPrefix . $subFile->getName()]) ? "t" : "-"; $args = $this->fireCustomInfo(MOXMAN_Vfs_CustomInfoEventArgs::LIST_TYPE, $subFile); $custom = (object) $args->getInfo(); if ($subFile->getPublicLinkPath()) { $custom->link = $subFile->getPublicLinkPath(); } $result->data[] = array($subFile->getName(), $subFile->isDirectory() ? 0 : $subFile->getSize(), $subFile->getLastModified(), $attrs, $custom); } return $result; }
/** * Returns the file system internal path. This is used when oding requests on the remote server. * * @return String Internal file system path. */ public function getInternalPath() { if (!$this->internalPath) { $url = parse_url($this->path); $path = isset($url["path"]) ? $url["path"] : "/"; $path = MOXMAN_Util_PathUtils::combine($this->getFileSystem()->getBucketOption("path"), $path); $this->internalPath = $path; } return $this->internalPath; }
/** * Renames/Moves this file to the specified file instance. * * @param MOXMAN_Vfs_IFile $dest File to rename/move to. */ public function moveTo(MOXMAN_Vfs_IFile $dest) { $entries = $this->fileSystem->getEntries($this->path); foreach ($entries as $entry) { $toPath = MOXMAN_Util_PathUtils::combine($dest->getPath(), substr($entry->path, strlen($this->getPath()))); $this->fileSystem->addEntry($toPath, array("isFile" => $entry->isFile, "lastModified" => $entry->lastModified, "data" => $entry->data, "canRead" => $entry->canRead, "canWrite" => $entry->canWrite)); } $this->fileSystem->deleteEntry($this->path); }
/** * Converts a file instance to a JSON serializable object. * * @param MOXMAN_Vfs_IFile $file File to convert into JSON format. * @param Boolean $meta State if the meta data should be returned or not. * @return stdClass JSON serializable object. */ public static function fileToJson($file, $meta = false) { $config = $file->getConfig(); $renameFilter = MOXMAN_Vfs_CombinedFileFilter::createFromConfig($config, "rename"); $editFilter = MOXMAN_Vfs_CombinedFileFilter::createFromConfig($config, "edit"); $viewFilter = MOXMAN_Vfs_CombinedFileFilter::createFromConfig($config, "view"); $configuredFilter = new MOXMAN_Vfs_BasicFileFilter(); $configuredFilter->setIncludeDirectoryPattern($config->get('filesystem.include_directory_pattern')); $configuredFilter->setExcludeDirectoryPattern($config->get('filesystem.exclude_directory_pattern')); $configuredFilter->setIncludeFilePattern($config->get('filesystem.include_file_pattern')); $configuredFilter->setExcludeFilePattern($config->get('filesystem.exclude_file_pattern')); $configuredFilter->setIncludeExtensions($config->get('filesystem.extensions')); $result = (object) array("path" => $file->getPublicPath(), "size" => $file->getSize(), "lastModified" => $file->getLastModified(), "isFile" => $file->isFile(), "canRead" => $file->canRead(), "canWrite" => $file->canWrite(), "canEdit" => $file->isFile() && $editFilter->accept($file), "canRename" => $renameFilter->accept($file), "canView" => $file->isFile() && $viewFilter->accept($file), "canPreview" => $file->isFile() && MOXMAN_Media_ImageAlter::canEdit($file), "visible" => $configuredFilter->accept($file), "exists" => $file->exists()); if ($meta) { $args = new MOXMAN_Vfs_CustomInfoEventArgs(MOXMAN_Vfs_CustomInfoEventArgs::INSERT_TYPE, $file); MOXMAN::getPluginManager()->get("core")->fire("CustomInfo", $args); $metaData = (object) array_merge($file->getMetaData()->getAll(), $args->getInfo()); if (MOXMAN_Media_ImageAlter::canEdit($file)) { $thumbnailFolderPath = MOXMAN_Util_PathUtils::combine($file->getParent(), $config->get('thumbnail.folder')); $thumbnailFile = MOXMAN::getFile($thumbnailFolderPath, $config->get('thumbnail.prefix') . $file->getName()); // TODO: Implement stat info cache layer here if ($file instanceof MOXMAN_Vfs_Local_File) { $info = MOXMAN_Media_MediaInfo::getInfo($file->getPath()); $metaData->width = $info["width"]; $metaData->height = $info["height"]; } if ($thumbnailFile->exists()) { $metaData->thumb_url = $thumbnailFile->getUrl(); // Get image size server side only on local filesystem if ($file instanceof MOXMAN_Vfs_Local_File) { $info = MOXMAN_Media_MediaInfo::getInfo($thumbnailFile->getPath()); $metaData->thumb_width = $info["width"]; $metaData->thumb_height = $info["height"]; } } } $metaData->url = $file->getUrl(); $result->meta = $metaData; } return $result; }
/** * Returns the meta data file instance used to store meta information. * * @param MOXMAN_Vfs_IFile $file File instance to get the meta data file for. * @return MOXMAN_Vfs_IFile Meta data file. */ protected function getMetaFile(MOXMAN_Vfs_IFile $file) { $metaFile = null; if ($file->exists()) { $parent = $file->getParentFile(); // Check if file isn't a root file if ($parent !== null) { $metaFile = $parent->getFileSystem()->getFile(MOXMAN_Util_PathUtils::combine($parent->getPath(), "meta.dat")); } } return $metaFile; }
/** * Returns an URL for the specified file object. * * @param MOXMAN_Vfs_IFile $file File to get the absolute URL for. * @return String Absolute URL for the specified file. */ public function getUrl(MOXMAN_Vfs_IFile $file) { $config = $file->getConfig(); // Get config items $wwwroot = $config->get("filesystem.local.wwwroot"); $prefix = $config->get("filesystem.local.urlprefix"); $suffix = $config->get("filesystem.local.urlsuffix"); // Map to wwwroot array if (is_array($wwwroot)) { foreach ($wwwroot as $rootPath => $rootConfig) { $rootPath = MOXMAN_Util_PathUtils::toAbsolute(MOXMAN_ROOT, $rootPath); if (strpos($file->getPath(), $rootPath) === 0) { $wwwroot = $rootPath; if (isset($rootConfig["wwwroot"])) { $wwwroot = $rootConfig["wwwroot"]; } if (isset($rootConfig["urlprefix"])) { $prefix = $rootConfig["urlprefix"]; } if (isset($rootConfig["urlsuffix"])) { $suffix = $rootConfig["urlsuffix"]; } break; } } if (is_array($wwwroot)) { $wwwroot = ""; } } $paths = MOXMAN_Util_PathUtils::getSitePaths(); // No wwwroot specified try to figure out a wwwroot if (!$wwwroot) { $wwwroot = $paths["wwwroot"]; } else { // Force the www root to an absolute file system path $wwwroot = MOXMAN_Util_PathUtils::toAbsolute(MOXMAN_ROOT, $wwwroot); } // Add prefix to URL if ($prefix == "") { $prefix = MOXMAN_Util_PathUtils::combine("{proto}://{host}", $paths["prefix"]); } // Replace protocol if (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == "on") { $prefix = str_replace("{proto}", "https", $prefix); } else { $prefix = str_replace("{proto}", "http", $prefix); } // Replace host/port $prefix = str_replace("{host}", $_SERVER['HTTP_HOST'], $prefix); $prefix = str_replace("{port}", $_SERVER['SERVER_PORT'], $prefix); // Insert path into URL if (stripos($file->getPath(), $wwwroot) === 0) { $url = substr($file->getPath(), strlen($wwwroot)); $url = MOXMAN_Util_PathUtils::combine($prefix, MOXMAN_Http_Uri::escapeUriString($url)); // Add suffix to URL if ($suffix) { $url .= $suffix; } return $url; } return ""; }
/** * Executes the command logic with the specified RPC parameters. * * @param Object $params Command parameters sent from client. * @return Object Result object to be passed back to client. */ public function execute($params) { $fromFile = MOXMAN::getFile($params->from); $toFile = MOXMAN::getFile($params->to); $config = $toFile->getConfig(); if ($config->get('general.demo')) { throw new MOXMAN_Exception("This action is restricted in demo mode.", MOXMAN_Exception::DEMO_MODE); } if (!$fromFile->exists()) { throw new MOXMAN_Exception("From file doesn't exist: " . $fromFile->getPublicPath(), MOXMAN_Exception::FILE_DOESNT_EXIST); } if (!$toFile->canWrite()) { throw new MOXMAN_Exception("No write access to file: " . $toFile->getPublicPath(), MOXMAN_Exception::NO_WRITE_ACCESS); } $paths = array(); $fileSystemManager = MOXMAN::getFileSystemManager(); $zipArchive = new ZipArchive(); $localTempFilePath = null; $result = array(); if ($fromFile instanceof MOXMAN_Vfs_Local_File) { $res = $zipArchive->open($fromFile->getPath()); } else { $localTempFilePath = $fileSystemManager->getLocalTempPath($fromFile); $fromFile->exportTo($localTempFilePath); $res = $zipArchive->open($localTempFilePath); } if ($res) { for ($i = 0; $i < $zipArchive->numFiles; $i++) { $stat = $zipArchive->statIndex($i); $paths[] = $stat["name"]; } $filter = MOXMAN_Vfs_BasicFileFilter::createFromConfig($config); $fileSystem = $toFile->getFileSystem(); foreach ($paths as $path) { $isFile = !preg_match('/\\/$/', $path); $toPath = MOXMAN_Util_PathUtils::combine($toFile->getPath(), iconv('cp437', 'UTF-8', $path)); $targetFile = MOXMAN::getFile($toPath); if ($filter->accept($targetFile, $isFile) === MOXMAN_Vfs_IFileFilter::ACCEPTED) { if ($isFile) { $content = $zipArchive->getFromName($path); // Fire before file action add event $args = new MOXMAN_Core_FileActionEventArgs("add", $targetFile); $args->getData()->fileSize = strlen($content); MOXMAN::getPluginManager()->get("core")->fire("BeforeFileAction", $args); $targetFile = $args->getFile(); $targetFile = $this->mkdirs($targetFile, true); $stream = $targetFile->open(MOXMAN_Vfs_IFileStream::WRITE); $stream->write($content); $stream->close(); //echo "Create file: ". $targetFile->getPublicPath() ."\n"; $this->fireFileAction(MOXMAN_Core_FileActionEventArgs::ADD, $targetFile); } else { $targetFile = $this->mkdirs($targetFile); } $result[] = $this->fileToJson($targetFile); } } $zipArchive->close(); if ($localTempFilePath) { $fileSystemManager->removeLocalTempFile($fromFile); } } return $result; }
private function getIndexPath(MOXMAN_Vfs_IFile $file) { $path = $file->getPath(); $rootName = $file->getFileSystem()->getRootName(); $publicPath = MOXMAN_Util_PathUtils::combine($rootName !== "/" ? "/" . $rootName : $rootName, substr($path, strlen($file->getFileSystem()->getRootPath()))); return $publicPath; }
/** * Removes the local temp file for a specific file instance. * * @param MOXMAN_Vfs_IFile File instance used to create a local temp file. */ public function removeLocalTempFile(MOXMAN_Vfs_IFile $file) { if ($file->exists()) { $tempDir = MOXMAN_Util_PathUtils::combine(MOXMAN_Util_PathUtils::getTempDir($this->config), "moxman_blob_cache"); $tempFile = MOXMAN_Util_PathUtils::combine($tempDir, md5($file->getPath() . $file->getLastModified()) . "." . MOXMAN_Util_PathUtils::getExtension($file->getName())); if (file_exists($tempFile)) { unlink($tempFile); } } }
/** * Process a request using the specified context. * * @param MOXMAN_Http_Context $httpContext Context instance to pass to use for the handler. */ public function processRequest(MOXMAN_Http_Context $httpContext) { $tempFilePath = null; $chunkFilePath = null; $request = $httpContext->getRequest(); $response = $httpContext->getResponse(); try { // Check if the user is authenticated or not if (!MOXMAN::getAuthManager()->isAuthenticated()) { if (!isset($json->method) || !preg_match('/^(login|logout)$/', $json->method)) { $exception = new MOXMAN_Exception("Access denied by authenticator(s).", 10); $exception->setData(array("login_url" => MOXMAN::getConfig()->get("authenticator.login_page"))); throw $exception; } } $file = MOXMAN::getFile($request->get("path")); $config = $file->getConfig(); if ($config->get('general.demo')) { throw new MOXMAN_Exception("This action is restricted in demo mode.", MOXMAN_Exception::DEMO_MODE); } $maxSizeBytes = preg_replace("/[^0-9.]/", "", $config->get("upload.maxsize")); if (strpos(strtolower($config->get("upload.maxsize")), "k") > 0) { $maxSizeBytes = round(floatval($maxSizeBytes) * 1024); } if (strpos(strtolower($config->get("upload.maxsize")), "m") > 0) { $maxSizeBytes = round(floatval($maxSizeBytes) * 1024 * 1024); } function generateRandomString($length = 10) { $characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'; $charactersLength = strlen($characters); $randomString = ''; for ($i = 0; $i < $length; $i++) { $randomString .= $characters[rand(0, $charactersLength - 1)]; } return $randomString; } $filename = generateRandomString() . '.' . MOXMAN_Util_PathUtils::getExtension($request->get("name")); $id = $request->get("id"); $loaded = intval($request->get("loaded", "0")); $total = intval($request->get("total", "-1")); $file = MOXMAN::getFile($file->getPath(), $filename); // Generate unique id for first chunk // TODO: We should cleanup orphan ID:s if upload fails etc if ($loaded == 0) { $id = uniqid(); } // Setup path to temp file based on id $tempFilePath = MOXMAN_Util_PathUtils::combine(MOXMAN_Util_PathUtils::getTempDir(), "mcupload_" . $id . "." . MOXMAN_Util_PathUtils::getExtension($file->getName())); $chunkFilePath = MOXMAN_Util_PathUtils::combine(MOXMAN_Util_PathUtils::getTempDir(), "mcupload_chunk_" . $id . "." . MOXMAN_Util_PathUtils::getExtension($file->getName())); if (!$file->canWrite()) { throw new MOXMAN_Exception("No write access to path: " . $file->getPublicPath(), MOXMAN_Exception::NO_WRITE_ACCESS); } if ($total > $maxSizeBytes) { throw new MOXMAN_Exception("File size to large: " . $file->getPublicPath(), MOXMAN_Exception::FILE_SIZE_TO_LARGE); } // Operations on first chunk if ($loaded == 0) { // Fire before file action add event $args = new MOXMAN_Core_FileActionEventArgs("add", $file); $args->getData()->fileSize = $total; MOXMAN::getPluginManager()->get("core")->fire("BeforeFileAction", $args); $file = $args->getFile(); if ($file->exists()) { if (!$config->get("upload.overwrite") && !$request->get("overwrite")) { throw new MOXMAN_Exception("Target file exists: " . $file->getPublicPath(), MOXMAN_Exception::FILE_EXISTS); } else { MOXMAN::getPluginManager()->get("core")->deleteThumbnail($file); $file->delete(); } } $filter = MOXMAN_Vfs_CombinedFileFilter::createFromConfig($config, "upload"); if ($filter->accept($file) !== MOXMAN_Vfs_CombinedFileFilter::ACCEPTED) { throw new MOXMAN_Exception("Invalid file name for: " . $file->getPublicPath(), MOXMAN_Exception::INVALID_FILE_NAME); } } $blobSize = 0; $inputFile = $request->getFile("file"); if (!$inputFile) { throw new MOXMAN_Exception("No input file specified."); } if ($loaded === 0) { // Check if we should mock or not if (defined('PHPUNIT')) { if (!copy($inputFile['tmp_name'], $tempFilePath)) { throw new MOXMAN_Exception("Could not move the uploaded temp file."); } } else { if (!move_uploaded_file($inputFile['tmp_name'], $tempFilePath)) { throw new MOXMAN_Exception("Could not move the uploaded temp file."); } } $blobSize = filesize($tempFilePath); } else { // Check if we should mock or not if (defined('PHPUNIT')) { if (!copy($inputFile['tmp_name'], $chunkFilePath)) { throw new MOXMAN_Exception("Could not move the uploaded temp file."); } } else { if (!move_uploaded_file($inputFile['tmp_name'], $chunkFilePath)) { throw new MOXMAN_Exception("Could not move the uploaded temp file."); } } $in = fopen($chunkFilePath, 'r'); if ($in) { $out = fopen($tempFilePath, 'a'); if ($out) { while ($buff = fread($in, 8192)) { $blobSize += strlen($buff); fwrite($out, $buff); } fclose($out); } fclose($in); } unlink($chunkFilePath); } // Import file when all chunks are complete if ($total == -1 || $loaded + $blobSize == $total) { clearstatcache(); // Check if file is valid on last chunk we also check on first chunk but not in the onces in between $filter = MOXMAN_Vfs_CombinedFileFilter::createFromConfig($config, "upload"); if ($filter->accept($file) !== MOXMAN_Vfs_CombinedFileFilter::ACCEPTED) { throw new MOXMAN_Exception("Invalid file name for: " . $file->getPublicPath(), MOXMAN_Exception::INVALID_FILE_NAME); } // Resize the temporary blob if ($config->get("upload.autoresize") && preg_match('/gif|jpe?g|png/i', MOXMAN_Util_PathUtils::getExtension($tempFilePath)) === 1) { $size = getimagesize($tempFilePath); $maxWidth = $config->get('upload.max_width'); $maxHeight = $config->get('upload.max_height'); if ($size[0] > $maxWidth || $size[1] > $maxHeight) { $imageAlter = new MOXMAN_Media_ImageAlter(); $imageAlter->load($tempFilePath); $imageAlter->resize($maxWidth, $maxHeight, true); $imageAlter->save($tempFilePath, $config->get("upload.autoresize_jpeg_quality")); } } // Create thumbnail and upload then import local blob MOXMAN::getPluginManager()->get("core")->createThumbnail($file, $tempFilePath); $file->importFrom($tempFilePath); unlink($tempFilePath); $args = new MOXMAN_Core_FileActionEventArgs("add", $file); MOXMAN::getPluginManager()->get("core")->fire("FileAction", $args); // In case file is modified $file = $args->getFile(); $result = MOXMAN_Core_Plugin::fileToJson($file, true); } else { $result = $id; } $response->sendJson(array("jsonrpc" => "2.0", "result" => $result, "id" => null)); } catch (Exception $e) { if ($tempFilePath && file_exists($tempFilePath)) { unlink($tempFilePath); } if ($chunkFilePath && file_exists($chunkFilePath)) { unlink($chunkFilePath); } MOXMAN::dispose(); // Closes any open file systems/connections $message = $e->getMessage(); $data = null; // Add file and line number when running in debug mode // @codeCoverageIgnoreStart if (MOXMAN::getConfig()->get("general.debug")) { $message .= " " . $e->getFile() . " (" . $e->getLine() . ")"; } // @codeCoverageIgnoreEnd // Grab the data from the exception if ($e instanceof MOXMAN_Exception && !$data) { $data = $e->getData(); } // Json encode error response $response->sendJson((object) array("jsonrpc" => "2.0", "error" => array("code" => $e->getCode(), "message" => $message, "data" => $data), "id" => null)); } }
private function deleteRecursive($path) { $handle = $this->fileSystem->getConnection(); $files = array(); $dirs = array(); $lines = ftp_rawlist($handle, $path); foreach ($lines as $line) { $matches = null; $unixRe = '/^([\\-ld])((?:[\\-r][\\-w][\\-xs]){3})\\s+(\\d+)\\s+(\\w+)\\s+([\\-\\w]+)\\s+(\\d+)\\s+(\\w+\\s+\\d+\\s+[\\w:]+)\\s+(.+)$/'; $windowsRe = "/^([^\\s]+\\s+[^\\s]+)\\s+((?:<DIR>|[\\w]+)?)\\s+(.+)\$/"; if (preg_match($unixRe, $line, $matches)) { $filePath = MOXMAN_Util_PathUtils::combine($path, $matches[8]); if ($matches[1] === "d") { $dirs[] = $filePath; } else { $files[] = $filePath; } } else { if (preg_match($windowsRe, $line, $matches)) { $filePath = MOXMAN_Util_PathUtils::combine($path, $matches[3]); if ($matches[2] === "<DIR>") { $dirs[] = $filePath; } else { $files[] = $filePath; } } else { // Unknown format throw new MOXMAN_Exception("Unknown FTP list format: " . $line); } } } // Delete files in dir foreach ($files as $file) { ftp_delete($handle, $file); } // Delete directories in dir foreach ($dirs as $dir) { $this->deleteRecursive($dir); } // Delete dir ftp_rmdir($handle, $path); }
/** * Lists files on the specified path. * * @param String $path */ public function listFiles($path) { $prefix = $this->getPrefixFromPath($path); $isTruncated = true; $marker = null; $files = array(); while ($isTruncated) { $query = array("delimiter" => "/", "max-keys" => "5000"); if ($prefix) { $query["prefix"] = $prefix; } if ($marker) { $query["marker"] = $marker; } $request = $this->createRequest("/"); $request->setQuery($this->buildQuery($query)); $response = $this->sendRequest($request); $xml = new SimpleXMLElement($response->getBody()); // List directories if (isset($xml->CommonPrefixes)) { foreach ($xml->CommonPrefixes as $cprefix) { if ($prefix != $cprefix->Prefix) { $stat = array("name" => basename($cprefix->Prefix), "isdir" => true, "size" => 0, "mdate" => 0); $path = MOXMAN_Util_PathUtils::combine($path, $stat["name"]); $files[] = $stat; } } } // List files if (isset($xml->Contents)) { foreach ($xml->Contents as $contents) { if ($prefix != $contents->Key) { $stat = array("name" => basename($contents->Key), "isdir" => strrpos($contents->Key, "/") === strlen($contents->Key) - 1, "size" => intval($contents->Size), "mdate" => strtotime($contents->LastModified)); $path = MOXMAN_Util_PathUtils::combine($path, $stat["name"]); $files[] = $stat; } } } $isTruncated = "" . $xml->IsTruncated === "true"; $marker = "" . $xml->NextMarker; } return $files; }