Commit 37cb8f5e089641be74990a68a67a3fe960a5462b
1 parent
021dc0e7
KTS-3661
"Error on downloading via SSL in IE" Fixed. Created a new KTUtil function to generate the correct headers for downloading files. KTC-147 "Error when opening a newly generated PDF document directly after it has been created." Fixed. Used the new KTUtil function to get the correct headers for the PDF. Committed by: Megan Watson Reviewed by: Conrad Vermeulen git-svn-id: https://kt-dms.svn.sourceforge.net/svnroot/kt-dms/trunk@9210 c91229c3-7414-0410-bfa2-8a42b809f60b
Showing
6 changed files
with
427 additions
and
462 deletions
lib/documentmanagement/PhysicalDocumentManager.inc
| ... | ... | @@ -9,31 +9,31 @@ |
| 9 | 9 | * Document Management Made Simple |
| 10 | 10 | * Copyright (C) 2008 KnowledgeTree Inc. |
| 11 | 11 | * Portions copyright The Jam Warehouse Software (Pty) Limited |
| 12 | - * | |
| 12 | + * | |
| 13 | 13 | * This program is free software; you can redistribute it and/or modify it under |
| 14 | 14 | * the terms of the GNU General Public License version 3 as published by the |
| 15 | 15 | * Free Software Foundation. |
| 16 | - * | |
| 16 | + * | |
| 17 | 17 | * This program is distributed in the hope that it will be useful, but WITHOUT |
| 18 | 18 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS |
| 19 | 19 | * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more |
| 20 | 20 | * details. |
| 21 | - * | |
| 21 | + * | |
| 22 | 22 | * You should have received a copy of the GNU General Public License |
| 23 | 23 | * along with this program. If not, see <http://www.gnu.org/licenses/>. |
| 24 | - * | |
| 25 | - * You can contact KnowledgeTree Inc., PO Box 7775 #87847, San Francisco, | |
| 24 | + * | |
| 25 | + * You can contact KnowledgeTree Inc., PO Box 7775 #87847, San Francisco, | |
| 26 | 26 | * California 94120-7775, or email info@knowledgetree.com. |
| 27 | - * | |
| 27 | + * | |
| 28 | 28 | * The interactive user interfaces in modified source and object code versions |
| 29 | 29 | * of this program must display Appropriate Legal Notices, as required under |
| 30 | 30 | * Section 5 of the GNU General Public License version 3. |
| 31 | - * | |
| 31 | + * | |
| 32 | 32 | * In accordance with Section 7(b) of the GNU General Public License version 3, |
| 33 | 33 | * these Appropriate Legal Notices must retain the display of the "Powered by |
| 34 | - * KnowledgeTree" logo and retain the original copyright notice. If the display of the | |
| 34 | + * KnowledgeTree" logo and retain the original copyright notice. If the display of the | |
| 35 | 35 | * logo is not reasonably feasible for technical reasons, the Appropriate Legal Notices |
| 36 | - * must display the words "Powered by KnowledgeTree" and retain the original | |
| 36 | + * must display the words "Powered by KnowledgeTree" and retain the original | |
| 37 | 37 | * copyright notice. |
| 38 | 38 | * Contributor( s): ______________________________________ |
| 39 | 39 | */ |
| ... | ... | @@ -56,25 +56,17 @@ class PhysicalDocumentManager { |
| 56 | 56 | * @todo investigate possible problem in MSIE 5.5 concerning Content-Disposition header |
| 57 | 57 | */ |
| 58 | 58 | function downloadPhysicalDocument($iDocumentID) { |
| 59 | - //get the document | |
| 60 | - $oDocument = & Document::get($iDocumentID); | |
| 61 | - //get the path to the document on the server | |
| 62 | - $sDocumentFileSystemPath = $oDocument->getPath(); | |
| 63 | - if (file_exists($sDocumentFileSystemPath)) { | |
| 64 | - //set the correct headers | |
| 65 | - header("Content-Type: " . | |
| 66 | - KTMime::getMimeTypeName($oDocument->getMimeTypeID())); | |
| 67 | - header("Content-Length: ". $oDocument->getFileSize()); | |
| 68 | - header("Content-Disposition: attachment; filename=\"" . $oDocument->getFileName() . "\""); | |
| 69 | - header("Expires: Mon, 26 Jul 1997 05:00:00 GMT"); | |
| 70 | - header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT"); | |
| 71 | - header("Cache-Control: must-revalidate"); | |
| 72 | - header("Content-Location: ".$oDocument->getFileName()); | |
| 59 | + //get the document | |
| 60 | + $oDocument = & Document::get($iDocumentID); | |
| 61 | + //get the path to the document on the server | |
| 62 | + $sDocumentFileSystemPath = $oDocument->getPath(); | |
| 63 | + | |
| 64 | + $mimeType = KTMime::getMimeTypeName($oDocument->getMimeTypeID()); | |
| 65 | + $fileSize = $oDocument->getFileSize(); | |
| 66 | + $fileName = $oDocument->getFileName(); | |
| 67 | + | |
| 68 | + return KTUtil::download($sDocumentFileSystemPath, $mimeType, $fileSize, $fileName); | |
| 73 | 69 | |
| 74 | - readfile($sDocumentFileSystemPath); | |
| 75 | - } else { | |
| 76 | - return false; | |
| 77 | - } | |
| 78 | 70 | } |
| 79 | 71 | |
| 80 | 72 | /** |
| ... | ... | @@ -85,26 +77,17 @@ class PhysicalDocumentManager { |
| 85 | 77 | * @return int number of bytes read from file on success or false otherwise; |
| 86 | 78 | */ |
| 87 | 79 | function downloadVersionedPhysicalDocument($iDocumentID, $sVersion) { |
| 88 | - //get the document | |
| 89 | - $oDocument = & Document::get($iDocumentID); | |
| 90 | - //get the path to the document on the server | |
| 91 | - $sDocumentFileSystemPath = $oDocument->getPath() . "-$sVersion"; | |
| 92 | - if (file_exists($sDocumentFileSystemPath)) { | |
| 93 | - //set the correct headers | |
| 94 | - header("Content-Type: " . | |
| 95 | - KTMime::getMimeTypeName($oDocument->getMimeTypeID())); | |
| 96 | - header("Content-Length: ". filesize($sDocumentFileSystemPath)); | |
| 97 | - // prefix the filename presented to the browser to preserve the document extension | |
| 98 | - header('Content-Disposition: attachment; filename="' . "$sVersion-" . $oDocument->getFileName() . '"'); | |
| 99 | - header("Expires: Mon, 26 Jul 1997 05:00:00 GMT"); | |
| 100 | - header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT"); | |
| 101 | - header("Cache-Control: must-revalidate"); | |
| 102 | - header("Content-Location: ".$oDocument->getFileName()); | |
| 103 | - readfile($sDocumentFileSystemPath); | |
| 104 | - } else { | |
| 105 | - return false; | |
| 106 | - } | |
| 107 | - } | |
| 80 | + //get the document | |
| 81 | + $oDocument = & Document::get($iDocumentID); | |
| 82 | + //get the path to the document on the server | |
| 83 | + $sDocumentFileSystemPath = $oDocument->getPath() . "-$sVersion"; | |
| 84 | + | |
| 85 | + $mimeType = KTMime::getMimeTypeName($oDocument->getMimeTypeID()); | |
| 86 | + $fileSize = $oDocument->getFileSize(); | |
| 87 | + $fileName = $sVersion.'-'.$oDocument->getFileName(); | |
| 88 | + | |
| 89 | + return KTUtil::download($sDocumentFileSystemPath, $mimeType, $fileSize, $fileName); | |
| 90 | + } | |
| 108 | 91 | |
| 109 | 92 | /** |
| 110 | 93 | * Move a document to a new folder |
| ... | ... | @@ -300,9 +283,9 @@ class PhysicalDocumentManager { |
| 300 | 283 | global $default; |
| 301 | 284 | $iContentId = $oVersion->getContentVersionId(); |
| 302 | 285 | $oContentVersion = KTDocumentContentVersion::get($iContentId); |
| 303 | - | |
| 286 | + | |
| 304 | 287 | $sFullPath = $default->documentRoot.'/'.$oContentVersion->getStoragePath(); |
| 305 | - | |
| 288 | + | |
| 306 | 289 | if (file_exists($sFullPath)) { |
| 307 | 290 | if(@unlink($sFullPath)){ |
| 308 | 291 | $default->log->info("PhysicalDocumentManager::deleteVersion unlinked $sFullPath"); | ... | ... |
lib/foldermanagement/compressionArchiveUtil.inc.php
| 1 | -<?php | |
| 2 | -/** | |
| 3 | - * $Id: | |
| 4 | - * | |
| 5 | - * KnowledgeTree Community Edition | |
| 6 | - * Document Management Made Simple | |
| 7 | - * Copyright (C) 2008 KnowledgeTree Inc. | |
| 8 | - * Portions copyright The Jam Warehouse Software (Pty) Limited | |
| 9 | - * | |
| 10 | - * This program is free software; you can redistribute it and/or modify it under | |
| 11 | - * the terms of the GNU General Public License version 3 as published by the | |
| 12 | - * Free Software Foundation. | |
| 13 | - * | |
| 14 | - * This program is distributed in the hope that it will be useful, but WITHOUT | |
| 15 | - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS | |
| 16 | - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more | |
| 17 | - * details. | |
| 18 | - * | |
| 19 | - * You should have received a copy of the GNU General Public License | |
| 20 | - * along with this program. If not, see <http://www.gnu.org/licenses/>. | |
| 21 | - * | |
| 22 | - * You can contact KnowledgeTree Inc., PO Box 7775 #87847, San Francisco, | |
| 23 | - * California 94120-7775, or email info@knowledgetree.com. | |
| 24 | - * | |
| 25 | - * The interactive user interfaces in modified source and object code versions | |
| 26 | - * of this program must display Appropriate Legal Notices, as required under | |
| 27 | - * Section 5 of the GNU General Public License version 3. | |
| 28 | - * | |
| 29 | - * In accordance with Section 7(b) of the GNU General Public License version 3, | |
| 30 | - * these Appropriate Legal Notices must retain the display of the "Powered by | |
| 31 | - * KnowledgeTree" logo and retain the original copyright notice. If the display of the | |
| 32 | - * logo is not reasonably feasible for technical reasons, the Appropriate Legal Notices | |
| 33 | - * must display the words "Powered by KnowledgeTree" and retain the original | |
| 34 | - * copyright notice. | |
| 35 | - * Contributor( s): ______________________________________ | |
| 36 | - * | |
| 37 | - */ | |
| 38 | - | |
| 39 | -/** | |
| 40 | -* Class to create and download a zip file | |
| 41 | -*/ | |
| 42 | -class ZipFolder { | |
| 43 | - | |
| 44 | - var $sTmpPath = ''; | |
| 45 | - var $sZipFileName = ''; | |
| 46 | - var $sZipFile = ''; | |
| 47 | - var $sPattern = ''; | |
| 48 | - var $sFolderPattern = ''; | |
| 49 | - var $aPaths = array(); | |
| 50 | - var $aReplaceKeys = array(); | |
| 51 | - var $aReplaceValues = array(); | |
| 52 | - var $sOutputEncoding = 'UTF-8'; | |
| 53 | - | |
| 54 | - /** | |
| 55 | - * Constructor | |
| 56 | - * | |
| 57 | - * @param string $sZipFileName The name of the zip file - gets ignored at the moment. | |
| 58 | - * @param string $exportCode The code to use if a zip file has already been created. | |
| 59 | - */ | |
| 60 | - function ZipFolder($sZipFileName, $exportCode = null) { | |
| 61 | - $this->oKTConfig =& KTConfig::getSingleton(); | |
| 62 | - $this->oStorage =& KTStorageManagerUtil::getSingleton(); | |
| 63 | - | |
| 64 | - $this->sOutputEncoding = $this->oKTConfig->get('export/encoding', 'UTF-8'); | |
| 65 | - | |
| 66 | - $this->sPattern = "[\*|\%|\\\|\/|\<|\>|\+|\:|\?|\||\'|\"]"; | |
| 67 | - $this->sFolderPattern = "[\*|\%|\<|\>|\+|\:|\?|\||\'|\"]"; | |
| 68 | - | |
| 69 | - // If the export code exists then a temp zip directory has already been created | |
| 70 | - if(!empty($exportCode)){ | |
| 71 | - $aData = KTUtil::arrayGet($_SESSION['zipcompression'], $exportCode); | |
| 72 | - | |
| 73 | - if(!empty($aData)){ | |
| 74 | - $sTmpPath = $aData['dir']; | |
| 75 | - } | |
| 76 | - }else { | |
| 77 | - $sBasedir = $this->oKTConfig->get("urls/tmpDirectory"); | |
| 78 | - $sTmpPath = tempnam($sBasedir, 'kt_compress_zip'); | |
| 79 | - | |
| 80 | - unlink($sTmpPath); | |
| 81 | - mkdir($sTmpPath, 0755); | |
| 82 | - } | |
| 83 | - | |
| 84 | - // Hard coding the zip file name. | |
| 85 | - // It normally uses the folder name but if there are special characters in the name then it doesn't download properly. | |
| 86 | - $sZipFileName = 'kt_zip'; | |
| 87 | - | |
| 88 | - $this->sTmpPath = $sTmpPath; | |
| 89 | - $this->sZipFileName = $sZipFileName; | |
| 90 | - $this->aPaths = array(); | |
| 91 | - | |
| 92 | - $aReplace = array( | |
| 93 | - "[" => "[[]", | |
| 94 | - " " => "[ ]", | |
| 95 | - "*" => "[*]", | |
| 96 | - "?" => "[?]", | |
| 97 | - ); | |
| 98 | - | |
| 99 | - $this->aReplaceKeys = array_keys($aReplace); | |
| 100 | - $this->aReplaceValues = array_values($aReplace); | |
| 101 | - } | |
| 102 | - | |
| 103 | - /** | |
| 104 | - * Return the full path | |
| 105 | - * | |
| 106 | - * @param mixed $oFolderOrDocument May be a Folder or Document | |
| 107 | - */ | |
| 108 | - function getFullFolderPath($oFolder) | |
| 109 | - { | |
| 110 | - static $sRootFolder = null; | |
| 111 | - | |
| 112 | - if (is_null($sRootFolder)) | |
| 113 | - { | |
| 114 | - $oRootFolder = Folder::get(1); | |
| 115 | - $sRootFolder = $oRootFolder->getName(); | |
| 116 | - } | |
| 117 | - | |
| 118 | - $sFullPath = $sRootFolder . '/'; | |
| 119 | - $sFullPath .= $oFolder->getFullPath(); | |
| 120 | - | |
| 121 | - | |
| 122 | - if (substr($sFullPath,-1) == '/') $sFullPath = substr($sFullPath,0,-1); | |
| 123 | - return $sFullPath; | |
| 124 | - } | |
| 125 | - | |
| 126 | - | |
| 127 | - /** | |
| 128 | - * Add a document to the zip file | |
| 129 | - */ | |
| 130 | - function addDocumentToZip($oDocument, $oFolder = null) { | |
| 131 | - if(empty($oFolder)){ | |
| 132 | - $oFolder = Folder::get($oDocument->getFolderID()); | |
| 133 | - } | |
| 134 | - | |
| 135 | - $sDocPath = $this->getFullFolderPath($oFolder); | |
| 136 | - $sDocPath = preg_replace($this->sFolderPattern, '-', $sDocPath); | |
| 137 | - $sDocPath = $this->_convertEncoding($sDocPath, true); | |
| 138 | - | |
| 139 | - | |
| 140 | - $sDocName = $oDocument->getFileName(); | |
| 141 | - $sDocName = preg_replace($this->sPattern, '-', $sDocName); | |
| 142 | - $sDocName = $this->_convertEncoding($sDocName, true); | |
| 143 | - | |
| 144 | - $sParentFolder = $this->sTmpPath.'/'.$sDocPath; | |
| 145 | - $newDir = $this->sTmpPath; | |
| 146 | - | |
| 147 | - $aFullPath = split('/', $sDocPath); | |
| 148 | - foreach ($aFullPath as $dirPart) { | |
| 149 | - $newDir = sprintf("%s/%s", $newDir, $dirPart); | |
| 150 | - if (!file_exists($newDir)) { | |
| 151 | - mkdir($newDir, 0700); | |
| 152 | - } | |
| 153 | - } | |
| 154 | - | |
| 155 | - $sOrigFile = $this->oStorage->temporaryFile($oDocument); | |
| 156 | - $sFilename = $sParentFolder.'/'.$sDocName; | |
| 157 | - copy($sOrigFile, $sFilename); | |
| 158 | - | |
| 159 | - $this->aPaths[] = $sDocPath.'/'.$sDocName; | |
| 160 | - return true; | |
| 161 | - } | |
| 162 | - | |
| 163 | - /** | |
| 164 | - * Add a folder to the zip file | |
| 165 | - */ | |
| 166 | - function addFolderToZip($oFolder) { | |
| 167 | - $sFolderPath = $this->getFullFolderPath($oFolder) .'/'; | |
| 168 | - $sFolderPath = preg_replace($this->sFolderPattern, '-', $sFolderPath); | |
| 169 | - $sFolderPath = $this->_convertEncoding($sFolderPath, true); | |
| 170 | - | |
| 171 | - $newDir = $this->sTmpPath; | |
| 172 | - | |
| 173 | - $aFullPath = split('/', $sFolderPath); | |
| 174 | - foreach ($aFullPath as $dirPart) { | |
| 175 | - $newDir = sprintf("%s/%s", $newDir, $dirPart); | |
| 176 | - if (!file_exists($newDir)) { | |
| 177 | - mkdir($newDir, 0700); | |
| 178 | - } | |
| 179 | - } | |
| 180 | - | |
| 181 | - $this->aPaths[] = $sFolderPath; | |
| 182 | - return true; | |
| 183 | - } | |
| 184 | - | |
| 185 | - /** | |
| 186 | - * Zip the temp folder | |
| 187 | - */ | |
| 188 | - function createZipFile($bEchoStatus = FALSE) { | |
| 189 | - if(empty($this->aPaths)){ | |
| 190 | - return PEAR::raiseError(_kt("No folders or documents found to compress")); | |
| 191 | - } | |
| 192 | - | |
| 193 | - // Set environment language to output character encoding | |
| 194 | - $loc = $this->sOutputEncoding; | |
| 195 | - putenv("LANG=$loc"); | |
| 196 | - putenv("LANGUAGE=$loc"); | |
| 197 | - $loc = setlocale(LC_ALL, $loc); | |
| 198 | - | |
| 199 | - | |
| 200 | - | |
| 201 | - $sManifest = sprintf("%s/%s", $this->sTmpPath, "MANIFEST"); | |
| 202 | - file_put_contents($sManifest, join("\n", $this->aPaths)); | |
| 203 | - $sZipFile = sprintf("%s/%s.zip", $this->sTmpPath, $this->sZipFileName); | |
| 204 | - $sZipFile = str_replace('<', '', str_replace('</', '', str_replace('>', '', $sZipFile))); | |
| 205 | - $sZipCommand = KTUtil::findCommand("export/zip", "zip"); | |
| 206 | - $aCmd = array($sZipCommand, "-r", $sZipFile, ".", "-i@MANIFEST"); | |
| 207 | - $sOldPath = getcwd(); | |
| 208 | - chdir($this->sTmpPath); | |
| 209 | - | |
| 210 | - // Note that the popen means that pexec will return a file descriptor | |
| 211 | - $aOptions = array('popen' => 'r'); | |
| 212 | - $fh = KTUtil::pexec($aCmd, $aOptions); | |
| 213 | - | |
| 214 | - if($bEchoStatus){ | |
| 215 | - $last_beat = time(); | |
| 216 | - while(!feof($fh)) { | |
| 217 | - if ($i % 1000 == 0) { | |
| 218 | - $this_beat = time(); | |
| 219 | - if ($last_beat + 1 < $this_beat) { | |
| 220 | - $last_beat = $this_beat; | |
| 221 | - print " "; | |
| 222 | - } | |
| 223 | - } | |
| 224 | - $contents = fread($fh, 4096); | |
| 225 | - if ($contents) { | |
| 226 | - print nl2br($this->_convertEncoding($contents, false)); | |
| 227 | - } | |
| 228 | - $i++; | |
| 229 | - } | |
| 230 | - } | |
| 231 | - pclose($fh); | |
| 232 | - | |
| 233 | - // Save the zip file and path into session | |
| 234 | - $_SESSION['zipcompression'] = KTUtil::arrayGet($_SESSION, 'zipcompression', array()); | |
| 235 | - $sExportCode = KTUtil::randomString(); | |
| 236 | - $_SESSION['zipcompression'][$sExportCode] = array( | |
| 237 | - 'file' => $sZipFile, | |
| 238 | - 'dir' => $this->sTmpPath, | |
| 239 | - ); | |
| 240 | - $_SESSION['zipcompression']['exportcode'] = $sExportCode; | |
| 241 | - | |
| 242 | - $this->sZipFile = $sZipFile; | |
| 243 | - return $sExportCode; | |
| 244 | - } | |
| 245 | - | |
| 246 | - /** | |
| 247 | - * Download the zip file | |
| 248 | - */ | |
| 249 | - function downloadZipFile($exportCode = NULL) { | |
| 250 | - if(!(isset($exportCode) && !empty($exportCode))) { | |
| 251 | - $exportCode = KTUtil::arrayGet($_SESSION['zipcompression'], 'exportcode'); | |
| 252 | - } | |
| 253 | - | |
| 254 | - $aData = KTUtil::arrayGet($_SESSION['zipcompression'], $exportCode); | |
| 255 | - | |
| 256 | - if(!empty($aData)){ | |
| 257 | - $sZipFile = $aData['file']; | |
| 258 | - $sTmpPath = $aData['dir']; | |
| 259 | - }else{ | |
| 260 | - $sZipFile = $this->sZipFile; | |
| 261 | - $sTmpPath = $this->sTmpPath; | |
| 262 | - } | |
| 263 | - | |
| 264 | - if (!file_exists($sZipFile)) { | |
| 265 | - return PEAR::raiseError(_kt('The ZIP file can only be downloaded once - if you cancel the download, you will need to reload the page.')); | |
| 266 | - } | |
| 267 | - | |
| 268 | - header("Content-Type: application/zip; charset=utf-8"); | |
| 269 | - header("Content-Length: ". filesize($sZipFile)); | |
| 270 | - header("Content-Disposition: attachment; filename=\"" . $this->sZipFileName . ".zip" . "\""); | |
| 271 | - header("Expires: Mon, 26 Jul 1997 05:00:00 GMT"); | |
| 272 | - header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT"); | |
| 273 | - header("Cache-Control: must-revalidate"); | |
| 274 | - readfile($sZipFile); | |
| 275 | - KTUtil::deleteDirectory($sTmpPath); | |
| 276 | - return true; | |
| 277 | - } | |
| 278 | - | |
| 279 | - /** | |
| 280 | - * Check that iconv exists and that the selected encoding is supported. | |
| 281 | - */ | |
| 282 | - function checkConvertEncoding() { | |
| 283 | - if(!function_exists("iconv")) { | |
| 284 | - return PEAR::raiseError(_kt('IConv PHP extension not installed. The zip file compression could not handle output filename encoding conversion !')); | |
| 285 | - } | |
| 286 | - $oKTConfig = $this->oKTConfig; | |
| 287 | - $this->sOutputEncoding = $oKTConfig->get('export/encoding', 'UTF-8'); | |
| 288 | - | |
| 289 | - // Test the specified encoding | |
| 290 | - if(iconv("UTF-8", $this->sOutputEncoding, "") === FALSE) { | |
| 291 | - return PEAR::raiseError(_kt('Specified output encoding for the zip files compression does not exists !')); | |
| 292 | - } | |
| 293 | - return true; | |
| 294 | - } | |
| 295 | - | |
| 296 | - function _convertEncoding($sMystring, $bEncode) { | |
| 297 | - if (strcasecmp($this->sOutputEncoding, "UTF-8") === 0) { | |
| 298 | - return $sMystring; | |
| 299 | - } | |
| 300 | - if ($bEncode) { | |
| 301 | - return iconv("UTF-8", $this->sOutputEncoding, $sMystring); | |
| 302 | - } else { | |
| 303 | - return iconv($this->sOutputEncoding, "UTF-8", $sMystring); | |
| 304 | - } | |
| 305 | - } | |
| 306 | -} | |
| 1 | +<?php | |
| 2 | +/** | |
| 3 | + * $Id: | |
| 4 | + * | |
| 5 | + * KnowledgeTree Community Edition | |
| 6 | + * Document Management Made Simple | |
| 7 | + * Copyright (C) 2008 KnowledgeTree Inc. | |
| 8 | + * Portions copyright The Jam Warehouse Software (Pty) Limited | |
| 9 | + * | |
| 10 | + * This program is free software; you can redistribute it and/or modify it under | |
| 11 | + * the terms of the GNU General Public License version 3 as published by the | |
| 12 | + * Free Software Foundation. | |
| 13 | + * | |
| 14 | + * This program is distributed in the hope that it will be useful, but WITHOUT | |
| 15 | + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS | |
| 16 | + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more | |
| 17 | + * details. | |
| 18 | + * | |
| 19 | + * You should have received a copy of the GNU General Public License | |
| 20 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. | |
| 21 | + * | |
| 22 | + * You can contact KnowledgeTree Inc., PO Box 7775 #87847, San Francisco, | |
| 23 | + * California 94120-7775, or email info@knowledgetree.com. | |
| 24 | + * | |
| 25 | + * The interactive user interfaces in modified source and object code versions | |
| 26 | + * of this program must display Appropriate Legal Notices, as required under | |
| 27 | + * Section 5 of the GNU General Public License version 3. | |
| 28 | + * | |
| 29 | + * In accordance with Section 7(b) of the GNU General Public License version 3, | |
| 30 | + * these Appropriate Legal Notices must retain the display of the "Powered by | |
| 31 | + * KnowledgeTree" logo and retain the original copyright notice. If the display of the | |
| 32 | + * logo is not reasonably feasible for technical reasons, the Appropriate Legal Notices | |
| 33 | + * must display the words "Powered by KnowledgeTree" and retain the original | |
| 34 | + * copyright notice. | |
| 35 | + * Contributor( s): ______________________________________ | |
| 36 | + * | |
| 37 | + */ | |
| 38 | + | |
| 39 | +/** | |
| 40 | +* Class to create and download a zip file | |
| 41 | +*/ | |
| 42 | +class ZipFolder { | |
| 43 | + | |
| 44 | + var $sTmpPath = ''; | |
| 45 | + var $sZipFileName = ''; | |
| 46 | + var $sZipFile = ''; | |
| 47 | + var $sPattern = ''; | |
| 48 | + var $sFolderPattern = ''; | |
| 49 | + var $aPaths = array(); | |
| 50 | + var $aReplaceKeys = array(); | |
| 51 | + var $aReplaceValues = array(); | |
| 52 | + var $sOutputEncoding = 'UTF-8'; | |
| 53 | + | |
| 54 | + /** | |
| 55 | + * Constructor | |
| 56 | + * | |
| 57 | + * @param string $sZipFileName The name of the zip file - gets ignored at the moment. | |
| 58 | + * @param string $exportCode The code to use if a zip file has already been created. | |
| 59 | + */ | |
| 60 | + function ZipFolder($sZipFileName, $exportCode = null) { | |
| 61 | + $this->oKTConfig =& KTConfig::getSingleton(); | |
| 62 | + $this->oStorage =& KTStorageManagerUtil::getSingleton(); | |
| 63 | + | |
| 64 | + $this->sOutputEncoding = $this->oKTConfig->get('export/encoding', 'UTF-8'); | |
| 65 | + | |
| 66 | + $this->sPattern = "[\*|\%|\\\|\/|\<|\>|\+|\:|\?|\||\'|\"]"; | |
| 67 | + $this->sFolderPattern = "[\*|\%|\<|\>|\+|\:|\?|\||\'|\"]"; | |
| 68 | + | |
| 69 | + // If the export code exists then a temp zip directory has already been created | |
| 70 | + if(!empty($exportCode)){ | |
| 71 | + $aData = KTUtil::arrayGet($_SESSION['zipcompression'], $exportCode); | |
| 72 | + | |
| 73 | + if(!empty($aData)){ | |
| 74 | + $sTmpPath = $aData['dir']; | |
| 75 | + } | |
| 76 | + }else { | |
| 77 | + $sBasedir = $this->oKTConfig->get("urls/tmpDirectory"); | |
| 78 | + $sTmpPath = tempnam($sBasedir, 'kt_compress_zip'); | |
| 79 | + | |
| 80 | + unlink($sTmpPath); | |
| 81 | + mkdir($sTmpPath, 0755); | |
| 82 | + } | |
| 83 | + | |
| 84 | + // Hard coding the zip file name. | |
| 85 | + // It normally uses the folder name but if there are special characters in the name then it doesn't download properly. | |
| 86 | + $sZipFileName = 'kt_zip'; | |
| 87 | + | |
| 88 | + $this->sTmpPath = $sTmpPath; | |
| 89 | + $this->sZipFileName = $sZipFileName; | |
| 90 | + $this->aPaths = array(); | |
| 91 | + | |
| 92 | + $aReplace = array( | |
| 93 | + "[" => "[[]", | |
| 94 | + " " => "[ ]", | |
| 95 | + "*" => "[*]", | |
| 96 | + "?" => "[?]", | |
| 97 | + ); | |
| 98 | + | |
| 99 | + $this->aReplaceKeys = array_keys($aReplace); | |
| 100 | + $this->aReplaceValues = array_values($aReplace); | |
| 101 | + } | |
| 102 | + | |
| 103 | + /** | |
| 104 | + * Return the full path | |
| 105 | + * | |
| 106 | + * @param mixed $oFolderOrDocument May be a Folder or Document | |
| 107 | + */ | |
| 108 | + function getFullFolderPath($oFolder) | |
| 109 | + { | |
| 110 | + static $sRootFolder = null; | |
| 111 | + | |
| 112 | + if (is_null($sRootFolder)) | |
| 113 | + { | |
| 114 | + $oRootFolder = Folder::get(1); | |
| 115 | + $sRootFolder = $oRootFolder->getName(); | |
| 116 | + } | |
| 117 | + | |
| 118 | + $sFullPath = $sRootFolder . '/'; | |
| 119 | + $sFullPath .= $oFolder->getFullPath(); | |
| 120 | + | |
| 121 | + | |
| 122 | + if (substr($sFullPath,-1) == '/') $sFullPath = substr($sFullPath,0,-1); | |
| 123 | + return $sFullPath; | |
| 124 | + } | |
| 125 | + | |
| 126 | + | |
| 127 | + /** | |
| 128 | + * Add a document to the zip file | |
| 129 | + */ | |
| 130 | + function addDocumentToZip($oDocument, $oFolder = null) { | |
| 131 | + if(empty($oFolder)){ | |
| 132 | + $oFolder = Folder::get($oDocument->getFolderID()); | |
| 133 | + } | |
| 134 | + | |
| 135 | + $sDocPath = $this->getFullFolderPath($oFolder); | |
| 136 | + $sDocPath = preg_replace($this->sFolderPattern, '-', $sDocPath); | |
| 137 | + $sDocPath = $this->_convertEncoding($sDocPath, true); | |
| 138 | + | |
| 139 | + | |
| 140 | + $sDocName = $oDocument->getFileName(); | |
| 141 | + $sDocName = preg_replace($this->sPattern, '-', $sDocName); | |
| 142 | + $sDocName = $this->_convertEncoding($sDocName, true); | |
| 143 | + | |
| 144 | + $sParentFolder = $this->sTmpPath.'/'.$sDocPath; | |
| 145 | + $newDir = $this->sTmpPath; | |
| 146 | + | |
| 147 | + $aFullPath = split('/', $sDocPath); | |
| 148 | + foreach ($aFullPath as $dirPart) { | |
| 149 | + $newDir = sprintf("%s/%s", $newDir, $dirPart); | |
| 150 | + if (!file_exists($newDir)) { | |
| 151 | + mkdir($newDir, 0700); | |
| 152 | + } | |
| 153 | + } | |
| 154 | + | |
| 155 | + $sOrigFile = $this->oStorage->temporaryFile($oDocument); | |
| 156 | + $sFilename = $sParentFolder.'/'.$sDocName; | |
| 157 | + copy($sOrigFile, $sFilename); | |
| 158 | + | |
| 159 | + $this->aPaths[] = $sDocPath.'/'.$sDocName; | |
| 160 | + return true; | |
| 161 | + } | |
| 162 | + | |
| 163 | + /** | |
| 164 | + * Add a folder to the zip file | |
| 165 | + */ | |
| 166 | + function addFolderToZip($oFolder) { | |
| 167 | + $sFolderPath = $this->getFullFolderPath($oFolder) .'/'; | |
| 168 | + $sFolderPath = preg_replace($this->sFolderPattern, '-', $sFolderPath); | |
| 169 | + $sFolderPath = $this->_convertEncoding($sFolderPath, true); | |
| 170 | + | |
| 171 | + $newDir = $this->sTmpPath; | |
| 172 | + | |
| 173 | + $aFullPath = split('/', $sFolderPath); | |
| 174 | + foreach ($aFullPath as $dirPart) { | |
| 175 | + $newDir = sprintf("%s/%s", $newDir, $dirPart); | |
| 176 | + if (!file_exists($newDir)) { | |
| 177 | + mkdir($newDir, 0700); | |
| 178 | + } | |
| 179 | + } | |
| 180 | + | |
| 181 | + $this->aPaths[] = $sFolderPath; | |
| 182 | + return true; | |
| 183 | + } | |
| 184 | + | |
| 185 | + /** | |
| 186 | + * Zip the temp folder | |
| 187 | + */ | |
| 188 | + function createZipFile($bEchoStatus = FALSE) { | |
| 189 | + if(empty($this->aPaths)){ | |
| 190 | + return PEAR::raiseError(_kt("No folders or documents found to compress")); | |
| 191 | + } | |
| 192 | + | |
| 193 | + // Set environment language to output character encoding | |
| 194 | + $loc = $this->sOutputEncoding; | |
| 195 | + putenv("LANG=$loc"); | |
| 196 | + putenv("LANGUAGE=$loc"); | |
| 197 | + $loc = setlocale(LC_ALL, $loc); | |
| 198 | + | |
| 199 | + | |
| 200 | + | |
| 201 | + $sManifest = sprintf("%s/%s", $this->sTmpPath, "MANIFEST"); | |
| 202 | + file_put_contents($sManifest, join("\n", $this->aPaths)); | |
| 203 | + $sZipFile = sprintf("%s/%s.zip", $this->sTmpPath, $this->sZipFileName); | |
| 204 | + $sZipFile = str_replace('<', '', str_replace('</', '', str_replace('>', '', $sZipFile))); | |
| 205 | + $sZipCommand = KTUtil::findCommand("export/zip", "zip"); | |
| 206 | + $aCmd = array($sZipCommand, "-r", $sZipFile, ".", "-i@MANIFEST"); | |
| 207 | + $sOldPath = getcwd(); | |
| 208 | + chdir($this->sTmpPath); | |
| 209 | + | |
| 210 | + // Note that the popen means that pexec will return a file descriptor | |
| 211 | + $aOptions = array('popen' => 'r'); | |
| 212 | + $fh = KTUtil::pexec($aCmd, $aOptions); | |
| 213 | + | |
| 214 | + if($bEchoStatus){ | |
| 215 | + $last_beat = time(); | |
| 216 | + while(!feof($fh)) { | |
| 217 | + if ($i % 1000 == 0) { | |
| 218 | + $this_beat = time(); | |
| 219 | + if ($last_beat + 1 < $this_beat) { | |
| 220 | + $last_beat = $this_beat; | |
| 221 | + print " "; | |
| 222 | + } | |
| 223 | + } | |
| 224 | + $contents = fread($fh, 4096); | |
| 225 | + if ($contents) { | |
| 226 | + print nl2br($this->_convertEncoding($contents, false)); | |
| 227 | + } | |
| 228 | + $i++; | |
| 229 | + } | |
| 230 | + } | |
| 231 | + pclose($fh); | |
| 232 | + | |
| 233 | + // Save the zip file and path into session | |
| 234 | + $_SESSION['zipcompression'] = KTUtil::arrayGet($_SESSION, 'zipcompression', array()); | |
| 235 | + $sExportCode = KTUtil::randomString(); | |
| 236 | + $_SESSION['zipcompression'][$sExportCode] = array( | |
| 237 | + 'file' => $sZipFile, | |
| 238 | + 'dir' => $this->sTmpPath, | |
| 239 | + ); | |
| 240 | + $_SESSION['zipcompression']['exportcode'] = $sExportCode; | |
| 241 | + | |
| 242 | + $this->sZipFile = $sZipFile; | |
| 243 | + return $sExportCode; | |
| 244 | + } | |
| 245 | + | |
| 246 | + /** | |
| 247 | + * Download the zip file | |
| 248 | + */ | |
| 249 | + function downloadZipFile($exportCode = NULL) { | |
| 250 | + if(!(isset($exportCode) && !empty($exportCode))) { | |
| 251 | + $exportCode = KTUtil::arrayGet($_SESSION['zipcompression'], 'exportcode'); | |
| 252 | + } | |
| 253 | + | |
| 254 | + $aData = KTUtil::arrayGet($_SESSION['zipcompression'], $exportCode); | |
| 255 | + | |
| 256 | + if(!empty($aData)){ | |
| 257 | + $sZipFile = $aData['file']; | |
| 258 | + $sTmpPath = $aData['dir']; | |
| 259 | + }else{ | |
| 260 | + $sZipFile = $this->sZipFile; | |
| 261 | + $sTmpPath = $this->sTmpPath; | |
| 262 | + } | |
| 263 | + | |
| 264 | + if (!file_exists($sZipFile)) { | |
| 265 | + return PEAR::raiseError(_kt('The ZIP file can only be downloaded once - if you cancel the download, you will need to reload the page.')); | |
| 266 | + } | |
| 267 | + | |
| 268 | + $mimeType = 'application/zip; charset=utf-8;'; | |
| 269 | + $fileSize = filesize($sZipFile); | |
| 270 | + $fileName = $this->sZipFileName . '.zip'; | |
| 271 | + | |
| 272 | + KTUtil::download($sZipFile, $mimeType, $fileSize, $fileName); | |
| 273 | + KTUtil::deleteDirectory($sTmpPath); | |
| 274 | + return true; | |
| 275 | + } | |
| 276 | + | |
| 277 | + /** | |
| 278 | + * Check that iconv exists and that the selected encoding is supported. | |
| 279 | + */ | |
| 280 | + function checkConvertEncoding() { | |
| 281 | + if(!function_exists("iconv")) { | |
| 282 | + return PEAR::raiseError(_kt('IConv PHP extension not installed. The zip file compression could not handle output filename encoding conversion !')); | |
| 283 | + } | |
| 284 | + $oKTConfig = $this->oKTConfig; | |
| 285 | + $this->sOutputEncoding = $oKTConfig->get('export/encoding', 'UTF-8'); | |
| 286 | + | |
| 287 | + // Test the specified encoding | |
| 288 | + if(iconv("UTF-8", $this->sOutputEncoding, "") === FALSE) { | |
| 289 | + return PEAR::raiseError(_kt('Specified output encoding for the zip files compression does not exists !')); | |
| 290 | + } | |
| 291 | + return true; | |
| 292 | + } | |
| 293 | + | |
| 294 | + function _convertEncoding($sMystring, $bEncode) { | |
| 295 | + if (strcasecmp($this->sOutputEncoding, "UTF-8") === 0) { | |
| 296 | + return $sMystring; | |
| 297 | + } | |
| 298 | + if ($bEncode) { | |
| 299 | + return iconv("UTF-8", $this->sOutputEncoding, $sMystring); | |
| 300 | + } else { | |
| 301 | + return iconv($this->sOutputEncoding, "UTF-8", $sMystring); | |
| 302 | + } | |
| 303 | + } | |
| 304 | +} | |
| 307 | 305 | ?> |
| 308 | 306 | \ No newline at end of file | ... | ... |
lib/storage/ondiskhashedstoragemanager.inc.php
| ... | ... | @@ -182,36 +182,27 @@ class KTOnDiskHashedStorageManager extends KTStorageManager { |
| 182 | 182 | } |
| 183 | 183 | |
| 184 | 184 | function download($oDocument, $bIsCheckout = false) { |
| 185 | - //get the path to the document on the server | |
| 186 | - $oConfig =& KTConfig::getSingleton(); | |
| 187 | - $sPath = sprintf("%s/%s", $oConfig->get('urls/documentRoot'), $this->getPath($oDocument)); | |
| 188 | - $mimetype = KTMime::getMimeTypeName($oDocument->getMimeTypeID()); | |
| 189 | - | |
| 190 | - if ($bIsCheckout && $oConfig->get('ui/fakeMimetype' ,false)) { | |
| 191 | - $mimetype = 'application/x-download'; | |
| 192 | - // note this does not work for "image" types in some browsers | |
| 193 | - // go web. | |
| 194 | - } | |
| 195 | - | |
| 196 | - if (file_exists($sPath)) { | |
| 197 | - $sFileName = $oDocument->getFileName( ); | |
| 185 | + global $default; | |
| 198 | 186 | |
| 199 | - //set the correct headers | |
| 200 | - header("Content-Type: " . $mimetype); | |
| 201 | - header("Content-Length: ". $oDocument->getFileSize()); | |
| 202 | - header('Content-Disposition: attachment; filename="' . $sFileName . '"'); | |
| 203 | - header("Expires: Mon, 26 Jul 1997 05:00:00 GMT"); | |
| 204 | - header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT"); | |
| 205 | - // HTTP/1.1 | |
| 206 | - if ( strpos( strtoupper( $browser), 'MSIE') == false) { | |
| 207 | - header("Cache-Control: no-store, no-cache, must-revalidate"); | |
| 208 | - header("Cache-Control: post-check=0, pre-check=0", false); | |
| 187 | + //get the path to the document on the server | |
| 188 | + $docRoot = $default->documentRoot; | |
| 189 | + $path = $docRoot .'/'. $oDocument->getStoragePath(); | |
| 190 | + | |
| 191 | + // Ensure the file exists | |
| 192 | + if (file_exists($path)) { | |
| 193 | + // Get the mime type | |
| 194 | + $mimeId = $oDocument->getMimeTypeID(); | |
| 195 | + $mimetype = KTMime::getMimeTypeName($mimeId); | |
| 196 | + | |
| 197 | + if ($bIsCheckout && $default->fakeMimetype) { | |
| 198 | + // note this does not work for "image" types in some browsers | |
| 199 | + $mimetype = 'application/x-download'; | |
| 209 | 200 | } |
| 210 | - // HTTP/1.0 | |
| 211 | - //header("Pragma: no-cache"); // Don't send this header! It breaks IE. | |
| 212 | 201 | |
| 202 | + $sFileName = $oDocument->getFileName( ); | |
| 203 | + $iFileSize = $oDocument->getFileSize(); | |
| 213 | 204 | |
| 214 | - readfile($sPath); | |
| 205 | + KTUtil::download($path, $mimetype, $iFileSize, $sFileName); | |
| 215 | 206 | } else { |
| 216 | 207 | return false; |
| 217 | 208 | } |
| ... | ... | @@ -239,19 +230,14 @@ class KTOnDiskHashedStorageManager extends KTStorageManager { |
| 239 | 230 | $sPath = sprintf("%s/%s", $oConfig->get('urls/documentRoot'), $this->getPath($oContentVersion)); |
| 240 | 231 | $sVersion = sprintf("%d.%d", $oContentVersion->getMajorVersionNumber(), $oContentVersion->getMinorVersionNumber()); |
| 241 | 232 | if (file_exists($sPath)) { |
| 242 | - //set the correct headers | |
| 243 | - header("Content-Type: " . | |
| 244 | - KTMime::getMimeTypeName($oContentVersion->getMimeTypeID())); | |
| 245 | - header("Content-Length: ". filesize($sPath)); | |
| 246 | - // prefix the filename presented to the browser to preserve the document extension | |
| 247 | - header('Content-Disposition: attachment; filename="' . "$sVersion-" . $oContentVersion->getFileName() . '"'); | |
| 248 | - header("Expires: Mon, 26 Jul 1997 05:00:00 GMT"); | |
| 249 | - header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT"); | |
| 250 | - header("Cache-Control: must-revalidate"); | |
| 251 | - | |
| 252 | - readfile($sPath); | |
| 253 | - //$oFile = new KTFSFileLike($sPath); | |
| 254 | - //KTFileLikeUtil::send_contents($oFile); | |
| 233 | + // Get the mime type | |
| 234 | + $mimeId = $oContentVersion->getMimeTypeID(); | |
| 235 | + $mimetype = KTMime::getMimeTypeName($mimeId); | |
| 236 | + | |
| 237 | + $sFileName = $sVersion.'-'.$oContentVersion->getFileName( ); | |
| 238 | + $iFileSize = $oContentVersion->getFileSize(); | |
| 239 | + | |
| 240 | + KTUtil::download($sPath, $mimetype, $iFileSize, $sFileName); | |
| 255 | 241 | } else { |
| 256 | 242 | return false; |
| 257 | 243 | } | ... | ... |
lib/storage/ondiskpathstoragemanager.inc.php
| ... | ... | @@ -132,20 +132,12 @@ class KTOnDiskPathStorageManager extends KTStorageManager { |
| 132 | 132 | //get the path to the document on the server |
| 133 | 133 | $oConfig =& KTConfig::getSingleton(); |
| 134 | 134 | $sPath = sprintf("%s/%s", $oConfig->get('urls/documentRoot'), $this->getPath($oDocument)); |
| 135 | - if (file_exists($sPath)) { | |
| 136 | - //set the correct headers | |
| 137 | - header("Content-Type: " . | |
| 138 | - KTMime::getMimeTypeName($oDocument->getMimeTypeID())); | |
| 139 | - header("Content-Length: ". $oDocument->getFileSize()); | |
| 140 | - header("Content-Disposition: attachment; filename=\"" . $oDocument->getFileName() . "\""); | |
| 141 | - header("Expires: Mon, 26 Jul 1997 05:00:00 GMT"); | |
| 142 | - header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT"); | |
| 143 | - header("Cache-Control: must-revalidate"); | |
| 144 | - | |
| 145 | - readfile($sPath); | |
| 146 | - } else { | |
| 147 | - return false; | |
| 148 | - } | |
| 135 | + | |
| 136 | + $mimeType = KTMime::getMimeTypeName($oDocument->getMimeTypeID()); | |
| 137 | + $fileSize = $oDocument->getFileSize(); | |
| 138 | + $fileName = $oDocument->getFileName(); | |
| 139 | + | |
| 140 | + return KTUtil::download($sPath, $mimeType, $fileSize, $fileName); | |
| 149 | 141 | } |
| 150 | 142 | |
| 151 | 143 | function createFolder($oFolder) { |
| ... | ... | @@ -185,20 +177,12 @@ class KTOnDiskPathStorageManager extends KTStorageManager { |
| 185 | 177 | $oConfig =& KTConfig::getSingleton(); |
| 186 | 178 | $sPath = sprintf("%s/%s", $oConfig->get('urls/documentRoot'), $this->getPath($oContentVersion)); |
| 187 | 179 | $sVersion = sprintf("%d.%d", $oContentVersion->getMajorVersionNumber(), $oContentVersion->getMinorVersionNumber()); |
| 188 | - if (file_exists($sPath)) { | |
| 189 | - //set the correct headers | |
| 190 | - header("Content-Type: " . | |
| 191 | - KTMime::getMimeTypeName($oDocument->getMimeTypeID())); | |
| 192 | - header("Content-Length: ". filesize($sPath)); | |
| 193 | - // prefix the filename presented to the browser to preserve the document extension | |
| 194 | - header('Content-Disposition: attachment; filename="' . "$sVersion-" . $oDocument->getFileName() . '"'); | |
| 195 | - header("Expires: Mon, 26 Jul 1997 05:00:00 GMT"); | |
| 196 | - header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT"); | |
| 197 | - header("Cache-Control: must-revalidate"); | |
| 198 | - readfile($sPath); | |
| 199 | - } else { | |
| 200 | - return false; | |
| 201 | - } | |
| 180 | + | |
| 181 | + $mimeType = KTMime::getMimeTypeName($oContentVersion->getMimeTypeID()); | |
| 182 | + $fileSize = $oContentVersion->getFileSize(); | |
| 183 | + $fileName = $sVersion.'-'.$oContentVersion->getFileName(); | |
| 184 | + | |
| 185 | + return KTUtil::download($sPath, $mimeType, $fileSize, $fileName); | |
| 202 | 186 | } |
| 203 | 187 | |
| 204 | 188 | /** | ... | ... |
lib/util/ktutil.inc
| ... | ... | @@ -1245,6 +1245,36 @@ class KTUtil { |
| 1245 | 1245 | return $aBreadcrumbs; |
| 1246 | 1246 | } |
| 1247 | 1247 | |
| 1248 | + /** | |
| 1249 | + * Generates the correct headers for downloading a document | |
| 1250 | + */ | |
| 1251 | + function download($path, $mimeType, $fileSize, $fileName, $displayType = 'attachment') | |
| 1252 | + { | |
| 1253 | + if (file_exists($path)) { | |
| 1254 | + // IE7 adds underscores to filenames: fix | |
| 1255 | + $browser = $_SERVER['HTTP_USER_AGENT']; | |
| 1256 | + if ( strpos( strtoupper( $browser), 'MSIE 7') !== false) { | |
| 1257 | + $fileName = rawurlencode($fileName); | |
| 1258 | + } | |
| 1259 | + | |
| 1260 | + // Set the correct headers | |
| 1261 | + header("Content-Type: {$mimeType}"); | |
| 1262 | + header("Content-Length: {$fileSize}"); | |
| 1263 | + header("Content-Disposition: {$displayType}; filename=\"{$fileName}\""); | |
| 1264 | + header("Expires: Mon, 26 Jul 1997 05:00:00 GMT"); | |
| 1265 | + header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT"); | |
| 1266 | + | |
| 1267 | + // Document must be cached in order to open it | |
| 1268 | + header("Cache-Control: must-revalidate"); | |
| 1269 | + | |
| 1270 | + // Allows the file to be downloaded, otherwise it attempts the download as "action.php?..." | |
| 1271 | + header("Pragma: public"); | |
| 1272 | + | |
| 1273 | + readfile($path); | |
| 1274 | + }else { | |
| 1275 | + return false; | |
| 1276 | + } | |
| 1277 | + } | |
| 1248 | 1278 | } |
| 1249 | 1279 | |
| 1250 | 1280 | /** | ... | ... |
plugins/ktstandard/PDFGeneratorAction.php
| ... | ... | @@ -6,31 +6,31 @@ |
| 6 | 6 | * Document Management Made Simple |
| 7 | 7 | * Copyright (C) 2008 KnowledgeTree Inc. |
| 8 | 8 | * Portions copyright The Jam Warehouse Software (Pty) Limited |
| 9 | - * | |
| 9 | + * | |
| 10 | 10 | * This program is free software; you can redistribute it and/or modify it under |
| 11 | 11 | * the terms of the GNU General Public License version 3 as published by the |
| 12 | 12 | * Free Software Foundation. |
| 13 | - * | |
| 13 | + * | |
| 14 | 14 | * This program is distributed in the hope that it will be useful, but WITHOUT |
| 15 | 15 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS |
| 16 | 16 | * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more |
| 17 | 17 | * details. |
| 18 | - * | |
| 18 | + * | |
| 19 | 19 | * You should have received a copy of the GNU General Public License |
| 20 | 20 | * along with this program. If not, see <http://www.gnu.org/licenses/>. |
| 21 | - * | |
| 22 | - * You can contact KnowledgeTree Inc., PO Box 7775 #87847, San Francisco, | |
| 21 | + * | |
| 22 | + * You can contact KnowledgeTree Inc., PO Box 7775 #87847, San Francisco, | |
| 23 | 23 | * California 94120-7775, or email info@knowledgetree.com. |
| 24 | - * | |
| 24 | + * | |
| 25 | 25 | * The interactive user interfaces in modified source and object code versions |
| 26 | 26 | * of this program must display Appropriate Legal Notices, as required under |
| 27 | 27 | * Section 5 of the GNU General Public License version 3. |
| 28 | - * | |
| 28 | + * | |
| 29 | 29 | * In accordance with Section 7(b) of the GNU General Public License version 3, |
| 30 | 30 | * these Appropriate Legal Notices must retain the display of the "Powered by |
| 31 | - * KnowledgeTree" logo and retain the original copyright notice. If the display of the | |
| 31 | + * KnowledgeTree" logo and retain the original copyright notice. If the display of the | |
| 32 | 32 | * logo is not reasonably feasible for technical reasons, the Appropriate Legal Notices |
| 33 | - * must display the words "Powered by KnowledgeTree" and retain the original | |
| 33 | + * must display the words "Powered by KnowledgeTree" and retain the original | |
| 34 | 34 | * copyright notice. |
| 35 | 35 | * Contributor( s): ______________________________________ |
| 36 | 36 | * |
| ... | ... | @@ -52,8 +52,8 @@ class PDFGeneratorAction extends KTDocumentAction { |
| 52 | 52 | var $sDisplayName = 'Generate PDF'; |
| 53 | 53 | // Note: 'asc' below seems to be a catchall for plain text docs. |
| 54 | 54 | // 'htm' and 'html' should work but are not so have been removed for now. |
| 55 | - var $aAcceptedMimeTypes = array('doc', 'ods', 'odt', 'ott', 'txt', 'rtf', 'sxw', 'stw', | |
| 56 | - // 'html', 'htm', | |
| 55 | + var $aAcceptedMimeTypes = array('doc', 'ods', 'odt', 'ott', 'txt', 'rtf', 'sxw', 'stw', | |
| 56 | + // 'html', 'htm', | |
| 57 | 57 | 'xml' , 'pdb', 'psw', 'ods', 'ots', 'sxc', |
| 58 | 58 | 'stc', 'dif', 'dbf', 'xls', 'xlt', 'slk', 'csv', 'pxl', |
| 59 | 59 | 'odp', 'otp', 'sxi', 'sti', 'ppt', 'pot', 'sxd', 'odg', |
| ... | ... | @@ -126,7 +126,7 @@ class PDFGeneratorAction extends KTDocumentAction { |
| 126 | 126 | $this->do_pdfdownload(); |
| 127 | 127 | } |
| 128 | 128 | redirect(KTUtil::ktLink( 'action.php', 'ktstandard.pdf.generate', array( "fDocumentId" => $this->oDocument->getId() ) ) ); |
| 129 | - exit(0); | |
| 129 | + exit(0); | |
| 130 | 130 | } |
| 131 | 131 | |
| 132 | 132 | function do_main() { |
| ... | ... | @@ -171,7 +171,7 @@ class PDFGeneratorAction extends KTDocumentAction { |
| 171 | 171 | /** |
| 172 | 172 | * Method for downloading the document as a pdf. |
| 173 | 173 | * |
| 174 | - * @return true on success else false | |
| 174 | + * @return true on success else false | |
| 175 | 175 | */ |
| 176 | 176 | function do_pdfdownload() { |
| 177 | 177 | |
| ... | ... | @@ -184,7 +184,7 @@ class PDFGeneratorAction extends KTDocumentAction { |
| 184 | 184 | // Set the error messsage and redirect to view document |
| 185 | 185 | $this->addErrorMessage(_kt('An error occurred generating the PDF - please contact the system administrator. Python binary not found.')); |
| 186 | 186 | redirect(generateControllerLink('viewDocument',sprintf('fDocumentId=%d',$oDocument->getId()))); |
| 187 | - exit(0); | |
| 187 | + exit(0); | |
| 188 | 188 | } |
| 189 | 189 | |
| 190 | 190 | //get the actual path to the document on the server |
| ... | ... | @@ -199,7 +199,7 @@ class PDFGeneratorAction extends KTDocumentAction { |
| 199 | 199 | if (substr( PHP_OS, 0, 3) == 'WIN') { |
| 200 | 200 | |
| 201 | 201 | $cmd = "\"" . $cmdpath . "\" \"". KT_DIR . "/bin/openoffice/pdfgen.py\" \"" . $sPath . "\" \"" . $sTempFilename . "\""; |
| 202 | - $cmd = str_replace( '/','\\',$cmd); | |
| 202 | + $cmd = str_replace( '/','\\',$cmd); | |
| 203 | 203 | |
| 204 | 204 | // TODO: Check for more errors here |
| 205 | 205 | // SECURTIY: Ensure $sPath and $sTempFilename are safe or they could be used to excecute arbitrary commands! |
| ... | ... | @@ -222,30 +222,14 @@ class PDFGeneratorAction extends KTDocumentAction { |
| 222 | 222 | |
| 223 | 223 | } |
| 224 | 224 | |
| 225 | - // Check the tempfile exists and the python script did not return anything (which would indicate an error) | |
| 225 | + // Check the tempfile exists and the python script did not return anything (which would indicate an error) | |
| 226 | 226 | if (file_exists($sTempFilename) && $res == '') { |
| 227 | 227 | |
| 228 | - $sUrlEncodedFileName = substr($oDocument->getFileName(), 0, strrpos($oDocument->getFileName(), '.') ); | |
| 229 | - $browser = $_SERVER['HTTP_USER_AGENT']; | |
| 230 | - if ( strpos( strtoupper( $browser), 'MSIE') !== false) { | |
| 231 | - $sUrlEncodedFileName = rawurlencode($sUrlEncodedFileName); | |
| 232 | - } | |
| 233 | - // Set the correct headers | |
| 234 | - header("Content-Type: application/pdf"); | |
| 235 | - header("Content-Length: ". filesize($sTempFilename)); | |
| 236 | - header("Content-Disposition: attachment; filename=\"" . $sUrlEncodedFileName . ".pdf\""); | |
| 237 | - header("Expires: Mon, 26 Jul 1997 05:00:00 GMT"); | |
| 238 | - header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT"); | |
| 239 | - // HTTP/1.1 | |
| 240 | - header("Cache-Control: no-store, no-cache, must-revalidate"); | |
| 241 | - header("Cache-Control: post-check=0, pre-check=0", false); | |
| 242 | - | |
| 243 | - // HTTP/1.0 | |
| 244 | - // header("Pragma: no-cache"); // Don't send this header! It breaks IE. | |
| 245 | - | |
| 246 | - // Get a filelike object and send it to the browser | |
| 247 | - $oFile = new KTFSFileLike($sTempFilename); | |
| 248 | - KTFileLikeUtil::send_contents($oFile); | |
| 228 | + $mimetype = 'application/pdf'; | |
| 229 | + $size = filesize($sTempFilename); | |
| 230 | + $name = substr($oDocument->getFileName(), 0, strrpos($oDocument->getFileName(), '.') ) . '.pdf'; | |
| 231 | + KTUtil::download($sTempFilename, $mimetype, $size, $name); | |
| 232 | + | |
| 249 | 233 | // Remove the tempfile |
| 250 | 234 | unlink($sTempFilename); |
| 251 | 235 | |
| ... | ... | @@ -253,20 +237,20 @@ class PDFGeneratorAction extends KTDocumentAction { |
| 253 | 237 | $oDocumentTransaction = & new DocumentTransaction($oDocument, 'Document downloaded as PDF', 'ktcore.transactions.download', $aOptions); |
| 254 | 238 | $oDocumentTransaction->create(); |
| 255 | 239 | // Just stop here - the content has already been sent. |
| 256 | - exit(0); | |
| 240 | + exit(0); | |
| 257 | 241 | |
| 258 | 242 | } else { |
| 259 | 243 | // Set the error messsage and redirect to view document |
| 260 | 244 | $this->addErrorMessage(_kt('An error occurred generating the PDF - please contact the system administrator. ' . $res)); |
| 261 | 245 | redirect(generateControllerLink('viewDocument',sprintf('fDocumentId=%d',$oDocument->getId()))); |
| 262 | - exit(0); | |
| 246 | + exit(0); | |
| 263 | 247 | } |
| 264 | 248 | |
| 265 | 249 | } else { |
| 266 | 250 | // Set the error messsage and redirect to view document |
| 267 | 251 | $this->addErrorMessage(_kt('An error occurred generating the PDF - please contact the system administrator. The path to the document did not exist.')); |
| 268 | 252 | redirect(generateControllerLink('viewDocument',sprintf('fDocumentId=%d',$oDocument->getId()))); |
| 269 | - exit(0); | |
| 253 | + exit(0); | |
| 270 | 254 | } |
| 271 | 255 | |
| 272 | 256 | ... | ... |