public function dir_rewinddir() { if ($this->dH == -1) { self::$currentListingIndex = 0; } else { return rewinddir($this->dH); } }
public function switchAction($action, $httpVars, $fileVars) { $selection = new UserSelection(); $dir = $httpVars["dir"] or ""; $dir = AJXP_Utils::decodeSecureMagic($dir); if ($dir == "/") { $dir = ""; } $selection->initFromHttpVars($httpVars); if (!$selection->isEmpty()) { //$this->filterUserSelectionToHidden($selection->getFiles()); } $urlBase = "pydio://" . ConfService::getRepository()->getId(); $mess = ConfService::getMessages(); switch ($action) { case "monitor_compression": $percentFile = fsAccessWrapper::getRealFSReference($urlBase . $dir . "/.zip_operation_" . $httpVars["ope_id"]); $percent = 0; if (is_file($percentFile)) { $percent = intval(file_get_contents($percentFile)); } if ($percent < 100) { AJXP_XMLWriter::header(); AJXP_XMLWriter::triggerBgAction("monitor_compression", $httpVars, $mess["powerfs.1"] . " ({$percent}%)", true, 1); AJXP_XMLWriter::close(); } else { @unlink($percentFile); AJXP_XMLWriter::header(); if ($httpVars["on_end"] == "reload") { AJXP_XMLWriter::triggerBgAction("reload_node", array(), "powerfs.2", true, 2); } else { $archiveName = AJXP_Utils::sanitize($httpVars["archive_name"], AJXP_SANITIZE_FILENAME); $archiveName = str_replace("'", "\\'", $archiveName); $jsCode = "\n PydioApi.getClient().downloadSelection(null, \$('download_form'), 'postcompress_download', {ope_id:'" . $httpVars["ope_id"] . "',archive_name:'" . $archiveName . "'});\n "; AJXP_XMLWriter::triggerBgJsAction($jsCode, $mess["powerfs.3"], true); AJXP_XMLWriter::triggerBgAction("reload_node", array(), "powerfs.2", true, 2); } AJXP_XMLWriter::close(); } break; case "postcompress_download": $archive = AJXP_Utils::getAjxpTmpDir() . DIRECTORY_SEPARATOR . $httpVars["ope_id"] . "_" . AJXP_Utils::sanitize(AJXP_Utils::decodeSecureMagic($httpVars["archive_name"]), AJXP_SANITIZE_FILENAME); $fsDriver = AJXP_PluginsService::getInstance()->getUniqueActivePluginForType("access"); if (is_file($archive)) { if (!$fsDriver->getFilteredOption("USE_XSENDFILE", ConfService::getRepository()) && !$fsDriver->getFilteredOption("USE_XACCELREDIRECT", ConfService::getRepository())) { register_shutdown_function("unlink", $archive); } $fsDriver->readFile($archive, "force-download", $httpVars["archive_name"], false, null, true); } else { echo "<script>alert('Cannot find archive! Is ZIP correctly installed?');</script>"; } break; case "compress": case "precompress": $archiveName = AJXP_Utils::sanitize(AJXP_Utils::decodeSecureMagic($httpVars["archive_name"]), AJXP_SANITIZE_FILENAME); if (!ConfService::currentContextIsCommandLine() && ConfService::backgroundActionsSupported()) { $opeId = substr(md5(time()), 0, 10); $httpVars["ope_id"] = $opeId; AJXP_Controller::applyActionInBackground(ConfService::getRepository()->getId(), $action, $httpVars); AJXP_XMLWriter::header(); $bgParameters = array("dir" => SystemTextEncoding::toUTF8($dir), "archive_name" => SystemTextEncoding::toUTF8($archiveName), "on_end" => isset($httpVars["on_end"]) ? $httpVars["on_end"] : "reload", "ope_id" => $opeId); AJXP_XMLWriter::triggerBgAction("monitor_compression", $bgParameters, $mess["powerfs.1"] . " (0%)", true); AJXP_XMLWriter::close(); session_write_close(); exit; } $rootDir = fsAccessWrapper::getRealFSReference($urlBase) . $dir; $percentFile = $rootDir . "/.zip_operation_" . $httpVars["ope_id"]; $compressLocally = $action == "compress" ? true : false; // List all files $todo = array(); $args = array(); $replaceSearch = array($rootDir, "\\"); $replaceReplace = array("", "/"); foreach ($selection->getFiles() as $selectionFile) { $baseFile = $selectionFile; $args[] = escapeshellarg(substr($selectionFile, strlen($dir) + ($dir == "/" ? 0 : 1))); $selectionFile = fsAccessWrapper::getRealFSReference($urlBase . $selectionFile); $todo[] = ltrim(str_replace($replaceSearch, $replaceReplace, $selectionFile), "/"); if (is_dir($selectionFile)) { $objects = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($selectionFile), RecursiveIteratorIterator::SELF_FIRST); foreach ($objects as $name => $object) { $todo[] = str_replace($replaceSearch, $replaceReplace, $name); } } if (trim($baseFile, "/") == "") { // ROOT IS SELECTED, FIX IT $args = array(escapeshellarg(basename($rootDir))); $rootDir = dirname($rootDir); break; } } $cmdSeparator = PHP_OS == "WIN32" || PHP_OS == "WINNT" || PHP_OS == "Windows" ? "&" : ";"; if (!$compressLocally) { $archiveName = AJXP_Utils::getAjxpTmpDir() . DIRECTORY_SEPARATOR . $httpVars["ope_id"] . "_" . $archiveName; } chdir($rootDir); $cmd = $this->getFilteredOption("ZIP_PATH") . " -r " . escapeshellarg($archiveName) . " " . implode(" ", $args); $fsDriver = AJXP_PluginsService::getInstance()->getUniqueActivePluginForType("access"); $c = $fsDriver->getConfigs(); if ((!isset($c["SHOW_HIDDEN_FILES"]) || $c["SHOW_HIDDEN_FILES"] == false) && stripos(PHP_OS, "win") === false) { $cmd .= " -x .\\*"; } $cmd .= " " . $cmdSeparator . " echo ZIP_FINISHED"; $proc = popen($cmd, "r"); $toks = array(); $handled = array(); $finishedEchoed = false; while (!feof($proc)) { set_time_limit(20); $results = fgets($proc, 256); if (strlen($results) == 0) { } else { $tok = strtok($results, "\n"); while ($tok !== false) { $toks[] = $tok; if ($tok == "ZIP_FINISHED") { $finishedEchoed = true; } else { $test = preg_match('/(\\w+): (.*) \\(([^\\(]+)\\) \\(([^\\(]+)\\)/', $tok, $matches); if ($test !== false) { $handled[] = $matches[2]; } } $tok = strtok("\n"); } if ($finishedEchoed) { $percent = 100; } else { $percent = min(round(count($handled) / count($todo) * 100), 100); } file_put_contents($percentFile, $percent); } // avoid a busy wait if ($percent < 100) { usleep(1); } } pclose($proc); file_put_contents($percentFile, 100); break; default: break; } }
public function readFile($filePathOrData, $headerType = "plain", $localName = "", $data = false, $gzip = null, $realfileSystem = false, $byteOffset = -1, $byteLength = -1) { if ($gzip === null) { $gzip = ConfService::getCoreConf("GZIP_COMPRESSION"); } if (!$realfileSystem && $this->wrapperClassName == "fsAccessWrapper") { $originalFilePath = $filePathOrData; $filePathOrData = fsAccessWrapper::patchPathForBaseDir($filePathOrData); } session_write_close(); restore_error_handler(); restore_exception_handler(); set_exception_handler('download_exception_handler'); set_error_handler('download_exception_handler'); // required for IE, otherwise Content-disposition is ignored if (ini_get('zlib.output_compression')) { AJXP_Utils::safeIniSet('zlib.output_compression', 'Off'); } $isFile = !$data && !$gzip; if ($byteLength == -1) { if ($data) { $size = strlen($filePathOrData); } else { if ($realfileSystem) { $size = sprintf("%u", filesize($filePathOrData)); } else { $size = $this->filesystemFileSize($filePathOrData); } } } else { $size = $byteLength; } if ($gzip && ($size > ConfService::getCoreConf("GZIP_LIMIT") || !function_exists("gzencode") || @strpos($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip') === FALSE)) { $gzip = false; // disable gzip } $localName = $localName == "" ? basename(isset($originalFilePath) ? $originalFilePath : $filePathOrData) : $localName; if ($headerType == "plain") { header("Content-type:text/plain"); } else { if ($headerType == "image") { header("Content-Type: " . AJXP_Utils::getImageMimeType(basename($filePathOrData)) . "; name=\"" . $localName . "\""); header("Content-Length: " . $size); header('Cache-Control: public'); } else { /* if (preg_match('/ MSIE /',$_SERVER['HTTP_USER_AGENT']) || preg_match('/ WebKit /',$_SERVER['HTTP_USER_AGENT'])) { $localName = str_replace("+", " ", urlencode(SystemTextEncoding::toUTF8($localName))); } */ if ($isFile) { header("Accept-Ranges: 0-{$size}"); $this->logDebug("Sending accept range 0-{$size}"); } // Check if we have a range header (we are resuming a transfer) if (isset($_SERVER['HTTP_RANGE']) && $isFile && $size != 0) { if ($headerType == "stream_content") { if (extension_loaded('fileinfo') && $this->wrapperClassName == "fsAccessWrapper") { $fInfo = new fInfo(FILEINFO_MIME); $realfile = call_user_func(array($this->wrapperClassName, "getRealFSReference"), $filePathOrData); $mimeType = $fInfo->file($realfile); $splitChar = explode(";", $mimeType); $mimeType = trim($splitChar[0]); $this->logDebug("Detected mime {$mimeType} for {$realfile}"); } else { $mimeType = AJXP_Utils::getStreamingMimeType(basename($filePathOrData)); } header('Content-type: ' . $mimeType); } // multiple ranges, which can become pretty complex, so ignore it for now $ranges = explode('=', $_SERVER['HTTP_RANGE']); $offsets = explode('-', $ranges[1]); $offset = floatval($offsets[0]); $length = floatval($offsets[1]) - $offset; if (!$length) { $length = $size - $offset; } if ($length + $offset > $size || $length < 0) { $length = $size - $offset; } $this->logDebug('Content-Range: bytes ' . $offset . '-' . $length . '/' . $size); header('HTTP/1.1 206 Partial Content'); header('Content-Range: bytes ' . $offset . '-' . ($offset + $length) . '/' . $size); header("Content-Length: " . $length); $file = fopen($filePathOrData, 'rb'); fseek($file, 0); $relOffset = $offset; while ($relOffset > 2000000000.0) { // seek to the requested offset, this is 0 if it's not a partial content request fseek($file, 2000000000, SEEK_CUR); $relOffset -= 2000000000; // This works because we never overcome the PHP 32 bit limit } fseek($file, $relOffset, SEEK_CUR); while (ob_get_level()) { ob_end_flush(); } $readSize = 0.0; $bufferSize = 1024 * 8; while (!feof($file) && $readSize < $length && connection_status() == 0) { $this->logDebug("dl reading {$readSize} to {$length}", $_SERVER["HTTP_RANGE"]); echo fread($file, $bufferSize); $readSize += $bufferSize; flush(); } fclose($file); return; } else { if ($gzip) { $gzippedData = $data ? gzencode($filePathOrData, 9) : gzencode(file_get_contents($filePathOrData), 9); $size = strlen($gzippedData); } HTMLWriter::generateAttachmentsHeader($localName, $size, $isFile, $gzip); if ($gzip) { print $gzippedData; return; } } } } if ($data) { print $filePathOrData; } else { if ($this->getFilteredOption("USE_XSENDFILE", $this->repository->getId()) && $this->wrapperClassName == "fsAccessWrapper") { if (!$realfileSystem) { $filePathOrData = fsAccessWrapper::getRealFSReference($filePathOrData); } $filePathOrData = str_replace("\\", "/", $filePathOrData); $server_name = $_SERVER["SERVER_SOFTWARE"]; $regex = '/^(lighttpd\\/1.4).([0-9]{2}$|[0-9]{3}$|[0-9]{4}$)+/'; if (preg_match($regex, $server_name)) { $header_sendfile = "X-LIGHTTPD-send-file"; } else { $header_sendfile = "X-Sendfile"; } header($header_sendfile . ": " . SystemTextEncoding::toUTF8($filePathOrData)); header("Content-type: application/octet-stream"); header('Content-Disposition: attachment; filename="' . basename($filePathOrData) . '"'); return; } if ($this->getFilteredOption("USE_XACCELREDIRECT", $this->repository->getId()) && $this->wrapperClassName == "fsAccessWrapper" && array_key_exists("X-Accel-Mapping", $_SERVER)) { if (!$realfileSystem) { $filePathOrData = fsAccessWrapper::getRealFSReference($filePathOrData); } $filePathOrData = str_replace("\\", "/", $filePathOrData); $filePathOrData = SystemTextEncoding::toUTF8($filePathOrData); $mapping = explode('=', $_SERVER['X-Accel-Mapping']); $replacecount = 0; $accelfile = str_replace($mapping[0], $mapping[1], $filePathOrData, $replacecount); if ($replacecount == 1) { header("X-Accel-Redirect: {$accelfile}"); header("Content-type: application/octet-stream"); header('Content-Disposition: attachment; filename="' . basename($accelfile) . '"'); return; } else { $this->logError("X-Accel-Redirect", "Problem with X-Accel-Mapping for file {$filePathOrData}"); } } $stream = fopen("php://output", "a"); if ($realfileSystem) { $this->logDebug("realFS!", array("file" => $filePathOrData)); $fp = fopen($filePathOrData, "rb"); if ($byteOffset != -1) { fseek($fp, $byteOffset); } $sentSize = 0; $readChunk = 4096; while (!feof($fp)) { if ($byteLength != -1 && $sentSize + $readChunk >= $byteLength) { // compute last chunk and break after $readChunk = $byteLength - $sentSize; $break = true; } $data = fread($fp, $readChunk); $dataSize = strlen($data); fwrite($stream, $data, $dataSize); $sentSize += $dataSize; if (isset($break)) { break; } } fclose($fp); } else { call_user_func(array($this->wrapperClassName, "copyFileInStream"), $filePathOrData, $stream); } fflush($stream); fclose($stream); } }
function switchAction($action, $httpVars, $fileVars) { if (!isset($this->actions[$action])) { return; } $selection = new UserSelection(); $dir = $httpVars["dir"] or ""; $dir = AJXP_Utils::securePath($dir); if ($dir == "/") { $dir = ""; } $selection->initFromHttpVars($httpVars); if (!$selection->isEmpty()) { //$this->filterUserSelectionToHidden($selection->getFiles()); } $urlBase = "ajxp.fs://" . ConfService::getRepository()->getId(); $mess = ConfService::getMessages(); switch ($action) { case "monitor_compression": $percentFile = fsAccessWrapper::getRealFSReference($urlBase . $dir . "/.zip_operation_" . $httpVars["ope_id"]); $percent = 0; if (is_file($percentFile)) { $percent = intval(file_get_contents($percentFile)); } if ($percent < 100) { AJXP_XMLWriter::header(); AJXP_XMLWriter::triggerBgAction("monitor_compression", $httpVars, $mess["powerfs.1"] . " ({$percent}%)", true, 1); AJXP_XMLWriter::close(); } else { @unlink($percentFile); AJXP_XMLWriter::header(); if ($httpVars["on_end"] == "reload") { AJXP_XMLWriter::triggerBgAction("reload_node", array(), "powerfs.2", true, 2); } else { $archiveName = $httpVars["archive_name"]; $jsCode = "\n \$('download_form').action = window.ajxpServerAccessPath;\n \$('download_form').secure_token.value = window.Connexion.SECURE_TOKEN;\n \$('download_form').select('input').each(function(input){\n if(input.name!='get_action' && input.name!='secure_token') input.remove();\n });\n \$('download_form').insert(new Element('input', {type:'hidden', name:'ope_id', value:'" . $httpVars["ope_id"] . "'}));\n \$('download_form').insert(new Element('input', {type:'hidden', name:'archive_name', value:'" . $archiveName . "'}));\n \$('download_form').insert(new Element('input', {type:'hidden', name:'get_action', value:'postcompress_download'}));\n \$('download_form').submit();\n "; AJXP_XMLWriter::triggerBgJsAction($jsCode, "powerfs.3", true); AJXP_XMLWriter::triggerBgAction("reload_node", array(), "powerfs.2", true, 2); } AJXP_XMLWriter::close(); } break; case "postcompress_download": $archive = AJXP_Utils::getAjxpTmpDir() . "/" . $httpVars["ope_id"] . "_" . $httpVars["archive_name"]; //$fsDriver = new fsAccessDriver("fake", ""); $fsDriver = AJXP_PluginsService::getInstance()->getUniqueActivePluginForType("access"); $fsDriver->readFile($archive, "force-download", $httpVars["archive_name"], false, null, true); break; case "compress": case "precompress": if (!ConfService::currentContextIsCommandLine() && ConfService::backgroundActionsSupported()) { $opeId = substr(md5(time()), 0, 10); $httpVars["ope_id"] = $opeId; AJXP_Controller::applyActionInBackground(ConfService::getRepository()->getId(), $action, $httpVars); AJXP_XMLWriter::header(); $bgParameters = array("dir" => $dir, "archive_name" => $httpVars["archive_name"], "on_end" => isset($httpVars["on_end"]) ? $httpVars["on_end"] : "reload", "ope_id" => $opeId); AJXP_XMLWriter::triggerBgAction("monitor_compression", $bgParameters, $mess["powerfs.1"] . " (0%)", true); AJXP_XMLWriter::close(); session_write_close(); exit; } $rootDir = fsAccessWrapper::getRealFSReference($urlBase) . $dir; $percentFile = $rootDir . "/.zip_operation_" . $httpVars["ope_id"]; $compressLocally = $action == "compress" ? true : false; // List all files $todo = array(); $args = array(); $replaceSearch = array($rootDir, "\\"); $replaceReplace = array("", "/"); foreach ($selection->getFiles() as $selectionFile) { $args[] = '"' . substr($selectionFile, strlen($dir) + ($dir == "/" ? 0 : 1)) . '"'; $selectionFile = fsAccessWrapper::getRealFSReference($urlBase . $selectionFile); $todo[] = ltrim(str_replace($replaceSearch, $replaceReplace, $selectionFile), "/"); if (is_dir($selectionFile)) { $objects = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($selectionFile), RecursiveIteratorIterator::SELF_FIRST); foreach ($objects as $name => $object) { $todo[] = str_replace($replaceSearch, $replaceReplace, $name); } } } $cmdSeparator = PHP_OS == "WIN32" || PHP_OS == "WINNT" || PHP_OS == "Windows" ? "&" : ";"; $archiveName = $httpVars["archive_name"]; if (!$compressLocally) { $archiveName = AJXP_Utils::getAjxpTmpDir() . "/" . $httpVars["ope_id"] . "_" . $archiveName; } chdir($rootDir); $cmd = "zip -r \"" . $archiveName . "\" " . implode(" ", $args); $fsDriver = AJXP_PluginsService::getInstance()->getUniqueActivePluginForType("access"); $c = $fsDriver->getConfigs(); if (!isset($c["SHOW_HIDDEN_FILES"]) || $c["SHOW_HIDDEN_FILES"] == false) { $cmd .= " -x .\\*"; } $cmd .= " " . $cmdSeparator . " echo ZIP_FINISHED"; $proc = popen($cmd, "r"); $toks = array(); $handled = array(); $finishedEchoed = false; while (!feof($proc)) { set_time_limit(20); $results = fgets($proc, 256); if (strlen($results) == 0) { } else { $tok = strtok($results, "\n"); while ($tok !== false) { $toks[] = $tok; if ($tok == "ZIP_FINISHED") { $finishedEchoed = true; } else { $test = preg_match('/(\\w+): (.*) \\(([^\\(]+)\\) \\(([^\\(]+)\\)/', $tok, $matches); if ($test !== false) { $handled[] = $matches[2]; } } $tok = strtok("\n"); } if ($finishedEchoed) { $percent = 100; } else { $percent = min(round(count($handled) / count($todo) * 100), 100); } file_put_contents($percentFile, $percent); } // avoid a busy wait if ($percent < 100) { usleep(1); } } pclose($proc); file_put_contents($percentFile, 100); break; default: break; } }
public function dir_readdir() { $x = parent::dir_readdir(); if (strstr($x, '%') !== false) { $x = urldecode($x); } return $x; }
/** * @param string $url * @param AJXP_MetaStreamWrapper $crtInstance * @return string * @throws Exception */ protected static function translateScheme($url, $crtInstance = null) { $parts = parse_url($url); $currentScheme = $parts['scheme']; $context = self::actualRepositoryWrapperProtocol($parts['host']); $newScheme = self::getNextScheme($url, $context); $repository = ConfService::getRepositoryById(parse_url($url, PHP_URL_HOST)); if ($currentScheme == "pydio" && $repository->hasContentFilter()) { $contentFilter = $repository->getContentFilter(); if ($contentFilter instanceof ContentFilter) { $baseDir = $contentFilter->getBaseDir(); if ($crtInstance != null) { $crtInstance->currentUniquePath = $contentFilter->getUniquePath(); } if (!empty($baseDir) || $baseDir != "/") { $crtPath = parse_url($url, PHP_URL_PATH); $crtBase = basename($crtPath); if (!empty($crtPath) && $crtPath != "/" && fsAccessWrapper::unPatchPathForBaseDir($crtBase) != $contentFilter->getUniquePath() && $crtBase != ".ajxp_meta") { throw new Exception("Cannot find file " . $crtBase); } // Prepend baseDir in path $url = str_replace($currentScheme . "://" . $repository->getId() . $crtPath, $currentScheme . "://" . $repository->getId() . rtrim($baseDir . $crtPath, "/"), $url); } } } $newUrl = str_replace($currentScheme . "://", $newScheme . "://", $url); self::applyInitPathHook($newUrl, $context); return $newUrl; }
public function rename($from, $to) { $fromUrl = parse_url($from); $repoId = $fromUrl["host"]; $repoObject = ConfService::getRepositoryById($repoId); $isViPR = $repoObject->getOption("IS_VIPR"); $isDir = false; if ($isViPR === true) { if (is_dir($from . "/")) { $from .= '/'; $to .= '/'; $isDir = true; } } if ($isDir === true || is_dir($from)) { AJXP_Logger::debug(__CLASS__, __FUNCTION__, "S3 Renaming dir {$from} to {$to}"); require_once "aws.phar"; $fromUrl = parse_url($from); $repoId = $fromUrl["host"]; $repoObject = ConfService::getRepositoryById($repoId); if (!isset($repoObject)) { $e = new Exception("Cannot find repository with id " . $repoId); self::$lastException = $e; throw $e; } // Get a client $options = array('key' => $repoObject->getOption("API_KEY"), 'secret' => $repoObject->getOption("SECRET_KEY")); $baseURL = $repoObject->getOption("STORAGE_URL"); if (!empty($baseURL)) { $options["base_url"] = $baseURL; } else { $options["region"] = $repoObject->getOption("REGION"); } $proxy = $repoObject->getOption("PROXY"); if (!empty($proxy)) { $options['request.options'] = array('proxy' => $proxy); } $s3Client = S3Client::factory($options); $bucket = $repoObject->getOption("CONTAINER"); $basePath = $repoObject->getOption("PATH"); $fromKeyname = trim(str_replace("//", "/", $basePath . parse_url($from, PHP_URL_PATH)), '/'); $toKeyname = trim(str_replace("//", "/", $basePath . parse_url($to, PHP_URL_PATH)), '/'); if ($isViPR) { $toKeyname .= '/'; $parts = explode('/', $bucket); $bucket = $parts[0]; if (isset($parts[1])) { $fromKeyname = $parts[1] . "/" . $fromKeyname; } } // Perform a batch of CopyObject operations. $batch = array(); $iterator = $s3Client->getIterator('ListObjects', array('Bucket' => $bucket, 'Prefix' => $fromKeyname . "/")); $toDelete = array(); AJXP_Logger::debug(__CLASS__, __FUNCTION__, "S3 Got iterator looking for prefix " . $fromKeyname . "/ , and toKeyName=" . $toKeyname); foreach ($iterator as $object) { $currentFrom = $object['Key']; $currentTo = $toKeyname . substr($currentFrom, strlen($fromKeyname)); if ($isViPR) { if (isset($parts[1])) { $currentTo = $parts[1] . "/" . $currentTo; } } AJXP_Logger::debug(__CLASS__, __FUNCTION__, "S3 Should move one object " . $currentFrom . " to new key :" . $currentTo); $batch[] = $s3Client->getCommand('CopyObject', array('Bucket' => $bucket, 'Key' => "{$currentTo}", 'CopySource' => "{$bucket}/" . rawurlencode($currentFrom))); $toDelete[] = $currentFrom; } try { AJXP_Logger::debug(__CLASS__, __FUNCTION__, "S3 Execute batch on " . count($batch) . " objects"); $successful = $s3Client->execute($batch); $failed = array(); $iterator->rewind(); $clear = new \Aws\S3\Model\ClearBucket($s3Client, $bucket); $clear->setIterator($iterator); $clear->clear(); } catch (\Guzzle\Service\Exception\CommandTransferException $e) { $successful = $e->getSuccessfulCommands(); $failed = $e->getFailedCommands(); } if (count($failed)) { foreach ($failed as $c) { // $c is a Aws\S3\Command\S3Command AJXP_Logger::error("S3Wrapper", __FUNCTION__, "Error while copying: " . $c->getOperation()->getServiceDescription()); } self::$lastException = new Exception("Failed moving folder: " . count($failed)); return false; } return true; } else { AJXP_Logger::debug(__CLASS__, __FUNCTION__, "S3 Execute standard rename on " . $from . " to " . $to); return parent::rename($from, $to); } }
function readFile($filePathOrData, $headerType = "plain", $localName = "", $data = false, $gzip = null, $realfileSystem = false, $byteOffset = -1, $byteLength = -1) { if ($gzip === null) { $gzip = ConfService::getCoreConf("GZIP_COMPRESSION"); } if (!$realfileSystem && $this->wrapperClassName == "fsAccessWrapper") { $originalFilePath = $filePathOrData; $filePathOrData = fsAccessWrapper::patchPathForBaseDir($filePathOrData); } session_write_close(); restore_error_handler(); restore_exception_handler(); set_exception_handler('download_exception_handler'); set_error_handler('download_exception_handler'); // required for IE, otherwise Content-disposition is ignored if (ini_get('zlib.output_compression')) { AJXP_Utils::safeIniSet('zlib.output_compression', 'Off'); } $isFile = !$data && !$gzip; if ($byteLength == -1) { if ($data) { $size = strlen($filePathOrData); } else { if ($realfileSystem) { $size = sprintf("%u", filesize($filePathOrData)); } else { $size = $this->filesystemFileSize($filePathOrData); } } } else { $size = $byteLength; } if ($gzip && ($size > ConfService::getCoreConf("GZIP_LIMIT") || !function_exists("gzencode") || @strpos($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip') === FALSE)) { $gzip = false; // disable gzip } $localName = $localName == "" ? basename(isset($originalFilePath) ? $originalFilePath : $filePathOrData) : $localName; if ($headerType == "plain") { header("Content-type:text/plain"); } else { if ($headerType == "image") { header("Content-Type: " . AJXP_Utils::getImageMimeType(basename($filePathOrData)) . "; name=\"" . $localName . "\""); header("Content-Length: " . $size); header('Cache-Control: public'); } else { /* if(preg_match('/ MSIE /',$_SERVER['HTTP_USER_AGENT']) || preg_match('/ WebKit /',$_SERVER['HTTP_USER_AGENT'])){ $localName = str_replace("+", " ", urlencode(SystemTextEncoding::toUTF8($localName))); } */ if ($isFile) { header("Accept-Ranges: 0-{$size}"); AJXP_Logger::debug("Sending accept range 0-{$size}"); } // Check if we have a range header (we are resuming a transfer) if (isset($_SERVER['HTTP_RANGE']) && $isFile && $size != 0) { if ($headerType == "stream_content") { if (extension_loaded('fileinfo') && $this->wrapperClassName == "fsAccessWrapper") { $fInfo = new fInfo(FILEINFO_MIME); $realfile = call_user_func(array($this->wrapperClassName, "getRealFSReference"), $filePathOrData); $mimeType = $fInfo->file($realfile); $splitChar = explode(";", $mimeType); $mimeType = trim($splitChar[0]); AJXP_Logger::debug("Detected mime {$mimeType} for {$realfile}"); } else { $mimeType = AJXP_Utils::getStreamingMimeType(basename($filePathOrData)); } header('Content-type: ' . $mimeType); } // multiple ranges, which can become pretty complex, so ignore it for now $ranges = explode('=', $_SERVER['HTTP_RANGE']); $offsets = explode('-', $ranges[1]); $offset = floatval($offsets[0]); $length = floatval($offsets[1]) - $offset; if (!$length) { $length = $size - $offset; } if ($length + $offset > $size || $length < 0) { $length = $size - $offset; } AJXP_Logger::debug('Content-Range: bytes ' . $offset . '-' . $length . '/' . $size); header('HTTP/1.1 206 Partial Content'); header('Content-Range: bytes ' . $offset . '-' . ($offset + $length) . '/' . $size); header("Content-Length: " . $length); $file = fopen($filePathOrData, 'rb'); fseek($file, 0); $relOffset = $offset; while ($relOffset > 2000000000.0) { // seek to the requested offset, this is 0 if it's not a partial content request fseek($file, 2000000000, SEEK_CUR); $relOffset -= 2000000000; // This works because we never overcome the PHP 32 bit limit } fseek($file, $relOffset, SEEK_CUR); while (ob_get_level()) { ob_end_flush(); } $readSize = 0.0; $bufferSize = 1024 * 8; while (!feof($file) && $readSize < $length && connection_status() == 0) { AJXP_Logger::debug("dl reading {$readSize} to {$length}", $_SERVER["HTTP_RANGE"]); echo fread($file, $bufferSize); $readSize += $bufferSize; flush(); } fclose($file); return; } else { if ($gzip) { $gzippedData = $data ? gzencode($filePathOrData, 9) : gzencode(file_get_contents($filePathOrData), 9); $size = strlen($gzippedData); } HTMLWriter::generateAttachmentsHeader($localName, $size, $isFile, $gzip); /* header("Content-Type: application/force-download; name=\"".$localName."\""); header("Content-Transfer-Encoding: binary"); if($gzip){ header("Content-Encoding: gzip"); // If gzip, recompute data size! $gzippedData = ($data?gzencode($filePathOrData,9):gzencode(file_get_contents($filePathOrData), 9)); $size = strlen($gzippedData); } header("Content-Length: ".$size); if ($isFile && ($size != 0)) header("Content-Range: bytes 0-" . ($size - 1) . "/" . $size . ";"); header("Content-Disposition: attachment; filename=\"".$localName."\""); header("Expires: 0"); header("Cache-Control: no-cache, must-revalidate"); header("Pragma: no-cache"); if (preg_match('/ MSIE /',$_SERVER['HTTP_USER_AGENT'])){ header("Cache-Control: max_age=0"); header("Pragma: public"); } // IE8 is dumb if (preg_match('/ MSIE /',$_SERVER['HTTP_USER_AGENT'])) { header("Pragma: public"); header("Expires: 0"); header("Cache-Control: must-revalidate, post-check=0, pre-check=0"); header("Cache-Control: private",false); // header("Content-Type: application/octet-stream"); } // For SSL websites there is a bug with IE see article KB 323308 // therefore we must reset the Cache-Control and Pragma Header if (ConfService::getConf("USE_HTTPS")==1 && preg_match('/ MSIE /',$_SERVER['HTTP_USER_AGENT'])) { header("Cache-Control:"); header("Pragma:"); } */ if ($gzip) { print $gzippedData; return; } } } } if ($data) { print $filePathOrData; } else { if ($this->pluginConf["USE_XSENDFILE"] && $this->wrapperClassName == "fsAccessWrapper") { if (!$realfileSystem) { $filePathOrData = fsAccessWrapper::getRealFSReference($filePathOrData); } $filePathOrData = str_replace("\\", "/", $filePathOrData); header("X-Sendfile: " . SystemTextEncoding::toUTF8($filePathOrData)); header("Content-type: application/octet-stream"); header('Content-Disposition: attachment; filename="' . basename($filePathOrData) . '"'); return; } $stream = fopen("php://output", "a"); if ($realfileSystem) { AJXP_Logger::debug("realFS!", array("file" => $filePathOrData)); $fp = fopen($filePathOrData, "rb"); if ($byteOffset != -1) { fseek($fp, $byteOffset); } $sentSize = 0; $readChunk = 4096; while (!feof($fp)) { if ($byteLength != -1 && $sentSize + $readChunk >= $byteLength) { // compute last chunk and break after $readChunk = $byteLength - $sentSize; $break = true; } $data = fread($fp, $readChunk); $dataSize = strlen($data); fwrite($stream, $data, $dataSize); $sentSize += $dataSize; if (isset($break)) { break; } } fclose($fp); } else { call_user_func(array($this->wrapperClassName, "copyFileInStream"), $filePathOrData, $stream); } fflush($stream); fclose($stream); } }
/** * @inheritdoc */ public function rename($from, $to) { $fromUrl = parse_url($from); $repoId = $fromUrl["host"]; $repoObject = ConfService::getRepositoryById($repoId); $isViPR = $repoObject->getOption("IS_VIPR"); $isDir = false; if ($isViPR === true) { if (is_dir($from . "/")) { $from .= '/'; $to .= '/'; $isDir = true; } } if ($isDir === true || is_dir($from)) { AJXP_Logger::debug(__CLASS__, __FUNCTION__, "S3 Renaming dir {$from} to {$to}"); require_once "aws-v2.phar"; $fromUrl = parse_url($from); $repoId = $fromUrl["host"]; $repoObject = ConfService::getRepositoryById($repoId); if (!isset($repoObject)) { $e = new Exception("Cannot find repository with id " . $repoId); self::$lastException = $e; throw $e; } $s3Client = self::getClientForRepository($repoObject, false); $bucket = $repoObject->getOption("CONTAINER"); $basePath = $repoObject->getOption("PATH"); $fromKeyname = trim(str_replace("//", "/", $basePath . parse_url($from, PHP_URL_PATH)), '/'); $toKeyname = trim(str_replace("//", "/", $basePath . parse_url($to, PHP_URL_PATH)), '/'); if ($isViPR) { $toKeyname .= '/'; $parts = explode('/', $bucket); $bucket = $parts[0]; if (isset($parts[1])) { $fromKeyname = $parts[1] . "/" . $fromKeyname; } } // Perform a batch of CopyObject operations. $batch = array(); $failed = array(); $iterator = $s3Client->getIterator('ListObjects', array('Bucket' => $bucket, 'Prefix' => $fromKeyname . "/")); $toDelete = array(); AJXP_Logger::debug(__CLASS__, __FUNCTION__, "S3 Got iterator looking for prefix " . $fromKeyname . "/ , and toKeyName=" . $toKeyname); foreach ($iterator as $object) { $currentFrom = $object['Key']; $currentTo = $toKeyname . substr($currentFrom, strlen($fromKeyname)); if ($isViPR) { if (isset($parts[1])) { $currentTo = $parts[1] . "/" . $currentTo; } } AJXP_Logger::debug(__CLASS__, __FUNCTION__, "S3 Should move one object " . $currentFrom . " to new key :" . $currentTo); $batch[] = $s3Client->getCommand('CopyObject', array('Bucket' => $bucket, 'Key' => "{$currentTo}", 'CopySource' => "{$bucket}/" . rawurlencode($currentFrom))); $toDelete[] = $currentFrom; } AJXP_Logger::debug(__CLASS__, __FUNCTION__, "S3 Execute batch on " . count($batch) . " objects"); ConfService::getConfStorageImpl()->_loadPluginConfig("access.s3", $globalOptions); $sdkVersion = $globalOptions["SDK_VERSION"]; if ($sdkVersion === "v3") { foreach ($batch as $command) { $successful = $s3Client->execute($command); } //We must delete the "/" in $fromKeyname because we want to delete the folder $clear = \Aws\S3\BatchDelete::fromIterator($s3Client, $bucket, $s3Client->getIterator('ListObjects', array('Bucket' => $bucket, 'Prefix' => $fromKeyname))); $clear->delete(); } else { try { $successful = $s3Client->execute($batch); $clear = new \Aws\S3\Model\ClearBucket($s3Client, $bucket); $iterator->rewind(); $clear->setIterator($iterator); $clear->clear(); $failed = array(); } catch (\Guzzle\Service\Exception\CommandTransferException $e) { $successful = $e->getSuccessfulCommands(); $failed = $e->getFailedCommands(); } } if (count($failed)) { foreach ($failed as $c) { // $c is a Aws\S3\Command\S3Command AJXP_Logger::error("S3Wrapper", __FUNCTION__, "Error while copying: " . $c->getOperation()->getServiceDescription()); } self::$lastException = new Exception("Failed moving folder: " . count($failed)); return false; } return true; } else { AJXP_Logger::debug(__CLASS__, __FUNCTION__, "S3 Execute standard rename on " . $from . " to " . $to); return parent::rename($from, $to); } }