/** * get the link and return the file that match it * @param string $link the link provided by storeFile * @return string $filename the file that match the link * @throws \common_exception_Error */ public function retrieveFile($link) { if (!\tao_helpers_File::securityCheck($link)) { throw new \common_exception_Error('Unsecure file link found'); } return $this->getBaseDir() . $link; }
/** * (non-PHPdoc) * @see tao_models_classes_export_ExportHandler::export() */ public function export($formValues, $destination) { $file = null; if (isset($formValues['filename']) === true) { $instances = is_string($formValues['instances']) ? array($formValues['instances']) : $formValues['instances']; if (count($instances) > 0) { $fileName = $formValues['filename'] . '_' . time() . '.zip'; $path = tao_helpers_File::concat(array($destination, $fileName)); if (tao_helpers_File::securityCheck($path, true) === false) { throw new common_Exception('Unauthorized file name for QTI Test ZIP archive.'); } // Create a new ZIP archive to store data related to the QTI Test. $zip = new ZipArchive(); if ($zip->open($path, ZipArchive::CREATE) !== true) { throw new common_Exception("Unable to create ZIP archive for QTI Test at location '" . $path . "'."); } // Create an empty IMS Manifest as a basis. $manifest = taoQtiTest_helpers_Utils::emptyImsManifest(); foreach ($instances as $instance) { $testResource = new core_kernel_classes_Resource($instance); $testExporter = new taoQtiTest_models_classes_export_QtiTestExporter($testResource, $zip, $manifest); common_Logger::d('Export ' . $instance); $testExporter->export(); } $file = $path; $zip->close(); } else { common_Logger::w("No instance in form to export"); } } else { common_Logger::w("Missing filename for QTI Test export using Export Handler '" . __CLASS__ . "'."); } return $file; }
public static function outputFile($relPath, $filename = null) { $fullpath = self::getExportPath() . DIRECTORY_SEPARATOR . $relPath; if (tao_helpers_File::securityCheck($fullpath, true) && file_exists($fullpath)) { Context::getInstance()->getResponse()->setContentHeader(tao_helpers_File::getMimeType($fullpath)); $fileName = empty($filename) ? basename($fullpath) : $filename; header('Content-Disposition: attachment; fileName="' . $fileName . '"'); header("Content-Length: " . filesize($fullpath)); //Clean all levels of output buffering while (ob_get_level() > 0) { ob_end_clean(); } flush(); $fp = fopen($fullpath, "r"); if ($fp !== false) { while (!feof($fp)) { echo fread($fp, 65536); flush(); } fclose($fp); @unlink($fullpath); } else { common_Logger::e('Unable to open File to export' . $fullpath); } } else { common_Logger::e('Could not find File to export: ' . $fullpath); } }
/** * (non-PHPdoc) * @see tao_models_classes_export_ExportHandler::export() */ public function export($formValues, $destination) { $report = common_report_Report::createSuccess(); if (isset($formValues['filename']) === true) { $instances = is_string($formValues['instances']) ? array($formValues['instances']) : $formValues['instances']; if (count($instances) > 0) { $fileName = $formValues['filename'] . '_' . time() . '.zip'; $path = tao_helpers_File::concat(array($destination, $fileName)); if (tao_helpers_File::securityCheck($path, true) === false) { throw new common_Exception('Unauthorized file name for QTI Test ZIP archive.'); } // Create a new ZIP archive to store data related to the QTI Test. $zip = new ZipArchive(); if ($zip->open($path, ZipArchive::CREATE) !== true) { throw new common_Exception("Unable to create ZIP archive for QTI Test at location '" . $path . "'."); } // Create an empty IMS Manifest as a basis. $manifest = $this->createManifest(); foreach ($instances as $instance) { $testResource = new core_kernel_classes_Resource($instance); $testExporter = $this->createExporter($testResource, $zip, $manifest); common_Logger::d('Export ' . $instance); $subReport = $testExporter->export(); if ($report->getType() !== common_report_Report::TYPE_ERROR && ($subReport->containsError() || $subReport->getType() === common_report_Report::TYPE_ERROR)) { $report->setType(common_report_Report::TYPE_ERROR); $report->setMessage(__('Not all test could be export', $testResource->getLabel())); } $report->add($subReport); } $report->setData($path); $zip->close(); } else { common_Logger::w("No instance in form to export"); } } else { common_Logger::w("Missing filename for QTI Test export using Export Handler '" . __CLASS__ . "'."); } return $report; }
/** * export a compiled delivery into an archive * * @param core_kernel_classes_Resource $compiledDelivery * @throws Exception * @return string */ public static function exportCompiledDelivery(core_kernel_classes_Resource $compiledDelivery) { $fileName = tao_helpers_Display::textCleaner($compiledDelivery->getLabel()) . '.zip'; $path = tao_helpers_File::concat(array(tao_helpers_Export::getExportPath(), $fileName)); if (!tao_helpers_File::securityCheck($path, true)) { throw new Exception('Unauthorized file name'); } $zipArchive = new ZipArchive(); if ($zipArchive->open($path, ZipArchive::CREATE) !== true) { throw new Exception('Unable to create archive at ' . $path); } $taoDeliveryVersion = common_ext_ExtensionsManager::singleton()->getInstalledVersion('taoDelivery'); $data = array('dir' => array(), 'label' => $compiledDelivery->getLabel(), 'version' => $taoDeliveryVersion); $directories = $compiledDelivery->getPropertyValues(new core_kernel_classes_Property(PROPERTY_COMPILEDDELIVERY_DIRECTORY)); foreach ($directories as $id) { $directory = tao_models_classes_service_FileStorage::singleton()->getDirectoryById($id); tao_helpers_File::addFilesToZip($zipArchive, $directory->getPath(), $directory->getRelativePath()); $data['dir'][$id] = $directory->getRelativePath(); } $runtime = $compiledDelivery->getUniquePropertyValue(new core_kernel_classes_Property(PROPERTY_COMPILEDDELIVERY_RUNTIME)); $serviceCall = tao_models_classes_service_ServiceCall::fromResource($runtime); $data['runtime'] = base64_encode($serviceCall->serializeToString()); $rdfExporter = new tao_models_classes_export_RdfExporter(); $rdfdata = $rdfExporter->getRdfString(array($compiledDelivery)); if (!$zipArchive->addFromString('delivery.rdf', $rdfdata)) { throw common_Exception('Unable to add metadata to exported delivery assembly'); } $data['meta'] = 'delivery.rdf'; $content = json_encode($data); //'<?php return '.common_Utils::toPHPVariableString($data).";"; if (!$zipArchive->addFromString(self::MANIFEST_FILE, $content)) { $zipArchive->close(); unlink($path); throw common_Exception('Unable to add manifest to exported delivery assembly'); } $zipArchive->close(); return $path; }
/** * Download custom styles */ public function download() { if (!$this->hasRequestParameter('uri')) { throw new common_exception_MissingParameter('uri', __METHOD__); } if (!$this->hasRequestParameter('stylesheetUri')) { throw new common_exception_MissingParameter('stylesheetUri', __METHOD__); } if (!$this->hasRequestParameter('lang')) { throw new common_exception_MissingParameter('lang', __METHOD__); } $item = new \core_kernel_classes_Resource($this->getRequestParameter('uri')); $lang = $this->getRequestParameter('lang'); $styleSheet = $this->getRequestParameter('stylesheetUri'); if (!\tao_helpers_File::securityCheck($styleSheet, true)) { throw new \common_exception_Error('invalid stylesheet path "' . $styleSheet . '"'); } header('Set-Cookie: fileDownload=true'); setcookie('fileDownload', 'true', 0, '/'); header('Content-type: application/octet-stream'); header(sprintf('Content-Disposition: attachment; filename=%s', basename($styleSheet))); echo CssHelper::downloadCssFile($item, $lang, $styleSheet); }
/** * Get XML content. * * @access protected * @author Aleh Hutnikau, <*****@*****.**> * @param boolean $refresh load content again. * @return string */ protected function getContent($refresh = false) { if ($this->content === null || $refresh) { try { switch ($this->sourceType) { case self::SOURCE_FILE: //check file if (!file_exists($this->source)) { throw new Exception("File {$this->source} not found."); } if (!is_readable($this->source)) { throw new Exception("Unable to read file {$this->source}."); } if (!preg_match("/\\.{$this->fileExtension}\$/", basename($this->source))) { throw new Exception("Wrong file extension in " . basename($this->source) . ", {$this->fileExtension} extension is expected"); } if (!tao_helpers_File::securityCheck($this->source)) { throw new Exception("{$this->source} seems to contain some security issues"); } $this->content = file_get_contents($this->source); break; case self::SOURCE_URL: //only same domain if (!preg_match("/^" . preg_quote(BASE_URL, '/') . "/", $this->source)) { throw new Exception("The given uri must be in the domain {$_SERVER['HTTP_HOST']}"); } $this->content = tao_helpers_Request::load($this->source, true); break; case self::SOURCE_STRING: $this->content = $this->source; break; case self::SOURCE_FLYFILE: if (!$this->source->exists()) { throw new common_Exception('Source file does not exists ("' . $this->source->getPath() . '").'); } if (!($this->content = $this->source->read())) { throw new common_Exception('Unable to read file ("' . $this->source->getPath() . '").'); } break; } } catch (Exception $e) { $this->addError($e); } } return $this->content; }
/** * Get, check and move the file uploaded (described in the posetedFile parameter) * * @param array $postedFile * @param string $folder * @return array $data */ protected function uploadFile($postedFile, $folder) { $returnValue = array(); if (isset($postedFile['tmp_name']) && isset($postedFile['name'])) { $tempFile = $postedFile['tmp_name']; $targetPath = tao_helpers_File::concat(array($this->rootFolder, $folder)); if (tao_helpers_File::securityCheck($targetPath)) { if (!file_exists($targetPath)) { mkdir($targetPath); } $targetFile = tao_helpers_File::concat(array($targetPath, uniqid() . '_' . $postedFile['name'])); if (move_uploaded_file($tempFile, $targetFile)) { $returnValue['uploaded'] = true; $data = $postedFile; $data['type'] = tao_helpers_File::getMimeType($targetFile); $data['uploaded_file'] = $targetFile; $returnValue['name'] = $postedFile['name']; $returnValue['uploaded_file'] = $targetFile; $returnValue['data'] = serialize($data); } } } return $returnValue; }
/** * Verify paths and encode the file * * @param string $basedir * @param string $source * @throws \tao_models_classes_FileNotFoundException * @throws \common_exception_Error * @return string */ protected static function secureEncode($basedir, $source) { $components = parse_url($source); if (!isset($components['scheme'])) { // relative path if (\tao_helpers_File::securityCheck($source, false)) { if (file_exists($basedir . $source)) { return 'data:' . FsUtils::getMimeType($basedir . $source) . ';' . 'base64,' . base64_encode(file_get_contents($basedir . $source)); } else { throw new \tao_models_classes_FileNotFoundException($source); } } else { throw new \common_exception_Error('Invalid source path "' . $source . '"'); } } else { // url, just return it as is return $source; } }
/** * Short description of method validate * * @access public * @author Bertrand Chevrier, <*****@*****.**> * @param string schema * @return boolean */ public function validate($schema = '') { //You know sometimes you think you have enough time, but it is not always true ... //(timeout in hudson with the generis-hard test suite) helpers_TimeOutHelper::setTimeOutLimit(helpers_TimeOutHelper::MEDIUM); $forced = $this->valid; $this->valid = true; try { switch ($this->sourceType) { case self::SOURCE_FILE: //check file if (!file_exists($this->source)) { throw new Exception("File {$this->source} not found."); } if (!is_readable($this->source)) { throw new Exception("Unable to read file {$this->source}."); } if (!preg_match("/\\.{$this->fileExtension}\$/", basename($this->source))) { throw new Exception("Wrong file extension in " . basename($this->source) . ", {$this->fileExtension} extension is expected"); } if (!tao_helpers_File::securityCheck($this->source)) { throw new Exception("{$this->source} seems to contain some security issues"); } break; case self::SOURCE_URL: //only same domain if (!preg_match("/^" . preg_quote(BASE_URL, '/') . "/", $this->source)) { throw new Exception("The given uri must be in the domain {$_SERVER['HTTP_HOST']}"); } break; } } catch (Exception $e) { if ($forced) { throw $e; } else { $this->addError($e); } } if ($this->valid && !$forced) { //valida can be true if forceValidation has been called $this->valid = false; try { libxml_use_internal_errors(true); $dom = new DomDocument(); $loadResult = false; switch ($this->sourceType) { case self::SOURCE_FILE: $loadResult = $dom->load($this->source); break; case self::SOURCE_URL: $xmlContent = tao_helpers_Request::load($this->source, true); $loadResult = $dom->loadXML($xmlContent); break; case self::SOURCE_STRING: $loadResult = $dom->loadXML($this->source); break; } if ($loadResult) { if (!empty($schema)) { $this->valid = $dom->schemaValidate($schema); } else { $this->valid = true; //only well-formed } } if (!$this->valid) { $this->addErrors(libxml_get_errors()); } libxml_clear_errors(); } catch (DOMException $de) { $this->addError($de); } } $returnValue = $this->valid; helpers_TimeOutHelper::reset(); return (bool) $returnValue; }
die; } $config = (include $configPath); $compiledPath = $config['options']['path']; $secretPassphrase = $config['options']['secret']; $ttl = $config['options']['ttl']; $correctToken = md5($timestamp . $subPath . $secretPassphrase); if (time() - $timestamp > $ttl || $token != $correctToken) { header('HTTP/1.0 403 Forbidden'); die; } $path = array(); foreach (explode('/', $subPath . $file) as $ele) { $path[] = rawurldecode($ele); } $filename = $compiledPath . implode(DIRECTORY_SEPARATOR, $path); if (strpos($filename, '?')) { // A query string is provided with the file to be retrieved - clean up! $parts = explode('?', $filename); $filename = $parts[0]; } if (tao_helpers_File::securityCheck($filename, true)) { header('Content-Type: ' . tao_helpers_File::getMimeType($filename, true)); $fp = fopen($filename, 'rb'); if ($fp === false) { header("HTTP/1.0 404 Not Found"); } else { fpassthru($fp); } } exit;
/** * Load an item external media * It prevents to get it direclty in the data folder that access is denied * @requiresRight uri READ * @deprecated */ public function getMediaResource() { if ($this->hasRequestParameter('path')) { $item = null; if ($this->hasRequestParameter('uri') && $this->hasRequestParameter('classUri')) { $item = $this->getCurrentInstance(); } else { if ($this->hasSessionAttribute('uri') && $this->hasSessionAttribute('classUri')) { $classUri = tao_helpers_Uri::decode($this->getSessionAttribute('classUri')); if ($this->getClassService()->isItemClass(new core_kernel_classes_Class($classUri))) { $item = new core_kernel_classes_Resource(tao_helpers_Uri::decode($this->getSessionAttribute('uri'))); } } } if (!is_null($item)) { $path = urldecode($this->getRequestParameter('path')); if (!tao_helpers_File::securityCheck($path)) { throw new Exception('Unauthorized path ' . $path); } if (preg_match('/(.)+\\/filemanager\\/views\\/data\\//i', $path)) { // check if the file is linked to the file manager $resource = preg_replace('/(.)+\\/filemanager\\/views\\/data\\//i', ROOT_PATH . '/filemanager/views/data/', $path); } else { // look in the item's dedicated folder. it should be a resource // that is local to the item, not it the file manager // $folder is the item's dedicated folder path, $path the path to the resource, relative to $folder $folder = $this->getClassService()->getItemFolder($item); $resource = tao_helpers_File::concat(array($folder, $path)); } if (file_exists($resource)) { $mimeType = tao_helpers_File::getMimeType($resource); //allow only images, video, flash (and css?) if (preg_match("/^(image|video|audio|application\\/x-shockwave-flash)/", $mimeType)) { header("Content-Type: {$mimeType}; charset utf-8"); print trim(file_get_contents($resource)); } } } } }
/** * Add content to file * * @see \oat\tao\model\media\MediaManagement::add * @param string $source * @param string $fileName * @param string $parent * @return array * @throws \common_Exception * @throws \tao_models_classes_FileNotFoundException */ public function add($source, $fileName, $parent) { if (!\tao_helpers_File::securityCheck($fileName, true)) { throw new \common_Exception('Unsecured filename "' . $fileName . '"'); } if (($resource = fopen($source, 'r')) === false) { throw new \common_Exception('Unable to read content of file ("' . $source . '")'); } $file = $this->getItemDirectory()->getDirectory($parent)->getFile($fileName); $writeSuccess = $file->put($resource); fclose($resource); if (!$writeSuccess) { throw new \common_Exception('Unable to write file ("' . $fileName . '")'); } return $this->getInfoFromFile($file); }
/** * (non-PHPdoc) * @see \oat\tao\model\media\MediaManagement::add */ public function add($source, $fileName, $parent) { if (!\tao_helpers_File::securityCheck($fileName, true)) { throw new \common_Exception('Unsecured filename "' . $fileName . '"'); } $sysPath = $this->getSysPath($parent . $fileName); if (!tao_helpers_File::copy($source, $sysPath)) { throw new \common_exception_Error('Unable to move file ' . $source); } $fileData = $this->getFileInfo('/' . ltrim($parent, '/') . $fileName, array()); return $fileData; }
/** * delete the selected file or folder * * @author CRP Henri Tudor - TAO Team - {@link http://www.tao.lu} */ public function delete() { $data = array('deleted' => false); if ($this->hasRequestParameter('file')) { $file = urldecode($this->getRequestParameter('file')); if (tao_helpers_File::securityCheck($file, true)) { $data['deleted'] = unlink(filemanager_helpers_FileUtils::cleanConcat(array(filemanager_helpers_FileUtils::getBasePath(), $file))); } } if ($this->hasRequestParameter("folder")) { $folder = urldecode($this->getRequestParameter('folder')); if (tao_helpers_File::securityCheck($folder, true)) { if (filemanager_helpers_FileUtils::deleteFolder(filemanager_helpers_FileUtils::cleanConcat(array(filemanager_helpers_FileUtils::getBasePath(), $folder)), true)) { $data['deleted'] = true; } } } echo json_encode($data); }
/** * @param $parentLink * @return string * @throws common_exception_Error */ private function getSysPath($parentLink) { $baseDir = taoItems_models_classes_ItemsService::singleton()->getItemFolder($this->item, $this->lang); $sysPath = $baseDir . ltrim($parentLink, '/'); if (!tao_helpers_File::securityCheck($sysPath)) { throw new common_exception_Error(__('Your path contains error')); } return $sysPath; }
/** * Sends file content to the client(browser or video/audio player in the browser), it serves images, video/audio files and any other type of file.<br /> * If the client asks for partial contents, then partial contents are served, if not, the whole file is send.<br /> * Works well with big files, without eating up memory. * @author "Martin for OAT <*****@*****.**>" * @param string $filename the file name * @param boolean $contenttype whether to add content type header or not * @param boolean $svgzSupport whether to add content encoding header or not * @throws common_exception_Error */ public static function returnFile($filename, $contenttype = true, $svgzSupport = false) { if (tao_helpers_File::securityCheck($filename, true)) { if (file_exists($filename)) { $mimeType = tao_helpers_File::getMimeType($filename, true); if ($contenttype) { header('Content-Type: ' . $mimeType); } $fp = fopen($filename, 'rb'); if ($fp === false) { header("HTTP/1.0 404 Not Found"); } else { $pathinfo = pathinfo($filename); if (isset($pathinfo['extension']) && $pathinfo['extension'] === 'svgz' && !$svgzSupport) { header('Content-Encoding: gzip'); } // session must be closed because, for example, video files might take a while to be sent to the client // and we need the client to be able to make other calls to the server during that time session_write_close(); $http416RequestRangeNotSatisfiable = 'HTTP/1.1 416 Requested Range Not Satisfiable'; $http206PartialContent = 'HTTP/1.1 206 Partial Content'; $http200OK = 'HTTP/1.1 200 OK'; $filesize = filesize($filename); $offset = 0; $length = $filesize; $useFpassthru = false; $partialContent = false; header('Accept-Ranges: bytes'); if (isset($_SERVER['HTTP_RANGE'])) { $partialContent = true; preg_match('/bytes=(\\d+)-(\\d+)?/', $_SERVER['HTTP_RANGE'], $matches); $offset = intval($matches[1]); if (!isset($matches[2])) { // no end position is given, so we serve the file from the start position to the end $useFpassthru = true; } else { $length = intval($matches[2]) - $offset; } } fseek($fp, $offset); if ($partialContent) { if ($offset < 0 || $offset > $filesize) { header($http416RequestRangeNotSatisfiable); } else { if ($useFpassthru) { // only a starting position is given header($http206PartialContent); header("Content-Length: " . ($filesize - $offset)); header('Content-Range: bytes ' . $offset . '-' . ($filesize - 1) . '/' . $filesize); if (ob_get_level() > 0) { ob_end_flush(); } fpassthru($fp); } else { // we are given a starting position and how many bytes the client asks for $endPosition = $offset + $length; if ($endPosition > $filesize) { header($http416RequestRangeNotSatisfiable); } else { header($http206PartialContent); header("Content-Length: " . $length); header('Content-Range: bytes ' . $offset . '-' . ($offset + $length - 1) . '/' . $filesize); // send 500KB per cycle $bytesPerCycle = 1024 * 1024 * 0.5; $currentPosition = $offset; if (ob_get_level() > 0) { ob_end_flush(); } // because the client might ask for the whole file, we split the serving into little pieces // this is also good in case someone with bad intentions tries to get the whole file many times // and eat up the server memory, we are not loading the whole file into the memory. while (!feof($fp)) { if ($currentPosition + $bytesPerCycle <= $endPosition) { $data = fread($fp, $bytesPerCycle); $currentPosition = $currentPosition + $bytesPerCycle; echo $data; } else { $data = fread($fp, $endPosition - $currentPosition); echo $data; } } } } } } else { // client does not want partial contents so we just serve the whole file header($http200OK); header("Content-Length: " . $filesize); if (ob_get_level() > 0) { ob_end_flush(); } fpassthru($fp); } fclose($fp); } } else { if (class_exists('common_Logger')) { common_Logger::w('File ' . $filename . ' not found'); } header("HTTP/1.0 404 Not Found"); } } else { throw new common_exception_Error('Security exception for path ' . $filename); } }
private function renderResource($item, $path) { $identifier = ''; $subPath = $path; if (strpos($path, '://') !== false) { $identifier = substr($path, 0, strpos($path, '://')); $subPath = substr($path, strpos($path, '://') + 3); } //@todo : allow preview in a language other than the one in the session $lang = common_session_SessionManager::getSession()->getDataLanguage(); $folder = taoItems_models_classes_ItemsService::singleton()->getItemFolder($item, $lang); if (tao_helpers_File::securityCheck($path, true)) { if ($identifier === 'taomgr') { $fileManager = FileManager::getFileManagementModel(); $filename = $fileManager->retrieveFile($subPath); } else { $filename = $folder . $path; } tao_helpers_Http::returnFile($filename); } else { throw new common_exception_Error('invalid item preview file path'); } }