public function switchAction($action, $httpVars, $filesVars)
 {
     $repository = ConfService::getRepository();
     if (!$repository->detectStreamWrapper(true)) {
         return false;
     }
     if (!isset($this->pluginConf)) {
         $this->pluginConf = array("GENERATE_THUMBNAIL" => false);
     }
     $selection = new UserSelection($repository, $httpVars);
     $destStreamURL = $selection->currentBaseUrl();
     if ($action == "preview_data_proxy") {
         $file = $selection->getUniqueFile();
         if (!file_exists($destStreamURL . $file) || !is_readable($destStreamURL . $file)) {
             header("Content-Type: " . AJXP_Utils::getImageMimeType(basename($file)) . "; name=\"" . basename($file) . "\"");
             header("Content-Length: 0");
             return;
         }
         $this->logInfo('Preview', 'Preview content of ' . $file, array("files" => $selection->getUniqueFile()));
         if (isset($httpVars["get_thumb"]) && $httpVars["get_thumb"] == "true" && $this->getFilteredOption("GENERATE_THUMBNAIL", $repository->getId())) {
             $dimension = 200;
             if (isset($httpVars["dimension"]) && is_numeric($httpVars["dimension"])) {
                 $dimension = $httpVars["dimension"];
             }
             $this->currentDimension = $dimension;
             $cacheItem = AJXP_Cache::getItem("diaporama_" . $dimension, $destStreamURL . $file, array($this, "generateThumbnail"));
             $data = $cacheItem->getData();
             $cId = $cacheItem->getId();
             header("Content-Type: " . AJXP_Utils::getImageMimeType(basename($cId)) . "; name=\"" . basename($cId) . "\"");
             header("Content-Length: " . strlen($data));
             header('Cache-Control: public');
             header("Pragma:");
             header("Last-Modified: " . gmdate("D, d M Y H:i:s", time() - 10000) . " GMT");
             header("Expires: " . gmdate("D, d M Y H:i:s", time() + 5 * 24 * 3600) . " GMT");
             print $data;
         } else {
             //$filesize = filesize($destStreamURL.$file);
             $node = new AJXP_Node($destStreamURL . $file);
             $fp = fopen($destStreamURL . $file, "r");
             $stat = fstat($fp);
             $filesize = $stat["size"];
             header("Content-Type: " . AJXP_Utils::getImageMimeType(basename($file)) . "; name=\"" . basename($file) . "\"");
             header("Content-Length: " . $filesize);
             header('Cache-Control: public');
             header("Pragma:");
             header("Last-Modified: " . gmdate("D, d M Y H:i:s", time() - 10000) . " GMT");
             header("Expires: " . gmdate("D, d M Y H:i:s", time() + 5 * 24 * 3600) . " GMT");
             $stream = fopen("php://output", "a");
             AJXP_MetaStreamWrapper::copyFileInStream($destStreamURL . $file, $stream);
             fflush($stream);
             fclose($stream);
             AJXP_Controller::applyHook("node.read", array($node));
         }
     }
 }
 public function switchAction($action, $httpVars, $filesVars)
 {
     $repository = ConfService::getRepositoryById($httpVars["repository_id"]);
     if (!$repository->detectStreamWrapper(true)) {
         return false;
     }
     if (AuthService::usersEnabled()) {
         $loggedUser = AuthService::getLoggedUser();
         if ($loggedUser === null && ConfService::getCoreConf("ALLOW_GUEST_BROWSING", "auth")) {
             AuthService::logUser("guest", null);
             $loggedUser = AuthService::getLoggedUser();
         }
         if (!$loggedUser->canSwitchTo($repository->getId())) {
             echo "You do not have permissions to access this resource";
             return false;
         }
     }
     $selection = new UserSelection($repository, $httpVars);
     if ($action == "open_file") {
         $selectedNode = $selection->getUniqueNode();
         $selectedNodeUrl = $selectedNode->getUrl();
         if (!file_exists($selectedNodeUrl) || !is_readable($selectedNodeUrl)) {
             echo "File does not exist";
             return false;
         }
         $filesize = filesize($selectedNodeUrl);
         $fp = fopen($selectedNodeUrl, "rb");
         $fileMime = "application/octet-stream";
         //Get mimetype with fileinfo PECL extension
         if (class_exists("finfo")) {
             $finfo = new finfo(FILEINFO_MIME);
             $fileMime = $finfo->buffer(fread($fp, 2000));
         }
         //Get mimetype with (deprecated) mime_content_type
         if (strpos($fileMime, "application/octet-stream") === 0 && function_exists("mime_content_type")) {
             $fileMime = @mime_content_type($fp);
         }
         //Guess mimetype based on file extension
         if (strpos($fileMime, "application/octet-stream") === 0) {
             $fileExt = substr(strrchr(basename($selectedNodeUrl), '.'), 1);
             if (empty($fileExt)) {
                 $fileMime = "application/octet-stream";
             } else {
                 $regex = "/^([\\w\\+\\-\\.\\/]+)\\s+(\\w+\\s)*({$fileExt}\\s)/i";
                 $lines = file($this->getBaseDir() . "/resources/other/mime.types");
                 foreach ($lines as $line) {
                     if (substr($line, 0, 1) == '#') {
                         continue;
                     }
                     // skip comments
                     $line = rtrim($line) . " ";
                     if (!preg_match($regex, $line, $matches)) {
                         continue;
                     }
                     // no match to the extension
                     $fileMime = $matches[1];
                 }
             }
         }
         fclose($fp);
         // If still no mimetype, give up and serve application/octet-stream
         if (empty($fileMime)) {
             $fileMime = "application/octet-stream";
         }
         //Send headers
         HTMLWriter::generateInlineHeaders(basename($selectedNodeUrl), $filesize, $fileMime);
         $stream = fopen("php://output", "a");
         AJXP_MetaStreamWrapper::copyFileInStream($selectedNodeUrl, $stream);
         fflush($stream);
         fclose($stream);
         AJXP_Controller::applyHook("node.read", array($selectedNode));
         $this->logInfo('Download', 'Read content of ' . $selectedNodeUrl, array("files" => $selectedNodeUrl));
     }
 }
 /**
  * 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);
     AJXP_MetaStreamWrapper::copyFileInStream($url, $stream);
     /*
     $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());
     }
 }
示例#4
0
 public function readFile($filePathOrData, $headerType = "plain", $localName = "", $data = false, $gzip = null, $realfileSystem = false, $byteOffset = -1, $byteLength = -1)
 {
     if (!$data && !$gzip && !file_exists($filePathOrData)) {
         throw new Exception("File {$filePathOrData} not found!");
     }
     if ($gzip === null) {
         $gzip = ConfService::getCoreConf("GZIP_COMPRESSION");
     }
     if (!$realfileSystem && AJXP_MetaStreamWrapper::actualRepositoryWrapperClass($this->repository->getId()) == "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 = filesize($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 ($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') && AJXP_MetaStreamWrapper::actualRepositoryWrapperClass($this->repository->getId()) == "fsAccessWrapper") {
                         $fInfo = new fInfo(FILEINFO_MIME);
                         $realfile = AJXP_MetaStreamWrapper::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');
                 if (!is_resource($file)) {
                     throw new Exception("Failed opening file " . $filePathOrData);
                 }
                 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) && AJXP_MetaStreamWrapper::actualRepositoryWrapperClass($this->repository->getId()) == "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()) && AJXP_MetaStreamWrapper::actualRepositoryWrapperClass($this->repository->getId()) == "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 (!is_resource($fp)) {
                 throw new Exception("Failed opening file " . $filePathOrData);
             }
             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 {
             AJXP_MetaStreamWrapper::copyFileInStream($filePathOrData, $stream);
         }
         fflush($stream);
         fclose($stream);
     }
 }
 public function switchAction($action, $httpVars, $filesVars)
 {
     $repository = ConfService::getRepository();
     if (!$repository->detectStreamWrapper(true)) {
         return false;
     }
     $selection = new UserSelection($repository, $httpVars);
     $node = $selection->getUniqueNode();
     if ($action == "read_video_data") {
         if (!file_exists($node->getUrl()) || !is_readable($node->getUrl())) {
             throw new Exception("Cannot find file!");
         }
         $this->logDebug("Reading video");
         session_write_close();
         $filesize = filesize($node->getUrl());
         $filename = $node->getUrl();
         $basename = AJXP_Utils::safeBasename($filename);
         //$fp = fopen($destStreamURL.$file, "r");
         if (preg_match("/\\.ogv\$/", $basename)) {
             header("Content-Type: video/ogg; name=\"" . $basename . "\"");
         } else {
             if (preg_match("/\\.mp4\$/", $basename)) {
                 header("Content-Type: video/mp4; name=\"" . $basename . "\"");
             } else {
                 if (preg_match("/\\.m4v\$/", $basename)) {
                     header("Content-Type: video/x-m4v; name=\"" . $basename . "\"");
                 } else {
                     if (preg_match("/\\.webm\$/", $basename)) {
                         header("Content-Type: video/webm; name=\"" . $basename . "\"");
                     }
                 }
             }
         }
         if (isset($_SERVER['HTTP_RANGE']) && $filesize != 0) {
             $this->logDebug("Http range", array($_SERVER['HTTP_RANGE']));
             // 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]);
             if ($offset == 0) {
                 $this->logInfo('Preview', 'Streaming content of ' . $filename, array("files" => $filename));
             }
             $length = floatval($offsets[1]) - $offset + 1;
             if (!$length) {
                 $length = $filesize - $offset;
             }
             if ($length + $offset > $filesize || $length < 0) {
                 $length = $filesize - $offset;
             }
             header('HTTP/1.1 206 Partial Content');
             header('Content-Range: bytes ' . $offset . '-' . ($offset + $length - 1) . '/' . $filesize);
             header('Accept-Ranges:bytes');
             header("Content-Length: " . $length);
             $file = fopen($filename, 'rb');
             if (!is_resource($file)) {
                 throw new Exception("Cannot open file {$file}!");
             }
             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;
             while (!feof($file) && $readSize < $length && connection_status() == 0) {
                 if ($length < 2048) {
                     echo fread($file, $length);
                 } else {
                     echo fread($file, 2048);
                 }
                 $readSize += 2048.0;
                 flush();
             }
             fclose($file);
         } else {
             $this->logInfo('Preview', 'Streaming content of ' . $filename, array("files" => $filename));
             header("Content-Length: " . $filesize);
             header("Content-Range: bytes 0-" . ($filesize - 1) . "/" . $filesize . ";");
             header('Cache-Control: public');
             $stream = fopen("php://output", "a");
             AJXP_MetaStreamWrapper::copyFileInStream($node->getUrl(), $stream);
             fflush($stream);
             fclose($stream);
         }
         AJXP_Controller::applyHook("node.read", array($node));
     } else {
         if ($action == "get_sess_id") {
             HTMLWriter::charsetHeader("text/plain");
             print session_id();
         }
     }
 }
 public function switchAction($action, $httpVars, $postProcessData)
 {
     $repository = ConfService::getRepository();
     if (!$repository->detectStreamWrapper(false)) {
         return false;
     }
     if ($action == "audio_proxy") {
         $selection = new UserSelection($repository, $httpVars);
         $destStreamURL = $selection->currentBaseUrl();
         $node = new AJXP_Node($destStreamURL . "/" . $selection->getUniqueFile());
         // Backward compat
         // May be a backward compatibility problem, try to base64decode the filepath
         if (!file_exists($node->getUrl()) && strpos($httpVars["file"], "base64encoded:") === false) {
             $file = AJXP_Utils::decodeSecureMagic(base64_decode($httpVars["file"]));
             if (!file_exists($destStreamURL . $file)) {
                 throw new Exception("Cannot find file!");
             } else {
                 $node = new AJXP_Node($destStreamURL . $file);
             }
         }
         if (!is_readable($node->getUrl())) {
             throw new Exception("Cannot find file!");
         }
         $fileUrl = $node->getUrl();
         $localName = basename($fileUrl);
         $cType = "audio/" . array_pop(explode(".", $localName));
         $size = filesize($node->getUrl());
         header("Content-Type: " . $cType . "; name=\"" . $localName . "\"");
         header("Content-Length: " . $size);
         $stream = fopen("php://output", "a");
         AJXP_MetaStreamWrapper::copyFileInStream($fileUrl, $stream);
         fflush($stream);
         fclose($stream);
         AJXP_Controller::applyHook("node.read", array($node));
         $this->logInfo('Preview', 'Read content of ' . $node->getUrl(), array("files" => $node->getUrl()));
         //exit(1);
     } else {
         if ($action == "ls") {
             if (!isset($httpVars["playlist"])) {
                 // This should not happen anyway, because of the applyCondition.
                 AJXP_Controller::passProcessDataThrough($postProcessData);
                 return false;
             }
             // We transform the XML into XSPF
             $xmlString = $postProcessData["ob_output"];
             $xmlDoc = new DOMDocument();
             $xmlDoc->loadXML($xmlString);
             $xElement = $xmlDoc->documentElement;
             header("Content-Type:application/xspf+xml;charset=UTF-8");
             print '<?xml version="1.0" encoding="UTF-8"?>';
             print '<playlist version="1" xmlns="http://xspf.org/ns/0/">';
             print "<trackList>";
             foreach ($xElement->childNodes as $child) {
                 $isFile = $child->getAttribute("is_file") == "true";
                 $label = $child->getAttribute("text");
                 $ar = explode(".", $label);
                 $ext = strtolower(end($ar));
                 if (!$isFile || $ext != "mp3") {
                     continue;
                 }
                 print "<track><location>" . AJXP_SERVER_ACCESS . "?secure_token=" . AuthService::getSecureToken() . "&get_action=audio_proxy&file=" . base64_encode($child->getAttribute("filename")) . "</location><title>" . $label . "</title></track>";
             }
             print "</trackList>";
             AJXP_XMLWriter::close("playlist");
         }
     }
 }