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,31 +9,31 @@ | ||
| 9 | * Document Management Made Simple | 9 | * Document Management Made Simple |
| 10 | * Copyright (C) 2008 KnowledgeTree Inc. | 10 | * Copyright (C) 2008 KnowledgeTree Inc. |
| 11 | * Portions copyright The Jam Warehouse Software (Pty) Limited | 11 | * Portions copyright The Jam Warehouse Software (Pty) Limited |
| 12 | - * | 12 | + * |
| 13 | * This program is free software; you can redistribute it and/or modify it under | 13 | * This program is free software; you can redistribute it and/or modify it under |
| 14 | * the terms of the GNU General Public License version 3 as published by the | 14 | * the terms of the GNU General Public License version 3 as published by the |
| 15 | * Free Software Foundation. | 15 | * Free Software Foundation. |
| 16 | - * | 16 | + * |
| 17 | * This program is distributed in the hope that it will be useful, but WITHOUT | 17 | * This program is distributed in the hope that it will be useful, but WITHOUT |
| 18 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS | 18 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS |
| 19 | * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more | 19 | * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more |
| 20 | * details. | 20 | * details. |
| 21 | - * | 21 | + * |
| 22 | * You should have received a copy of the GNU General Public License | 22 | * You should have received a copy of the GNU General Public License |
| 23 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | 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 | * California 94120-7775, or email info@knowledgetree.com. | 26 | * California 94120-7775, or email info@knowledgetree.com. |
| 27 | - * | 27 | + * |
| 28 | * The interactive user interfaces in modified source and object code versions | 28 | * The interactive user interfaces in modified source and object code versions |
| 29 | * of this program must display Appropriate Legal Notices, as required under | 29 | * of this program must display Appropriate Legal Notices, as required under |
| 30 | * Section 5 of the GNU General Public License version 3. | 30 | * Section 5 of the GNU General Public License version 3. |
| 31 | - * | 31 | + * |
| 32 | * In accordance with Section 7(b) of the GNU General Public License version 3, | 32 | * In accordance with Section 7(b) of the GNU General Public License version 3, |
| 33 | * these Appropriate Legal Notices must retain the display of the "Powered by | 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 | * logo is not reasonably feasible for technical reasons, the Appropriate Legal Notices | 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 | * copyright notice. | 37 | * copyright notice. |
| 38 | * Contributor( s): ______________________________________ | 38 | * Contributor( s): ______________________________________ |
| 39 | */ | 39 | */ |
| @@ -56,25 +56,17 @@ class PhysicalDocumentManager { | @@ -56,25 +56,17 @@ class PhysicalDocumentManager { | ||
| 56 | * @todo investigate possible problem in MSIE 5.5 concerning Content-Disposition header | 56 | * @todo investigate possible problem in MSIE 5.5 concerning Content-Disposition header |
| 57 | */ | 57 | */ |
| 58 | function downloadPhysicalDocument($iDocumentID) { | 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,26 +77,17 @@ class PhysicalDocumentManager { | ||
| 85 | * @return int number of bytes read from file on success or false otherwise; | 77 | * @return int number of bytes read from file on success or false otherwise; |
| 86 | */ | 78 | */ |
| 87 | function downloadVersionedPhysicalDocument($iDocumentID, $sVersion) { | 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 | * Move a document to a new folder | 93 | * Move a document to a new folder |
| @@ -300,9 +283,9 @@ class PhysicalDocumentManager { | @@ -300,9 +283,9 @@ class PhysicalDocumentManager { | ||
| 300 | global $default; | 283 | global $default; |
| 301 | $iContentId = $oVersion->getContentVersionId(); | 284 | $iContentId = $oVersion->getContentVersionId(); |
| 302 | $oContentVersion = KTDocumentContentVersion::get($iContentId); | 285 | $oContentVersion = KTDocumentContentVersion::get($iContentId); |
| 303 | - | 286 | + |
| 304 | $sFullPath = $default->documentRoot.'/'.$oContentVersion->getStoragePath(); | 287 | $sFullPath = $default->documentRoot.'/'.$oContentVersion->getStoragePath(); |
| 305 | - | 288 | + |
| 306 | if (file_exists($sFullPath)) { | 289 | if (file_exists($sFullPath)) { |
| 307 | if(@unlink($sFullPath)){ | 290 | if(@unlink($sFullPath)){ |
| 308 | $default->log->info("PhysicalDocumentManager::deleteVersion unlinked $sFullPath"); | 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 | \ No newline at end of file | 306 | \ No newline at end of file |
lib/storage/ondiskhashedstoragemanager.inc.php
| @@ -182,36 +182,27 @@ class KTOnDiskHashedStorageManager extends KTStorageManager { | @@ -182,36 +182,27 @@ class KTOnDiskHashedStorageManager extends KTStorageManager { | ||
| 182 | } | 182 | } |
| 183 | 183 | ||
| 184 | function download($oDocument, $bIsCheckout = false) { | 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 | } else { | 206 | } else { |
| 216 | return false; | 207 | return false; |
| 217 | } | 208 | } |
| @@ -239,19 +230,14 @@ class KTOnDiskHashedStorageManager extends KTStorageManager { | @@ -239,19 +230,14 @@ class KTOnDiskHashedStorageManager extends KTStorageManager { | ||
| 239 | $sPath = sprintf("%s/%s", $oConfig->get('urls/documentRoot'), $this->getPath($oContentVersion)); | 230 | $sPath = sprintf("%s/%s", $oConfig->get('urls/documentRoot'), $this->getPath($oContentVersion)); |
| 240 | $sVersion = sprintf("%d.%d", $oContentVersion->getMajorVersionNumber(), $oContentVersion->getMinorVersionNumber()); | 231 | $sVersion = sprintf("%d.%d", $oContentVersion->getMajorVersionNumber(), $oContentVersion->getMinorVersionNumber()); |
| 241 | if (file_exists($sPath)) { | 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 | } else { | 241 | } else { |
| 256 | return false; | 242 | return false; |
| 257 | } | 243 | } |
lib/storage/ondiskpathstoragemanager.inc.php
| @@ -132,20 +132,12 @@ class KTOnDiskPathStorageManager extends KTStorageManager { | @@ -132,20 +132,12 @@ class KTOnDiskPathStorageManager extends KTStorageManager { | ||
| 132 | //get the path to the document on the server | 132 | //get the path to the document on the server |
| 133 | $oConfig =& KTConfig::getSingleton(); | 133 | $oConfig =& KTConfig::getSingleton(); |
| 134 | $sPath = sprintf("%s/%s", $oConfig->get('urls/documentRoot'), $this->getPath($oDocument)); | 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 | function createFolder($oFolder) { | 143 | function createFolder($oFolder) { |
| @@ -185,20 +177,12 @@ class KTOnDiskPathStorageManager extends KTStorageManager { | @@ -185,20 +177,12 @@ class KTOnDiskPathStorageManager extends KTStorageManager { | ||
| 185 | $oConfig =& KTConfig::getSingleton(); | 177 | $oConfig =& KTConfig::getSingleton(); |
| 186 | $sPath = sprintf("%s/%s", $oConfig->get('urls/documentRoot'), $this->getPath($oContentVersion)); | 178 | $sPath = sprintf("%s/%s", $oConfig->get('urls/documentRoot'), $this->getPath($oContentVersion)); |
| 187 | $sVersion = sprintf("%d.%d", $oContentVersion->getMajorVersionNumber(), $oContentVersion->getMinorVersionNumber()); | 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,6 +1245,36 @@ class KTUtil { | ||
| 1245 | return $aBreadcrumbs; | 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,31 +6,31 @@ | ||
| 6 | * Document Management Made Simple | 6 | * Document Management Made Simple |
| 7 | * Copyright (C) 2008 KnowledgeTree Inc. | 7 | * Copyright (C) 2008 KnowledgeTree Inc. |
| 8 | * Portions copyright The Jam Warehouse Software (Pty) Limited | 8 | * Portions copyright The Jam Warehouse Software (Pty) Limited |
| 9 | - * | 9 | + * |
| 10 | * This program is free software; you can redistribute it and/or modify it under | 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 | 11 | * the terms of the GNU General Public License version 3 as published by the |
| 12 | * Free Software Foundation. | 12 | * Free Software Foundation. |
| 13 | - * | 13 | + * |
| 14 | * This program is distributed in the hope that it will be useful, but WITHOUT | 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 | 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 | 16 | * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more |
| 17 | * details. | 17 | * details. |
| 18 | - * | 18 | + * |
| 19 | * You should have received a copy of the GNU General Public License | 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/>. | 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 | * California 94120-7775, or email info@knowledgetree.com. | 23 | * California 94120-7775, or email info@knowledgetree.com. |
| 24 | - * | 24 | + * |
| 25 | * The interactive user interfaces in modified source and object code versions | 25 | * The interactive user interfaces in modified source and object code versions |
| 26 | * of this program must display Appropriate Legal Notices, as required under | 26 | * of this program must display Appropriate Legal Notices, as required under |
| 27 | * Section 5 of the GNU General Public License version 3. | 27 | * Section 5 of the GNU General Public License version 3. |
| 28 | - * | 28 | + * |
| 29 | * In accordance with Section 7(b) of the GNU General Public License version 3, | 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 | 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 | * logo is not reasonably feasible for technical reasons, the Appropriate Legal Notices | 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 | * copyright notice. | 34 | * copyright notice. |
| 35 | * Contributor( s): ______________________________________ | 35 | * Contributor( s): ______________________________________ |
| 36 | * | 36 | * |
| @@ -52,8 +52,8 @@ class PDFGeneratorAction extends KTDocumentAction { | @@ -52,8 +52,8 @@ class PDFGeneratorAction extends KTDocumentAction { | ||
| 52 | var $sDisplayName = 'Generate PDF'; | 52 | var $sDisplayName = 'Generate PDF'; |
| 53 | // Note: 'asc' below seems to be a catchall for plain text docs. | 53 | // Note: 'asc' below seems to be a catchall for plain text docs. |
| 54 | // 'htm' and 'html' should work but are not so have been removed for now. | 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 | 'xml' , 'pdb', 'psw', 'ods', 'ots', 'sxc', | 57 | 'xml' , 'pdb', 'psw', 'ods', 'ots', 'sxc', |
| 58 | 'stc', 'dif', 'dbf', 'xls', 'xlt', 'slk', 'csv', 'pxl', | 58 | 'stc', 'dif', 'dbf', 'xls', 'xlt', 'slk', 'csv', 'pxl', |
| 59 | 'odp', 'otp', 'sxi', 'sti', 'ppt', 'pot', 'sxd', 'odg', | 59 | 'odp', 'otp', 'sxi', 'sti', 'ppt', 'pot', 'sxd', 'odg', |
| @@ -126,7 +126,7 @@ class PDFGeneratorAction extends KTDocumentAction { | @@ -126,7 +126,7 @@ class PDFGeneratorAction extends KTDocumentAction { | ||
| 126 | $this->do_pdfdownload(); | 126 | $this->do_pdfdownload(); |
| 127 | } | 127 | } |
| 128 | redirect(KTUtil::ktLink( 'action.php', 'ktstandard.pdf.generate', array( "fDocumentId" => $this->oDocument->getId() ) ) ); | 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 | function do_main() { | 132 | function do_main() { |
| @@ -171,7 +171,7 @@ class PDFGeneratorAction extends KTDocumentAction { | @@ -171,7 +171,7 @@ class PDFGeneratorAction extends KTDocumentAction { | ||
| 171 | /** | 171 | /** |
| 172 | * Method for downloading the document as a pdf. | 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 | function do_pdfdownload() { | 176 | function do_pdfdownload() { |
| 177 | 177 | ||
| @@ -184,7 +184,7 @@ class PDFGeneratorAction extends KTDocumentAction { | @@ -184,7 +184,7 @@ class PDFGeneratorAction extends KTDocumentAction { | ||
| 184 | // Set the error messsage and redirect to view document | 184 | // Set the error messsage and redirect to view document |
| 185 | $this->addErrorMessage(_kt('An error occurred generating the PDF - please contact the system administrator. Python binary not found.')); | 185 | $this->addErrorMessage(_kt('An error occurred generating the PDF - please contact the system administrator. Python binary not found.')); |
| 186 | redirect(generateControllerLink('viewDocument',sprintf('fDocumentId=%d',$oDocument->getId()))); | 186 | redirect(generateControllerLink('viewDocument',sprintf('fDocumentId=%d',$oDocument->getId()))); |
| 187 | - exit(0); | 187 | + exit(0); |
| 188 | } | 188 | } |
| 189 | 189 | ||
| 190 | //get the actual path to the document on the server | 190 | //get the actual path to the document on the server |
| @@ -199,7 +199,7 @@ class PDFGeneratorAction extends KTDocumentAction { | @@ -199,7 +199,7 @@ class PDFGeneratorAction extends KTDocumentAction { | ||
| 199 | if (substr( PHP_OS, 0, 3) == 'WIN') { | 199 | if (substr( PHP_OS, 0, 3) == 'WIN') { |
| 200 | 200 | ||
| 201 | $cmd = "\"" . $cmdpath . "\" \"". KT_DIR . "/bin/openoffice/pdfgen.py\" \"" . $sPath . "\" \"" . $sTempFilename . "\""; | 201 | $cmd = "\"" . $cmdpath . "\" \"". KT_DIR . "/bin/openoffice/pdfgen.py\" \"" . $sPath . "\" \"" . $sTempFilename . "\""; |
| 202 | - $cmd = str_replace( '/','\\',$cmd); | 202 | + $cmd = str_replace( '/','\\',$cmd); |
| 203 | 203 | ||
| 204 | // TODO: Check for more errors here | 204 | // TODO: Check for more errors here |
| 205 | // SECURTIY: Ensure $sPath and $sTempFilename are safe or they could be used to excecute arbitrary commands! | 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,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 | if (file_exists($sTempFilename) && $res == '') { | 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 | // Remove the tempfile | 233 | // Remove the tempfile |
| 250 | unlink($sTempFilename); | 234 | unlink($sTempFilename); |
| 251 | 235 | ||
| @@ -253,20 +237,20 @@ class PDFGeneratorAction extends KTDocumentAction { | @@ -253,20 +237,20 @@ class PDFGeneratorAction extends KTDocumentAction { | ||
| 253 | $oDocumentTransaction = & new DocumentTransaction($oDocument, 'Document downloaded as PDF', 'ktcore.transactions.download', $aOptions); | 237 | $oDocumentTransaction = & new DocumentTransaction($oDocument, 'Document downloaded as PDF', 'ktcore.transactions.download', $aOptions); |
| 254 | $oDocumentTransaction->create(); | 238 | $oDocumentTransaction->create(); |
| 255 | // Just stop here - the content has already been sent. | 239 | // Just stop here - the content has already been sent. |
| 256 | - exit(0); | 240 | + exit(0); |
| 257 | 241 | ||
| 258 | } else { | 242 | } else { |
| 259 | // Set the error messsage and redirect to view document | 243 | // Set the error messsage and redirect to view document |
| 260 | $this->addErrorMessage(_kt('An error occurred generating the PDF - please contact the system administrator. ' . $res)); | 244 | $this->addErrorMessage(_kt('An error occurred generating the PDF - please contact the system administrator. ' . $res)); |
| 261 | redirect(generateControllerLink('viewDocument',sprintf('fDocumentId=%d',$oDocument->getId()))); | 245 | redirect(generateControllerLink('viewDocument',sprintf('fDocumentId=%d',$oDocument->getId()))); |
| 262 | - exit(0); | 246 | + exit(0); |
| 263 | } | 247 | } |
| 264 | 248 | ||
| 265 | } else { | 249 | } else { |
| 266 | // Set the error messsage and redirect to view document | 250 | // Set the error messsage and redirect to view document |
| 267 | $this->addErrorMessage(_kt('An error occurred generating the PDF - please contact the system administrator. The path to the document did not exist.')); | 251 | $this->addErrorMessage(_kt('An error occurred generating the PDF - please contact the system administrator. The path to the document did not exist.')); |
| 268 | redirect(generateControllerLink('viewDocument',sprintf('fDocumentId=%d',$oDocument->getId()))); | 252 | redirect(generateControllerLink('viewDocument',sprintf('fDocumentId=%d',$oDocument->getId()))); |
| 269 | - exit(0); | 253 | + exit(0); |
| 270 | } | 254 | } |
| 271 | 255 | ||
| 272 | 256 |