From 37cb8f5e089641be74990a68a67a3fe960a5462b Mon Sep 17 00:00:00 2001 From: Megan Watson Date: Tue, 9 Sep 2008 08:45:13 +0000 Subject: [PATCH] KTS-3661 "Error on downloading via SSL in IE" Fixed. Created a new KTUtil function to generate the correct headers for downloading files. --- lib/documentmanagement/PhysicalDocumentManager.inc | 81 ++++++++++++++++++++++++++++++++------------------------------------------------- lib/foldermanagement/compressionArchiveUtil.inc.php | 610 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ lib/storage/ondiskhashedstoragemanager.inc.php | 64 +++++++++++++++++++++++++--------------------------------------- lib/storage/ondiskpathstoragemanager.inc.php | 40 ++++++++++++---------------------------- lib/util/ktutil.inc | 30 ++++++++++++++++++++++++++++++ plugins/ktstandard/PDFGeneratorAction.php | 64 ++++++++++++++++++++++++---------------------------------------- 6 files changed, 427 insertions(+), 462 deletions(-) diff --git a/lib/documentmanagement/PhysicalDocumentManager.inc b/lib/documentmanagement/PhysicalDocumentManager.inc index eee3c15..1c6499e 100644 --- a/lib/documentmanagement/PhysicalDocumentManager.inc +++ b/lib/documentmanagement/PhysicalDocumentManager.inc @@ -9,31 +9,31 @@ * Document Management Made Simple * Copyright (C) 2008 KnowledgeTree Inc. * Portions copyright The Jam Warehouse Software (Pty) Limited - * + * * This program is free software; you can redistribute it and/or modify it under * the terms of the GNU General Public License version 3 as published by the * Free Software Foundation. - * + * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more * details. - * + * * You should have received a copy of the GNU General Public License * along with this program. If not, see . - * - * You can contact KnowledgeTree Inc., PO Box 7775 #87847, San Francisco, + * + * You can contact KnowledgeTree Inc., PO Box 7775 #87847, San Francisco, * California 94120-7775, or email info@knowledgetree.com. - * + * * The interactive user interfaces in modified source and object code versions * of this program must display Appropriate Legal Notices, as required under * Section 5 of the GNU General Public License version 3. - * + * * In accordance with Section 7(b) of the GNU General Public License version 3, * these Appropriate Legal Notices must retain the display of the "Powered by - * KnowledgeTree" logo and retain the original copyright notice. If the display of the + * KnowledgeTree" logo and retain the original copyright notice. If the display of the * logo is not reasonably feasible for technical reasons, the Appropriate Legal Notices - * must display the words "Powered by KnowledgeTree" and retain the original + * must display the words "Powered by KnowledgeTree" and retain the original * copyright notice. * Contributor( s): ______________________________________ */ @@ -56,25 +56,17 @@ class PhysicalDocumentManager { * @todo investigate possible problem in MSIE 5.5 concerning Content-Disposition header */ function downloadPhysicalDocument($iDocumentID) { - //get the document - $oDocument = & Document::get($iDocumentID); - //get the path to the document on the server - $sDocumentFileSystemPath = $oDocument->getPath(); - if (file_exists($sDocumentFileSystemPath)) { - //set the correct headers - header("Content-Type: " . - KTMime::getMimeTypeName($oDocument->getMimeTypeID())); - header("Content-Length: ". $oDocument->getFileSize()); - header("Content-Disposition: attachment; filename=\"" . $oDocument->getFileName() . "\""); - header("Expires: Mon, 26 Jul 1997 05:00:00 GMT"); - header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT"); - header("Cache-Control: must-revalidate"); - header("Content-Location: ".$oDocument->getFileName()); + //get the document + $oDocument = & Document::get($iDocumentID); + //get the path to the document on the server + $sDocumentFileSystemPath = $oDocument->getPath(); + + $mimeType = KTMime::getMimeTypeName($oDocument->getMimeTypeID()); + $fileSize = $oDocument->getFileSize(); + $fileName = $oDocument->getFileName(); + + return KTUtil::download($sDocumentFileSystemPath, $mimeType, $fileSize, $fileName); - readfile($sDocumentFileSystemPath); - } else { - return false; - } } /** @@ -85,26 +77,17 @@ class PhysicalDocumentManager { * @return int number of bytes read from file on success or false otherwise; */ function downloadVersionedPhysicalDocument($iDocumentID, $sVersion) { - //get the document - $oDocument = & Document::get($iDocumentID); - //get the path to the document on the server - $sDocumentFileSystemPath = $oDocument->getPath() . "-$sVersion"; - if (file_exists($sDocumentFileSystemPath)) { - //set the correct headers - header("Content-Type: " . - KTMime::getMimeTypeName($oDocument->getMimeTypeID())); - header("Content-Length: ". filesize($sDocumentFileSystemPath)); - // prefix the filename presented to the browser to preserve the document extension - header('Content-Disposition: attachment; filename="' . "$sVersion-" . $oDocument->getFileName() . '"'); - header("Expires: Mon, 26 Jul 1997 05:00:00 GMT"); - header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT"); - header("Cache-Control: must-revalidate"); - header("Content-Location: ".$oDocument->getFileName()); - readfile($sDocumentFileSystemPath); - } else { - return false; - } - } + //get the document + $oDocument = & Document::get($iDocumentID); + //get the path to the document on the server + $sDocumentFileSystemPath = $oDocument->getPath() . "-$sVersion"; + + $mimeType = KTMime::getMimeTypeName($oDocument->getMimeTypeID()); + $fileSize = $oDocument->getFileSize(); + $fileName = $sVersion.'-'.$oDocument->getFileName(); + + return KTUtil::download($sDocumentFileSystemPath, $mimeType, $fileSize, $fileName); + } /** * Move a document to a new folder @@ -300,9 +283,9 @@ class PhysicalDocumentManager { global $default; $iContentId = $oVersion->getContentVersionId(); $oContentVersion = KTDocumentContentVersion::get($iContentId); - + $sFullPath = $default->documentRoot.'/'.$oContentVersion->getStoragePath(); - + if (file_exists($sFullPath)) { if(@unlink($sFullPath)){ $default->log->info("PhysicalDocumentManager::deleteVersion unlinked $sFullPath"); diff --git a/lib/foldermanagement/compressionArchiveUtil.inc.php b/lib/foldermanagement/compressionArchiveUtil.inc.php index 28f9a3c..17a1ce1 100644 --- a/lib/foldermanagement/compressionArchiveUtil.inc.php +++ b/lib/foldermanagement/compressionArchiveUtil.inc.php @@ -1,307 +1,305 @@ -. - * - * You can contact KnowledgeTree Inc., PO Box 7775 #87847, San Francisco, - * California 94120-7775, or email info@knowledgetree.com. - * - * The interactive user interfaces in modified source and object code versions - * of this program must display Appropriate Legal Notices, as required under - * Section 5 of the GNU General Public License version 3. - * - * In accordance with Section 7(b) of the GNU General Public License version 3, - * these Appropriate Legal Notices must retain the display of the "Powered by - * KnowledgeTree" logo and retain the original copyright notice. If the display of the - * logo is not reasonably feasible for technical reasons, the Appropriate Legal Notices - * must display the words "Powered by KnowledgeTree" and retain the original - * copyright notice. - * Contributor( s): ______________________________________ - * - */ - -/** -* Class to create and download a zip file -*/ -class ZipFolder { - - var $sTmpPath = ''; - var $sZipFileName = ''; - var $sZipFile = ''; - var $sPattern = ''; - var $sFolderPattern = ''; - var $aPaths = array(); - var $aReplaceKeys = array(); - var $aReplaceValues = array(); - var $sOutputEncoding = 'UTF-8'; - - /** - * Constructor - * - * @param string $sZipFileName The name of the zip file - gets ignored at the moment. - * @param string $exportCode The code to use if a zip file has already been created. - */ - function ZipFolder($sZipFileName, $exportCode = null) { - $this->oKTConfig =& KTConfig::getSingleton(); - $this->oStorage =& KTStorageManagerUtil::getSingleton(); - - $this->sOutputEncoding = $this->oKTConfig->get('export/encoding', 'UTF-8'); - - $this->sPattern = "[\*|\%|\\\|\/|\<|\>|\+|\:|\?|\||\'|\"]"; - $this->sFolderPattern = "[\*|\%|\<|\>|\+|\:|\?|\||\'|\"]"; - - // If the export code exists then a temp zip directory has already been created - if(!empty($exportCode)){ - $aData = KTUtil::arrayGet($_SESSION['zipcompression'], $exportCode); - - if(!empty($aData)){ - $sTmpPath = $aData['dir']; - } - }else { - $sBasedir = $this->oKTConfig->get("urls/tmpDirectory"); - $sTmpPath = tempnam($sBasedir, 'kt_compress_zip'); - - unlink($sTmpPath); - mkdir($sTmpPath, 0755); - } - - // Hard coding the zip file name. - // It normally uses the folder name but if there are special characters in the name then it doesn't download properly. - $sZipFileName = 'kt_zip'; - - $this->sTmpPath = $sTmpPath; - $this->sZipFileName = $sZipFileName; - $this->aPaths = array(); - - $aReplace = array( - "[" => "[[]", - " " => "[ ]", - "*" => "[*]", - "?" => "[?]", - ); - - $this->aReplaceKeys = array_keys($aReplace); - $this->aReplaceValues = array_values($aReplace); - } - - /** - * Return the full path - * - * @param mixed $oFolderOrDocument May be a Folder or Document - */ - function getFullFolderPath($oFolder) - { - static $sRootFolder = null; - - if (is_null($sRootFolder)) - { - $oRootFolder = Folder::get(1); - $sRootFolder = $oRootFolder->getName(); - } - - $sFullPath = $sRootFolder . '/'; - $sFullPath .= $oFolder->getFullPath(); - - - if (substr($sFullPath,-1) == '/') $sFullPath = substr($sFullPath,0,-1); - return $sFullPath; - } - - - /** - * Add a document to the zip file - */ - function addDocumentToZip($oDocument, $oFolder = null) { - if(empty($oFolder)){ - $oFolder = Folder::get($oDocument->getFolderID()); - } - - $sDocPath = $this->getFullFolderPath($oFolder); - $sDocPath = preg_replace($this->sFolderPattern, '-', $sDocPath); - $sDocPath = $this->_convertEncoding($sDocPath, true); - - - $sDocName = $oDocument->getFileName(); - $sDocName = preg_replace($this->sPattern, '-', $sDocName); - $sDocName = $this->_convertEncoding($sDocName, true); - - $sParentFolder = $this->sTmpPath.'/'.$sDocPath; - $newDir = $this->sTmpPath; - - $aFullPath = split('/', $sDocPath); - foreach ($aFullPath as $dirPart) { - $newDir = sprintf("%s/%s", $newDir, $dirPart); - if (!file_exists($newDir)) { - mkdir($newDir, 0700); - } - } - - $sOrigFile = $this->oStorage->temporaryFile($oDocument); - $sFilename = $sParentFolder.'/'.$sDocName; - copy($sOrigFile, $sFilename); - - $this->aPaths[] = $sDocPath.'/'.$sDocName; - return true; - } - - /** - * Add a folder to the zip file - */ - function addFolderToZip($oFolder) { - $sFolderPath = $this->getFullFolderPath($oFolder) .'/'; - $sFolderPath = preg_replace($this->sFolderPattern, '-', $sFolderPath); - $sFolderPath = $this->_convertEncoding($sFolderPath, true); - - $newDir = $this->sTmpPath; - - $aFullPath = split('/', $sFolderPath); - foreach ($aFullPath as $dirPart) { - $newDir = sprintf("%s/%s", $newDir, $dirPart); - if (!file_exists($newDir)) { - mkdir($newDir, 0700); - } - } - - $this->aPaths[] = $sFolderPath; - return true; - } - - /** - * Zip the temp folder - */ - function createZipFile($bEchoStatus = FALSE) { - if(empty($this->aPaths)){ - return PEAR::raiseError(_kt("No folders or documents found to compress")); - } - - // Set environment language to output character encoding - $loc = $this->sOutputEncoding; - putenv("LANG=$loc"); - putenv("LANGUAGE=$loc"); - $loc = setlocale(LC_ALL, $loc); - - - - $sManifest = sprintf("%s/%s", $this->sTmpPath, "MANIFEST"); - file_put_contents($sManifest, join("\n", $this->aPaths)); - $sZipFile = sprintf("%s/%s.zip", $this->sTmpPath, $this->sZipFileName); - $sZipFile = str_replace('<', '', str_replace('', '', $sZipFile))); - $sZipCommand = KTUtil::findCommand("export/zip", "zip"); - $aCmd = array($sZipCommand, "-r", $sZipFile, ".", "-i@MANIFEST"); - $sOldPath = getcwd(); - chdir($this->sTmpPath); - - // Note that the popen means that pexec will return a file descriptor - $aOptions = array('popen' => 'r'); - $fh = KTUtil::pexec($aCmd, $aOptions); - - if($bEchoStatus){ - $last_beat = time(); - while(!feof($fh)) { - if ($i % 1000 == 0) { - $this_beat = time(); - if ($last_beat + 1 < $this_beat) { - $last_beat = $this_beat; - print " "; - } - } - $contents = fread($fh, 4096); - if ($contents) { - print nl2br($this->_convertEncoding($contents, false)); - } - $i++; - } - } - pclose($fh); - - // Save the zip file and path into session - $_SESSION['zipcompression'] = KTUtil::arrayGet($_SESSION, 'zipcompression', array()); - $sExportCode = KTUtil::randomString(); - $_SESSION['zipcompression'][$sExportCode] = array( - 'file' => $sZipFile, - 'dir' => $this->sTmpPath, - ); - $_SESSION['zipcompression']['exportcode'] = $sExportCode; - - $this->sZipFile = $sZipFile; - return $sExportCode; - } - - /** - * Download the zip file - */ - function downloadZipFile($exportCode = NULL) { - if(!(isset($exportCode) && !empty($exportCode))) { - $exportCode = KTUtil::arrayGet($_SESSION['zipcompression'], 'exportcode'); - } - - $aData = KTUtil::arrayGet($_SESSION['zipcompression'], $exportCode); - - if(!empty($aData)){ - $sZipFile = $aData['file']; - $sTmpPath = $aData['dir']; - }else{ - $sZipFile = $this->sZipFile; - $sTmpPath = $this->sTmpPath; - } - - if (!file_exists($sZipFile)) { - return PEAR::raiseError(_kt('The ZIP file can only be downloaded once - if you cancel the download, you will need to reload the page.')); - } - - header("Content-Type: application/zip; charset=utf-8"); - header("Content-Length: ". filesize($sZipFile)); - header("Content-Disposition: attachment; filename=\"" . $this->sZipFileName . ".zip" . "\""); - header("Expires: Mon, 26 Jul 1997 05:00:00 GMT"); - header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT"); - header("Cache-Control: must-revalidate"); - readfile($sZipFile); - KTUtil::deleteDirectory($sTmpPath); - return true; - } - - /** - * Check that iconv exists and that the selected encoding is supported. - */ - function checkConvertEncoding() { - if(!function_exists("iconv")) { - return PEAR::raiseError(_kt('IConv PHP extension not installed. The zip file compression could not handle output filename encoding conversion !')); - } - $oKTConfig = $this->oKTConfig; - $this->sOutputEncoding = $oKTConfig->get('export/encoding', 'UTF-8'); - - // Test the specified encoding - if(iconv("UTF-8", $this->sOutputEncoding, "") === FALSE) { - return PEAR::raiseError(_kt('Specified output encoding for the zip files compression does not exists !')); - } - return true; - } - - function _convertEncoding($sMystring, $bEncode) { - if (strcasecmp($this->sOutputEncoding, "UTF-8") === 0) { - return $sMystring; - } - if ($bEncode) { - return iconv("UTF-8", $this->sOutputEncoding, $sMystring); - } else { - return iconv($this->sOutputEncoding, "UTF-8", $sMystring); - } - } -} +. + * + * You can contact KnowledgeTree Inc., PO Box 7775 #87847, San Francisco, + * California 94120-7775, or email info@knowledgetree.com. + * + * The interactive user interfaces in modified source and object code versions + * of this program must display Appropriate Legal Notices, as required under + * Section 5 of the GNU General Public License version 3. + * + * In accordance with Section 7(b) of the GNU General Public License version 3, + * these Appropriate Legal Notices must retain the display of the "Powered by + * KnowledgeTree" logo and retain the original copyright notice. If the display of the + * logo is not reasonably feasible for technical reasons, the Appropriate Legal Notices + * must display the words "Powered by KnowledgeTree" and retain the original + * copyright notice. + * Contributor( s): ______________________________________ + * + */ + +/** +* Class to create and download a zip file +*/ +class ZipFolder { + + var $sTmpPath = ''; + var $sZipFileName = ''; + var $sZipFile = ''; + var $sPattern = ''; + var $sFolderPattern = ''; + var $aPaths = array(); + var $aReplaceKeys = array(); + var $aReplaceValues = array(); + var $sOutputEncoding = 'UTF-8'; + + /** + * Constructor + * + * @param string $sZipFileName The name of the zip file - gets ignored at the moment. + * @param string $exportCode The code to use if a zip file has already been created. + */ + function ZipFolder($sZipFileName, $exportCode = null) { + $this->oKTConfig =& KTConfig::getSingleton(); + $this->oStorage =& KTStorageManagerUtil::getSingleton(); + + $this->sOutputEncoding = $this->oKTConfig->get('export/encoding', 'UTF-8'); + + $this->sPattern = "[\*|\%|\\\|\/|\<|\>|\+|\:|\?|\||\'|\"]"; + $this->sFolderPattern = "[\*|\%|\<|\>|\+|\:|\?|\||\'|\"]"; + + // If the export code exists then a temp zip directory has already been created + if(!empty($exportCode)){ + $aData = KTUtil::arrayGet($_SESSION['zipcompression'], $exportCode); + + if(!empty($aData)){ + $sTmpPath = $aData['dir']; + } + }else { + $sBasedir = $this->oKTConfig->get("urls/tmpDirectory"); + $sTmpPath = tempnam($sBasedir, 'kt_compress_zip'); + + unlink($sTmpPath); + mkdir($sTmpPath, 0755); + } + + // Hard coding the zip file name. + // It normally uses the folder name but if there are special characters in the name then it doesn't download properly. + $sZipFileName = 'kt_zip'; + + $this->sTmpPath = $sTmpPath; + $this->sZipFileName = $sZipFileName; + $this->aPaths = array(); + + $aReplace = array( + "[" => "[[]", + " " => "[ ]", + "*" => "[*]", + "?" => "[?]", + ); + + $this->aReplaceKeys = array_keys($aReplace); + $this->aReplaceValues = array_values($aReplace); + } + + /** + * Return the full path + * + * @param mixed $oFolderOrDocument May be a Folder or Document + */ + function getFullFolderPath($oFolder) + { + static $sRootFolder = null; + + if (is_null($sRootFolder)) + { + $oRootFolder = Folder::get(1); + $sRootFolder = $oRootFolder->getName(); + } + + $sFullPath = $sRootFolder . '/'; + $sFullPath .= $oFolder->getFullPath(); + + + if (substr($sFullPath,-1) == '/') $sFullPath = substr($sFullPath,0,-1); + return $sFullPath; + } + + + /** + * Add a document to the zip file + */ + function addDocumentToZip($oDocument, $oFolder = null) { + if(empty($oFolder)){ + $oFolder = Folder::get($oDocument->getFolderID()); + } + + $sDocPath = $this->getFullFolderPath($oFolder); + $sDocPath = preg_replace($this->sFolderPattern, '-', $sDocPath); + $sDocPath = $this->_convertEncoding($sDocPath, true); + + + $sDocName = $oDocument->getFileName(); + $sDocName = preg_replace($this->sPattern, '-', $sDocName); + $sDocName = $this->_convertEncoding($sDocName, true); + + $sParentFolder = $this->sTmpPath.'/'.$sDocPath; + $newDir = $this->sTmpPath; + + $aFullPath = split('/', $sDocPath); + foreach ($aFullPath as $dirPart) { + $newDir = sprintf("%s/%s", $newDir, $dirPart); + if (!file_exists($newDir)) { + mkdir($newDir, 0700); + } + } + + $sOrigFile = $this->oStorage->temporaryFile($oDocument); + $sFilename = $sParentFolder.'/'.$sDocName; + copy($sOrigFile, $sFilename); + + $this->aPaths[] = $sDocPath.'/'.$sDocName; + return true; + } + + /** + * Add a folder to the zip file + */ + function addFolderToZip($oFolder) { + $sFolderPath = $this->getFullFolderPath($oFolder) .'/'; + $sFolderPath = preg_replace($this->sFolderPattern, '-', $sFolderPath); + $sFolderPath = $this->_convertEncoding($sFolderPath, true); + + $newDir = $this->sTmpPath; + + $aFullPath = split('/', $sFolderPath); + foreach ($aFullPath as $dirPart) { + $newDir = sprintf("%s/%s", $newDir, $dirPart); + if (!file_exists($newDir)) { + mkdir($newDir, 0700); + } + } + + $this->aPaths[] = $sFolderPath; + return true; + } + + /** + * Zip the temp folder + */ + function createZipFile($bEchoStatus = FALSE) { + if(empty($this->aPaths)){ + return PEAR::raiseError(_kt("No folders or documents found to compress")); + } + + // Set environment language to output character encoding + $loc = $this->sOutputEncoding; + putenv("LANG=$loc"); + putenv("LANGUAGE=$loc"); + $loc = setlocale(LC_ALL, $loc); + + + + $sManifest = sprintf("%s/%s", $this->sTmpPath, "MANIFEST"); + file_put_contents($sManifest, join("\n", $this->aPaths)); + $sZipFile = sprintf("%s/%s.zip", $this->sTmpPath, $this->sZipFileName); + $sZipFile = str_replace('<', '', str_replace('', '', $sZipFile))); + $sZipCommand = KTUtil::findCommand("export/zip", "zip"); + $aCmd = array($sZipCommand, "-r", $sZipFile, ".", "-i@MANIFEST"); + $sOldPath = getcwd(); + chdir($this->sTmpPath); + + // Note that the popen means that pexec will return a file descriptor + $aOptions = array('popen' => 'r'); + $fh = KTUtil::pexec($aCmd, $aOptions); + + if($bEchoStatus){ + $last_beat = time(); + while(!feof($fh)) { + if ($i % 1000 == 0) { + $this_beat = time(); + if ($last_beat + 1 < $this_beat) { + $last_beat = $this_beat; + print " "; + } + } + $contents = fread($fh, 4096); + if ($contents) { + print nl2br($this->_convertEncoding($contents, false)); + } + $i++; + } + } + pclose($fh); + + // Save the zip file and path into session + $_SESSION['zipcompression'] = KTUtil::arrayGet($_SESSION, 'zipcompression', array()); + $sExportCode = KTUtil::randomString(); + $_SESSION['zipcompression'][$sExportCode] = array( + 'file' => $sZipFile, + 'dir' => $this->sTmpPath, + ); + $_SESSION['zipcompression']['exportcode'] = $sExportCode; + + $this->sZipFile = $sZipFile; + return $sExportCode; + } + + /** + * Download the zip file + */ + function downloadZipFile($exportCode = NULL) { + if(!(isset($exportCode) && !empty($exportCode))) { + $exportCode = KTUtil::arrayGet($_SESSION['zipcompression'], 'exportcode'); + } + + $aData = KTUtil::arrayGet($_SESSION['zipcompression'], $exportCode); + + if(!empty($aData)){ + $sZipFile = $aData['file']; + $sTmpPath = $aData['dir']; + }else{ + $sZipFile = $this->sZipFile; + $sTmpPath = $this->sTmpPath; + } + + if (!file_exists($sZipFile)) { + return PEAR::raiseError(_kt('The ZIP file can only be downloaded once - if you cancel the download, you will need to reload the page.')); + } + + $mimeType = 'application/zip; charset=utf-8;'; + $fileSize = filesize($sZipFile); + $fileName = $this->sZipFileName . '.zip'; + + KTUtil::download($sZipFile, $mimeType, $fileSize, $fileName); + KTUtil::deleteDirectory($sTmpPath); + return true; + } + + /** + * Check that iconv exists and that the selected encoding is supported. + */ + function checkConvertEncoding() { + if(!function_exists("iconv")) { + return PEAR::raiseError(_kt('IConv PHP extension not installed. The zip file compression could not handle output filename encoding conversion !')); + } + $oKTConfig = $this->oKTConfig; + $this->sOutputEncoding = $oKTConfig->get('export/encoding', 'UTF-8'); + + // Test the specified encoding + if(iconv("UTF-8", $this->sOutputEncoding, "") === FALSE) { + return PEAR::raiseError(_kt('Specified output encoding for the zip files compression does not exists !')); + } + return true; + } + + function _convertEncoding($sMystring, $bEncode) { + if (strcasecmp($this->sOutputEncoding, "UTF-8") === 0) { + return $sMystring; + } + if ($bEncode) { + return iconv("UTF-8", $this->sOutputEncoding, $sMystring); + } else { + return iconv($this->sOutputEncoding, "UTF-8", $sMystring); + } + } +} ?> \ No newline at end of file diff --git a/lib/storage/ondiskhashedstoragemanager.inc.php b/lib/storage/ondiskhashedstoragemanager.inc.php index 7bb96c8..6ead3a7 100644 --- a/lib/storage/ondiskhashedstoragemanager.inc.php +++ b/lib/storage/ondiskhashedstoragemanager.inc.php @@ -182,36 +182,27 @@ class KTOnDiskHashedStorageManager extends KTStorageManager { } function download($oDocument, $bIsCheckout = false) { - //get the path to the document on the server - $oConfig =& KTConfig::getSingleton(); - $sPath = sprintf("%s/%s", $oConfig->get('urls/documentRoot'), $this->getPath($oDocument)); - $mimetype = KTMime::getMimeTypeName($oDocument->getMimeTypeID()); - - if ($bIsCheckout && $oConfig->get('ui/fakeMimetype' ,false)) { - $mimetype = 'application/x-download'; - // note this does not work for "image" types in some browsers - // go web. - } - - if (file_exists($sPath)) { - $sFileName = $oDocument->getFileName( ); + global $default; - //set the correct headers - header("Content-Type: " . $mimetype); - header("Content-Length: ". $oDocument->getFileSize()); - header('Content-Disposition: attachment; filename="' . $sFileName . '"'); - header("Expires: Mon, 26 Jul 1997 05:00:00 GMT"); - header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT"); - // HTTP/1.1 - if ( strpos( strtoupper( $browser), 'MSIE') == false) { - header("Cache-Control: no-store, no-cache, must-revalidate"); - header("Cache-Control: post-check=0, pre-check=0", false); + //get the path to the document on the server + $docRoot = $default->documentRoot; + $path = $docRoot .'/'. $oDocument->getStoragePath(); + + // Ensure the file exists + if (file_exists($path)) { + // Get the mime type + $mimeId = $oDocument->getMimeTypeID(); + $mimetype = KTMime::getMimeTypeName($mimeId); + + if ($bIsCheckout && $default->fakeMimetype) { + // note this does not work for "image" types in some browsers + $mimetype = 'application/x-download'; } - // HTTP/1.0 - //header("Pragma: no-cache"); // Don't send this header! It breaks IE. + $sFileName = $oDocument->getFileName( ); + $iFileSize = $oDocument->getFileSize(); - readfile($sPath); + KTUtil::download($path, $mimetype, $iFileSize, $sFileName); } else { return false; } @@ -239,19 +230,14 @@ class KTOnDiskHashedStorageManager extends KTStorageManager { $sPath = sprintf("%s/%s", $oConfig->get('urls/documentRoot'), $this->getPath($oContentVersion)); $sVersion = sprintf("%d.%d", $oContentVersion->getMajorVersionNumber(), $oContentVersion->getMinorVersionNumber()); if (file_exists($sPath)) { - //set the correct headers - header("Content-Type: " . - KTMime::getMimeTypeName($oContentVersion->getMimeTypeID())); - header("Content-Length: ". filesize($sPath)); - // prefix the filename presented to the browser to preserve the document extension - header('Content-Disposition: attachment; filename="' . "$sVersion-" . $oContentVersion->getFileName() . '"'); - header("Expires: Mon, 26 Jul 1997 05:00:00 GMT"); - header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT"); - header("Cache-Control: must-revalidate"); - - readfile($sPath); - //$oFile = new KTFSFileLike($sPath); - //KTFileLikeUtil::send_contents($oFile); + // Get the mime type + $mimeId = $oContentVersion->getMimeTypeID(); + $mimetype = KTMime::getMimeTypeName($mimeId); + + $sFileName = $sVersion.'-'.$oContentVersion->getFileName( ); + $iFileSize = $oContentVersion->getFileSize(); + + KTUtil::download($sPath, $mimetype, $iFileSize, $sFileName); } else { return false; } diff --git a/lib/storage/ondiskpathstoragemanager.inc.php b/lib/storage/ondiskpathstoragemanager.inc.php index 3d775ac..e8d6d55 100644 --- a/lib/storage/ondiskpathstoragemanager.inc.php +++ b/lib/storage/ondiskpathstoragemanager.inc.php @@ -132,20 +132,12 @@ class KTOnDiskPathStorageManager extends KTStorageManager { //get the path to the document on the server $oConfig =& KTConfig::getSingleton(); $sPath = sprintf("%s/%s", $oConfig->get('urls/documentRoot'), $this->getPath($oDocument)); - if (file_exists($sPath)) { - //set the correct headers - header("Content-Type: " . - KTMime::getMimeTypeName($oDocument->getMimeTypeID())); - header("Content-Length: ". $oDocument->getFileSize()); - header("Content-Disposition: attachment; filename=\"" . $oDocument->getFileName() . "\""); - header("Expires: Mon, 26 Jul 1997 05:00:00 GMT"); - header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT"); - header("Cache-Control: must-revalidate"); - - readfile($sPath); - } else { - return false; - } + + $mimeType = KTMime::getMimeTypeName($oDocument->getMimeTypeID()); + $fileSize = $oDocument->getFileSize(); + $fileName = $oDocument->getFileName(); + + return KTUtil::download($sPath, $mimeType, $fileSize, $fileName); } function createFolder($oFolder) { @@ -185,20 +177,12 @@ class KTOnDiskPathStorageManager extends KTStorageManager { $oConfig =& KTConfig::getSingleton(); $sPath = sprintf("%s/%s", $oConfig->get('urls/documentRoot'), $this->getPath($oContentVersion)); $sVersion = sprintf("%d.%d", $oContentVersion->getMajorVersionNumber(), $oContentVersion->getMinorVersionNumber()); - if (file_exists($sPath)) { - //set the correct headers - header("Content-Type: " . - KTMime::getMimeTypeName($oDocument->getMimeTypeID())); - header("Content-Length: ". filesize($sPath)); - // prefix the filename presented to the browser to preserve the document extension - header('Content-Disposition: attachment; filename="' . "$sVersion-" . $oDocument->getFileName() . '"'); - header("Expires: Mon, 26 Jul 1997 05:00:00 GMT"); - header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT"); - header("Cache-Control: must-revalidate"); - readfile($sPath); - } else { - return false; - } + + $mimeType = KTMime::getMimeTypeName($oContentVersion->getMimeTypeID()); + $fileSize = $oContentVersion->getFileSize(); + $fileName = $sVersion.'-'.$oContentVersion->getFileName(); + + return KTUtil::download($sPath, $mimeType, $fileSize, $fileName); } /** diff --git a/lib/util/ktutil.inc b/lib/util/ktutil.inc index ac516c2..a48e1e0 100644 --- a/lib/util/ktutil.inc +++ b/lib/util/ktutil.inc @@ -1245,6 +1245,36 @@ class KTUtil { return $aBreadcrumbs; } + /** + * Generates the correct headers for downloading a document + */ + function download($path, $mimeType, $fileSize, $fileName, $displayType = 'attachment') + { + if (file_exists($path)) { + // IE7 adds underscores to filenames: fix + $browser = $_SERVER['HTTP_USER_AGENT']; + if ( strpos( strtoupper( $browser), 'MSIE 7') !== false) { + $fileName = rawurlencode($fileName); + } + + // Set the correct headers + header("Content-Type: {$mimeType}"); + header("Content-Length: {$fileSize}"); + header("Content-Disposition: {$displayType}; filename=\"{$fileName}\""); + header("Expires: Mon, 26 Jul 1997 05:00:00 GMT"); + header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT"); + + // Document must be cached in order to open it + header("Cache-Control: must-revalidate"); + + // Allows the file to be downloaded, otherwise it attempts the download as "action.php?..." + header("Pragma: public"); + + readfile($path); + }else { + return false; + } + } } /** diff --git a/plugins/ktstandard/PDFGeneratorAction.php b/plugins/ktstandard/PDFGeneratorAction.php index eae45c2..59e14c7 100644 --- a/plugins/ktstandard/PDFGeneratorAction.php +++ b/plugins/ktstandard/PDFGeneratorAction.php @@ -6,31 +6,31 @@ * Document Management Made Simple * Copyright (C) 2008 KnowledgeTree Inc. * Portions copyright The Jam Warehouse Software (Pty) Limited - * + * * This program is free software; you can redistribute it and/or modify it under * the terms of the GNU General Public License version 3 as published by the * Free Software Foundation. - * + * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more * details. - * + * * You should have received a copy of the GNU General Public License * along with this program. If not, see . - * - * You can contact KnowledgeTree Inc., PO Box 7775 #87847, San Francisco, + * + * You can contact KnowledgeTree Inc., PO Box 7775 #87847, San Francisco, * California 94120-7775, or email info@knowledgetree.com. - * + * * The interactive user interfaces in modified source and object code versions * of this program must display Appropriate Legal Notices, as required under * Section 5 of the GNU General Public License version 3. - * + * * In accordance with Section 7(b) of the GNU General Public License version 3, * these Appropriate Legal Notices must retain the display of the "Powered by - * KnowledgeTree" logo and retain the original copyright notice. If the display of the + * KnowledgeTree" logo and retain the original copyright notice. If the display of the * logo is not reasonably feasible for technical reasons, the Appropriate Legal Notices - * must display the words "Powered by KnowledgeTree" and retain the original + * must display the words "Powered by KnowledgeTree" and retain the original * copyright notice. * Contributor( s): ______________________________________ * @@ -52,8 +52,8 @@ class PDFGeneratorAction extends KTDocumentAction { var $sDisplayName = 'Generate PDF'; // Note: 'asc' below seems to be a catchall for plain text docs. // 'htm' and 'html' should work but are not so have been removed for now. - var $aAcceptedMimeTypes = array('doc', 'ods', 'odt', 'ott', 'txt', 'rtf', 'sxw', 'stw', - // 'html', 'htm', + var $aAcceptedMimeTypes = array('doc', 'ods', 'odt', 'ott', 'txt', 'rtf', 'sxw', 'stw', + // 'html', 'htm', 'xml' , 'pdb', 'psw', 'ods', 'ots', 'sxc', 'stc', 'dif', 'dbf', 'xls', 'xlt', 'slk', 'csv', 'pxl', 'odp', 'otp', 'sxi', 'sti', 'ppt', 'pot', 'sxd', 'odg', @@ -126,7 +126,7 @@ class PDFGeneratorAction extends KTDocumentAction { $this->do_pdfdownload(); } redirect(KTUtil::ktLink( 'action.php', 'ktstandard.pdf.generate', array( "fDocumentId" => $this->oDocument->getId() ) ) ); - exit(0); + exit(0); } function do_main() { @@ -171,7 +171,7 @@ class PDFGeneratorAction extends KTDocumentAction { /** * Method for downloading the document as a pdf. * - * @return true on success else false + * @return true on success else false */ function do_pdfdownload() { @@ -184,7 +184,7 @@ class PDFGeneratorAction extends KTDocumentAction { // Set the error messsage and redirect to view document $this->addErrorMessage(_kt('An error occurred generating the PDF - please contact the system administrator. Python binary not found.')); redirect(generateControllerLink('viewDocument',sprintf('fDocumentId=%d',$oDocument->getId()))); - exit(0); + exit(0); } //get the actual path to the document on the server @@ -199,7 +199,7 @@ class PDFGeneratorAction extends KTDocumentAction { if (substr( PHP_OS, 0, 3) == 'WIN') { $cmd = "\"" . $cmdpath . "\" \"". KT_DIR . "/bin/openoffice/pdfgen.py\" \"" . $sPath . "\" \"" . $sTempFilename . "\""; - $cmd = str_replace( '/','\\',$cmd); + $cmd = str_replace( '/','\\',$cmd); // TODO: Check for more errors here // SECURTIY: Ensure $sPath and $sTempFilename are safe or they could be used to excecute arbitrary commands! @@ -222,30 +222,14 @@ class PDFGeneratorAction extends KTDocumentAction { } - // Check the tempfile exists and the python script did not return anything (which would indicate an error) + // Check the tempfile exists and the python script did not return anything (which would indicate an error) if (file_exists($sTempFilename) && $res == '') { - $sUrlEncodedFileName = substr($oDocument->getFileName(), 0, strrpos($oDocument->getFileName(), '.') ); - $browser = $_SERVER['HTTP_USER_AGENT']; - if ( strpos( strtoupper( $browser), 'MSIE') !== false) { - $sUrlEncodedFileName = rawurlencode($sUrlEncodedFileName); - } - // Set the correct headers - header("Content-Type: application/pdf"); - header("Content-Length: ". filesize($sTempFilename)); - header("Content-Disposition: attachment; filename=\"" . $sUrlEncodedFileName . ".pdf\""); - header("Expires: Mon, 26 Jul 1997 05:00:00 GMT"); - header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT"); - // HTTP/1.1 - header("Cache-Control: no-store, no-cache, must-revalidate"); - header("Cache-Control: post-check=0, pre-check=0", false); - - // HTTP/1.0 - // header("Pragma: no-cache"); // Don't send this header! It breaks IE. - - // Get a filelike object and send it to the browser - $oFile = new KTFSFileLike($sTempFilename); - KTFileLikeUtil::send_contents($oFile); + $mimetype = 'application/pdf'; + $size = filesize($sTempFilename); + $name = substr($oDocument->getFileName(), 0, strrpos($oDocument->getFileName(), '.') ) . '.pdf'; + KTUtil::download($sTempFilename, $mimetype, $size, $name); + // Remove the tempfile unlink($sTempFilename); @@ -253,20 +237,20 @@ class PDFGeneratorAction extends KTDocumentAction { $oDocumentTransaction = & new DocumentTransaction($oDocument, 'Document downloaded as PDF', 'ktcore.transactions.download', $aOptions); $oDocumentTransaction->create(); // Just stop here - the content has already been sent. - exit(0); + exit(0); } else { // Set the error messsage and redirect to view document $this->addErrorMessage(_kt('An error occurred generating the PDF - please contact the system administrator. ' . $res)); redirect(generateControllerLink('viewDocument',sprintf('fDocumentId=%d',$oDocument->getId()))); - exit(0); + exit(0); } } else { // Set the error messsage and redirect to view document $this->addErrorMessage(_kt('An error occurred generating the PDF - please contact the system administrator. The path to the document did not exist.')); redirect(generateControllerLink('viewDocument',sprintf('fDocumentId=%d',$oDocument->getId()))); - exit(0); + exit(0); } -- libgit2 0.21.4