/** * 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 = MOXMAN_Util_Sanitize::fileName($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 instance based on the specified path. The path can be in the following formats: * - Scheme path: local:/mydir/myfile * - Encoded path: {0}/myfile * - Default scheme path: /myfile * * @param string $path Path to get the file system instance for. * @param string $childPath Path to the child of specified parent path. * @return MOXMAN_Vfs_IFile File instance from the specified path. */ public function getFile($path, $childPath = "") { // Verfiy that the path doesn't have any abnormalities $path = MOXMAN_Util_Sanitize::path($path); $childPath = MOXMAN_Util_Sanitize::childPath($childPath); if ($this->fileSystems) { $this->createFileSystems(); // Is a http URL then ask each file systems URL resolver for a file if (preg_match('/^https?:\\/\\//', $path)) { $file = null; foreach ($this->fileSystems as $fileSystem) { $urlResolver = $fileSystem->getFileUrlResolver(); if ($urlResolver) { $file = $urlResolver->getFile($path); if ($file) { break; } } } return $file; } if ($childPath) { $path = MOXMAN_Util_PathUtils::combine($path, $childPath); } // Decode {num} with root path $matches = array(); if (preg_match('/^\\{([0-9]+)\\}/', $path, $matches)) { $rootIdx = intval($matches[1]); if (!isset($this->fileSystems[$rootIdx])) { throw new MOXMAN_Exception("Could not decode {" . $rootIdx . "} with a root path. Index not found."); } $path = str_replace("{" . $rootIdx . "}", $this->fileSystems[$rootIdx]->getRootPath(), $path); } // Parse scheme like db, zip, $matches = array(); $scheme = ""; if (preg_match('/^([a-z0-9]+):\\/\\/(.+)$/', $path, $matches)) { $scheme = $matches[1]; //$pathPart = $matches[2]; //$pathPart = substr($pathPart, 0, 1) !== "/" ? "/" . $pathPart : $pathPart; } // Get file from one of the file systems foreach ($this->fileSystems as $fileSystem) { if (!$scheme || $fileSystem->getScheme() === $scheme) { // Check if it matches the absolute root if (strpos($path, $fileSystem->getRootPath()) === 0) { $file = $fileSystem->getFile($path); return $file; } // Check if path matches the public root $rootPrefix = $fileSystem->getRootName(); if ($rootPrefix !== '/') { $rootPrefix = '/' . $rootPrefix; } if ($path === $rootPrefix) { return $fileSystem->getRootFile(); } if ($rootPrefix !== '/') { $rootPrefix .= '/'; } // Check if path matches the beginning of public root if (strpos($path, $rootPrefix) === 0) { $filePath = MOXMAN_Util_PathUtils::combine($fileSystem->getRootPath(), substr($path, strlen($rootPrefix))); $file = $fileSystem->getFile($filePath); return $file; } } } } // Could not resolve path no file system returned a file throw new MOXMAN_Exception("Could not resolve path: " . $path); }
/** * 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 { if ($request->getMethod() != 'POST') { throw new MOXMAN_Exception("Not a HTTP post request."); } if (MOXMAN::getConfig()->get('general.csrf', true)) { if (!MOXMAN_Http_Csrf::verifyToken(MOXMAN::getConfig()->get('general.license'), $request->get('csrf'))) { throw new MOXMAN_Exception("Invalid csrf token."); } } // Check if the user is authenticated or not if (!MOXMAN::getAuthManager()->isAuthenticated()) { if (!isset($json->method) || !preg_match('/^(login|logout)$/', $json->method)) { throw new MOXMAN_Exception("Access denied by authenticator(s).", 10); } } $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); } $uploadMaxSize = $config->get("upload.maxsize", "10mb"); $maxSizeBytes = preg_replace("/[^0-9.]/", "", $uploadMaxSize); if (strpos(strtolower($uploadMaxSize), "k") > 0) { $maxSizeBytes = round(floatval($maxSizeBytes) * 1024); } if (strpos(strtolower($uploadMaxSize), "m") > 0) { $maxSizeBytes = round(floatval($maxSizeBytes) * 1024 * 1024); } $filename = $request->get("name"); $id = MOXMAN_Util_Sanitize::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 (!$id || $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 $filter = MOXMAN_Vfs_CombinedFileFilter::createFromConfig($config, "upload"); if (!$filter->accept($file)) { 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(); // Fire off event before file is permanently written to disk $args = new MOXMAN_Vfs_FileActionEventArgs("add", $file); $args->getData()->fileSize = $total; MOXMAN::getPluginManager()->get("core")->fire("BeforeFileAction", $args); $file = $args->getFile(); // 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)) { throw new MOXMAN_Exception("Invalid file name for: " . $file->getPublicPath(), MOXMAN_Exception::INVALID_FILE_NAME); } if ($file->exists()) { $resolution = $request->get("resolution"); if ($resolution == "overwrite") { MOXMAN::getPluginManager()->get("core")->deleteFile($file); } else { if ($resolution == "rename") { $file = MOXMAN_Util_FileUtils::uniqueFile($file); } else { throw new MOXMAN_Exception("Target file exists: " . $file->getPublicPath(), MOXMAN_Exception::FILE_EXISTS); } } } // 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', -1); $maxHeight = $config->get('upload.max_height', -1); if ($maxWidth > 0 && $maxHeight > 0 && ($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", 90)); } } // Create thumbnail and upload then import local blob MOXMAN::getPluginManager()->get("core")->createThumbnail($file, $tempFilePath); $file->importFrom($tempFilePath); unlink($tempFilePath); $args = new MOXMAN_Vfs_FileActionEventArgs("add", $file); MOXMAN::getPluginManager()->get("core")->fire("FileAction", $args); $result = array("file" => MOXMAN_CorePlugin::fileToJson($args->getFile(), true), "files" => MOXMAN_CorePlugin::filesToJson($args->getFileList(), 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)); } }
/** * 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(); $size = 0; 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)) { 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(), MOXMAN_Util_Sanitize::fileName($params->tempname)); $size = filesize($tempFilePath); $file->importFrom($tempFilePath); } $args = $this->fireBeforeFileAction("add", $file, $size); $file = $args->getFile(); MOXMAN::getFileSystemManager()->removeLocalTempFile($file); $this->fireFileAction(MOXMAN_Vfs_FileActionEventArgs::ADD, $file); return parent::fileToJson($file, true); }