sFriendlyName = _kt('Bulk Export Plugin'); return $res; } function setup() { $this->registerAction('folderaction', 'KTBulkExportAction', 'ktstandard.bulkexport.action'); } } require_once(KT_LIB_DIR . '/actions/folderaction.inc.php'); class KTBulkExportAction extends KTFolderAction { var $sName = 'ktstandard.bulkexport.action'; var $sPermissionName = "ktcore.permissions.read"; var $_sShowPermission = "ktcore.permissions.read"; var $sOutputEncoding = 'UTF-8'; function _checkConvertEncoding() { if(!function_exists("iconv")) { $this->addErrorMessage(_kt('IConv PHP extension not installed. Bulk export could not handle output filename encoding conversion !')); return false; } $oKTConfig = KTConfig::getSingleton(); $this->sOutputEncoding = $oKTConfig->get('export/encoding', 'UTF-8'); // Test the specified encoding if(iconv("UTF-8", $this->sOutputEncoding, "") === FALSE) { $this->addErrorMessage(_kt('Specified output encoding for bulk export does not exists !')); return false; } return true; } /** * Convert encoding to defined character encoding * * @param string the string to convert * @param boolean encode(true) or decode(false) string * @return string the encoded string */ function _convertEncoding($sMystring, $bEncode) { if (strcasecmp($this->sOutputEncoding, "UTF-8") === 0) { return $sMystring; } if ($bEncode) { return iconv("UTF-8", $this->sOutputEncoding, $sMystring); } else { return iconv($this->sOutputEncoding, "UTF-8", $sMystring); } } function getDisplayName() { return _kt('Bulk Export'); } function do_main() { if(!$this->_checkConvertEncoding()) { redirect(KTBrowseUtil::getUrlForFolder($oFolder)); exit(0); } $oStorage =& KTStorageManagerUtil::getSingleton(); $aQuery = $this->buildQuery(); $this->oValidator->notError($aQuery); $aDocumentIds = DBUtil::getResultArrayKey($aQuery, 'id'); $this->startTransaction(); $oKTConfig =& KTConfig::getSingleton(); $sBasedir = $oKTConfig->get("urls/tmpDirectory"); $bNoisy = $oKTConfig->get("tweaks/noisyBulkOperations"); if (empty($aDocumentIds)) { $this->addErrorMessage(_kt("No documents found to export")); redirect(KTBrowseUtil::getUrlForFolder($oFolder)); exit(0); } $this->oPage->requireJSResource('thirdpartyjs/MochiKit/Base.js'); $this->oPage->requireJSResource('thirdpartyjs/MochiKit/Async.js'); $this->oPage->template = "kt3/minimal_page"; $this->handleOutput(""); $sTmpPath = tempnam($sBasedir, 'kt_export'); unlink($sTmpPath); mkdir($sTmpPath, 0700); $this->sTmpPath = $sTmpPath; $aPaths = array(); $aReplace = array( "[" => "[[]", " " => "[ ]", "*" => "[*]", "?" => "[?]", ); $aReplaceKeys = array_keys($aReplace); $aReplaceValues = array_values($aReplace); foreach ($aDocumentIds as $iId) { $oDocument = Document::get($iId); if ($bNoisy) { $oDocumentTransaction = & new DocumentTransaction($oDocument, "Document part of bulk export", 'ktstandard.transactions.bulk_export', array()); $oDocumentTransaction->create(); } $sParentFolder = str_replace('<', '', str_replace('', '', str_replace('>', '', sprintf('%s/%s', $sTmpPath, $oDocument->getFullPath())))); $newDir = $this->sTmpPath; $sFullPath = str_replace('<', '', str_replace('', '', str_replace('>', '', $this->_convertEncoding($oDocument->getFullPath(), true)))); foreach (split('/', $sFullPath) as $dirPart) { $newDir = sprintf("%s/%s", $newDir, $dirPart); if (!file_exists($newDir)) { mkdir($newDir, 0700); } } $sOrigFile = str_replace('<', '', str_replace('', '', str_replace('>', '', $oStorage->temporaryFile($oDocument)))); $sFilename = sprintf("%s/%s", $sParentFolder, str_replace('<', '', str_replace('', '', str_replace('>', '', $oDocument->getFileName())))); $sFilename = $this->_convertEncoding($sFilename, true); copy($sOrigFile, $sFilename); $sPath = str_replace('<', '', str_replace('', '', str_replace('>', '', sprintf("%s/%s", $oDocument->getFullPath(), $oDocument->getFileName())))); $sPath = str_replace($aReplaceKeys, $aReplaceValues, $sPath); $sPath = $this->_convertEncoding($sPath, true); $aPaths[] = $sPath; } $sManifest = sprintf("%s/%s", $this->sTmpPath, "MANIFEST"); file_put_contents($sManifest, join("\n", $aPaths)); $sZipFile = sprintf("%s/%s.zip", $this->sTmpPath, $this->oFolder->getName()); $sZipFile = str_replace('<', '', str_replace('', '', str_replace('>', '', $sZipFile))); $_SESSION['bulkexport'] = KTUtil::arrayGet($_SESSION, 'bulkexport', array()); $sExportCode = KTUtil::randomString(); $_SESSION['bulkexport'][$sExportCode] = array( 'file' => $sZipFile, 'dir' => $this->sTmpPath, ); $sZipCommand = KTUtil::findCommand("export/zip", "zip"); $aCmd = array( $sZipCommand, "-r", $sZipFile, ".", "-i@MANIFEST", ); $sOldPath = getcwd(); chdir($this->sTmpPath); // Note that the popen means that pexec will return a file descriptor $aOptions = array('popen' => 'r'); $fh = KTUtil::pexec($aCmd, $aOptions); $last_beat = time(); while(!feof($fh)) { if ($i % 1000 == 0) { $this_beat = time(); if ($last_beat + 1 < $this_beat) { $last_beat = $this_beat; print " "; } } $contents = fread($fh, 4096); if ($contents) { print nl2br($this->_convertEncoding($contents, false)); } $i++; } pclose($fh); $oTransaction = KTFolderTransaction::createFromArray(array( 'folderid' => $this->oFolder->getId(), 'comment' => "Bulk export", 'transactionNS' => 'ktstandard.transactions.bulk_export', 'userid' => $_SESSION['userID'], 'ip' => Session::getClientIP(), )); $url = KTUtil::addQueryStringSelf(sprintf('action=downloadZipFile&fFolderId=%d&exportcode=%s', $this->oFolder->getId(), $sExportCode)); printf('
' . _kt('Go here to download the zip file if you are not automatically redirected there') . "
\n", $url); $folderurl = KTBrowseUtil::getUrlForFolder($this->oFolder); printf('' . _kt('Once downloaded, return to the original folder') . "
\n", $folderurl); printf("