/** * Initialises the archiver class, seeding from an existent installer's JPA archive. * * @param string $sourceJPAPath Absolute path to an installer's JPA archive * @param string $targetArchivePath Absolute path to the generated archive (ignored in this class) * @param array $options A named key array of options (optional) * @access public */ function initialize($sourceJPAPath, $targetArchivePath, $options = array()) { JoomlapackLogger::WriteLog(_JP_LOG_DEBUG, __CLASS__ . " :: new instance"); // No setup! JoomlapackLogger::WriteLog(_JP_LOG_DEBUG, __CLASS__ . " :: Initializing with {$sourceJPAPath}"); parent::initialize($sourceJPAPath, $targetArchivePath, $options); }
/** * Implements the _run() abstract method */ function _run() { if ($this->_getState() == 'postrun') { JoomlapackLogger::WriteLog(_JP_LOG_DEBUG, __CLASS__ . " :: Already finished"); $this->_Step = ''; $this->_Substep = ''; } else { $this->setState('running'); $this->_isRunning = true; $this->_hasRan = false; } // Try to step the archiver $cube =& JoomlapackCUBE::getInstance(); $archive =& $cube->provisioning->getArchiverEngine(); $ret = $archive->transformJPA($this->_offset); // Error propagation if ($ret === false || $archive->getError() != '') { $this->setError($archive->getError()); } else { $this->_offset = $ret['offset']; $this->_Step = $ret['filename']; } // Check for completion if ($ret['done']) { JoomlapackLogger::WriteLog(_JP_LOG_DEBUG, __CLASS__ . ":: archive is initialized"); $this->_hasRan = true; $this->_isRunning = false; } }
/** * Appends a warning to the warnings stack * * @param string $message The warning message * @param bool $silent If set to true, no logging is performed (usefull for message propagation) */ function setWarning($message, $silent = false) { if (!$silent) { JoomlapackLogger::WriteLog(_JP_LOG_WARNING, $message); } $this->_warnings[] = $message; }
/** * Finalises the archive by compressing it. Overrides parent's method * @return boolean TRUE on success, FALSE on failure */ function finalize() { // Get gzip's binary location $registry = JoomlapackModelRegistry::getInstance(); $gzip = escapeshellcmd($registry->get('gzipbinary')); // Construct and run command line $command = "{$gzip} " . escapeshellcmd($this->_tempFilename); JoomlapackLogger::WriteLog(_JP_LOG_DEBUG, "JoomlapackPackerTARGZ :: Calling gzip. The command line is:"); JoomlapackLogger::WriteLog(_JP_LOG_DEBUG, $command); $result = shell_exec($command); // Normally, gzip should be silent as a fish. If anything was sput out, // there must have been an error. if (strlen(trim($result)) > 0) { $errorMessage = "Error calling gzip: " . $result . " \n Command line was: \n " . $command . " \n Please check file permissions and examine the result message for any hints regarding the problem tar faced archiving your files."; $this->setError($errorMessage); return false; } // Now, unregister the temp file (which no longer exists), register the gzipped file as // a new temp file and try to move it JoomlapackCUBETempfiles::unregisterAndDeleteTempFile($this->_tempFilename); $this->_tempFilename = JoomlapackCUBETempfiles::registerTempFile(basename($this->_archiveFilename)); copy($this->_tempFilename, $this->_archiveFilename); JoomlapackCUBETempfiles::unregisterAndDeleteTempFile($this->_tempFilename); // If no errors occured, return true return true; }
/** * Writes a line to the log, if the log level is high enough * * @param int|bool $level The log level (_JP_LOG_XX constants). Use FALSE to pause logging, TRUE to resume logging * @param string $message The message to write to the log */ function WriteLog($level, $message) { static $configuredLoglevel; static $site_root; if (empty($site_root)) { if (!class_exists('JoomlapackHelperUtils')) { jpimport('helpers.utils', true); } $site_root = JoomlapackHelperUtils::TranslateWinPath(JPATH_SITE); } if (empty($configuredLoglevel) or $level === true) { // Load the registry if (!class_exists('JoomlapackModelRegistry')) { jpimport('models.registry', true); } $registry =& JoomlapackModelRegistry::getInstance(); // Fetch log level $configuredLoglevel = $registry->get('logLevel'); } if ($level === false) { // Pause logging $configuredLogLevel = false; return; } // Catch paused logging if ($configuredLoglevel === false) { return; } if ($configuredLoglevel >= $level && $configuredLoglevel != 0) { $logName = JoomlapackLogger::logName(); $message = str_replace(JPATH_SITE, "<root>", $message); $message = str_replace($site_root, "<root>", $message); // Fix 2.4 - Also replace the translated path on Windows machines $message = str_replace("\n", ' \\n ', $message); // Fix 1.1.1 - Handle (error) messages containing newlines (by nicholas) switch ($level) { case _JP_LOG_ERROR: $string = "ERROR |"; break; case _JP_LOG_WARNING: $string = "WARNING |"; break; case _JP_LOG_INFO: $string = "INFO |"; break; default: $string = "DEBUG |"; break; } $string .= @strftime("%y%m%d %T") . "|{$message}\r\n"; $fp = @fopen($logName, "at"); if (!($fp === FALSE)) { @fwrite($fp, $string); @fclose($fp); } } }
function renderProgress() { jpimport('core.cube'); jpimport('helpers.backup', true); JoomlapackLogger::WriteLog(_JP_LOG_DEBUG, '--- Entering renderProgress()'); $cube =& JoomlapackCUBE::getInstance(); JoomlapackLogger::WriteLog(_JP_LOG_DEBUG, '--- renderProgress() got CUBE Instance'); $array = $cube->getCUBEArray(); JoomlapackLogger::WriteLog(_JP_LOG_DEBUG, '--- renderProgress() got CUBE Array'); return JoomlapackHelperBackup::getBackupProcessHTML($array); }
/** * Public constructor for JoomlapackListerAbstraction class. Does some heuristics to figure out the * server capabilities and setup internal variables */ function JoomlapackListerAbstraction() { JoomlapackLogger::WriteLog(_JP_LOG_DEBUG, "Initializing " . __CLASS__); // Don't use glob if it's disabled or if opendir is available $this->_globEnable = function_exists('glob'); if (function_exists('opendir') && function_exists('readdir') && function_exists('closedir')) { $this->_globEnable = false; } $this->_currentDir = null; $this->_currentDirList = null; JoomlapackLogger::WriteLog(_JP_LOG_DEBUG, __CLASS__ . " is initialized."); }
/** * Displays the HTML for this page * */ function echoHTML() { $nohtml = JoomlapackAbstraction::getParam('no_html', 0); if ($nohtml == 1) { JoomlapackLogger::VisualizeLogDirect(); } else { $configuration =& JoomlapackConfiguration::getInstance(); $option = JoomlapackAbstraction::getParam('option', 'com_joomlapack'); // Show top header echo JoomlapackCommonHTML::getAdminHeadingHTML(JoomlapackLangManager::_('LOG_LOGBANNER')); echo "<p><a href=\"index2.php?option={$option}&act=dllog&no_html=1\">" . JoomlapackLangManager::_('LOG_DOWNLOADTEXT') . "</a></p>"; echo '<iframe src="index2.php?option=' . $option . '&act=log&no_html=1" width="90%" height="400px">'; echo '</iframe>'; } }
/** * Parses the log file and outputs formatted HTML to the standard output */ function VisualizeLogDirect() { $logName = JoomlapackLogger::logName(); if (!file_exists($logName)) { return false; } //joostina pach $fp = fopen($logName, "rt"); if ($fp === FALSE) { return false; } while (!feof($fp)) { $line = fgets($fp); if (!$line) { return; } $exploded = explode("|", $line, 3); unset($line); switch (trim($exploded[0])) { case "ERROR": $fmtString = "<span style=\"color: red; font-weight: bold;\">["; break; case "WARNING": $fmtString = "<span style=\"color: #D8AD00; font-weight: bold;\">["; break; case "INFO": $fmtString = "<span style=\"color: black;\">["; break; case "DEBUG": $fmtString = "<span style=\"color: #666666; font-size: small;\">["; break; default: $fmtString = "<span style=\"font-size: small;\">["; break; } $fmtString .= $exploded[1] . "] " . htmlspecialchars($exploded[2]) . "</span><br/>\n"; unset($exploded); echo $fmtString; unset($fmtString); ob_flush(); } //ob_flush(); }
/** * Writes a variable to the database (#__jp_packvars) * * @param string $varName The name of the variable (must be unique; if it exists it gets overwritten) * @param string $value The value to store * @param bool $boolLongText True if you want to store a large string; deprecated since 1.1.2b * @static */ function WriteVar($varName, $value, $boolLongText = false) { $database = JoomlapackAbstraction::getDatabase(); // Hopefully fixes the 'MySQL server has gone away' errors by testing MySQL // connection status and reconnecting if necessary. if (method_exists($database, 'connected')) { $database->connected(); } // Kill exisiting variable (if any) JoomlapackTables::DeleteVar($varName); // Create variable $sql = "INSERT INTO #__jp_packvars (`key`, value2) VALUES (" . $database->Quote($varName) . ", " . $database->Quote($value) . ")"; $database->setQuery($sql); if ($database->query() === false) { JoomlapackLogger::WriteLog(_JP_LOG_ERROR, 'Failed to store packing variable ' . $varName . ' in database.'); JoomlapackLogger::WriteLog(_JP_LOG_ERROR, 'Error Message: ' . $database->getErrorMsg()); JoomlapackLogger::WriteLog(_JP_LOG_ERROR, 'Value was ' . $value); return false; } return true; }
function &getFolders($folder) { // Initialize variables $arr = array(); $false = false; if (!is_dir($folder)) { return $false; } $counter = 0; $registry =& JoomlapackModelRegistry::getInstance(); $maxCounter = $registry->get('mnMaxFragmentFiles', 50) * 2; $cube =& JoomlapackCUBE::getInstance(); $allowBreakflag = $cube->operationCounter != 0; $handle = @opendir($folder); // If directory is not accessible, just return FALSE if ($handle === FALSE) { JoomlapackLogger::WriteLog(_JP_LOG_WARNING, 'Unreadable directory ' . $dirName); return $false; } while (($file = @readdir($handle)) !== false && !$this->BREAKFLAG) { if ($file != '.' && $file != '..') { $dir = $folder . DS . $file; $isDir = is_dir($dir); if ($isDir) { $data = JPISWINDOWS ? JoomlapackHelperUtils::TranslateWinPath($dir) : $dir; if ($data) { $arr[] = $data; } } } $counter++; if ($counter >= $maxCounter) { $this->BREAKFLAG = $allowBreakflag; } } @closedir($handle); return $arr; }
/** * Writes a variable to the database (#__jp_temp) * * @param string $varName The name of the variable (must be unique; if it exists it gets overwritten) * @param string $value The value to store * @static */ function WriteVar($varName, $value) { $db =& JFactory::getDBO(); // Hopefully fixes the 'MySQL server has gone away' errors by testing MySQL // connection status and reconnecting if necessary. //$db->connected(); // Kill exisiting variable (if any) JoomlapackCUBETables::DeleteVar($varName); // Base64-encode the value $value2 = JoomlapackCUBETables::_getBase64() ? base64_encode($value) : $value; // Create variable // OMG! $db-Quote DOES NOT encode 'key' into `key`, thus causing havoc. I have // to use backticks manually. BUMMER! AAARGH! $sql = 'INSERT INTO #__jp_temp (`key`,`value`)' . ' VALUES (' . $db->Quote($varName) . ', ' . $db->Quote($value2) . ')'; $db->setQuery($sql); if ($db->query() === false) { JoomlapackLogger::WriteLog(_JP_LOG_ERROR, JText::sprintf('CUBE_TABLES_FAILEDSTORE', $varName)); JoomlapackLogger::WriteLog(_JP_LOG_ERROR, 'Error: ' . $db->getErrorMsg()); JoomlapackLogger::WriteLog(_JP_LOG_ERROR, 'Value: ' . $value); return false; } return true; }
/** * Initialises the archiver class, creating the archive from an existent * installer's JPA archive. * * @param string $sourceJPAPath Absolute path to an installer's JPA archive * @param string $targetArchivePath Absolute path to the generated archive * @param array $options A named key array of options (optional). This is currently not supported * @access public */ function initialize($sourceJPAPath, $targetArchivePath, $options = array()) { JoomlapackLogger::WriteLog(_JP_LOG_DEBUG, "JoomlapackPackerTAR :: initialize - archive {$targetArchivePath}"); // Get names of temporary files $configuration =& JoomlapackModelRegistry::getInstance(); $this->_dataFileName = $targetArchivePath; // Try to kill the archive if it exists JoomlapackLogger::WriteLog(_JP_LOG_DEBUG, "JoomlapackPackerTAR :: Killing old archive"); $fp = fopen($this->_dataFileName, "wb"); if (!($fp === false)) { ftruncate($fp, 0); fclose($fp); } else { @unlink($this->_dataFileName); } if (!@touch($this->_dataFileName)) { $this->setError(JText::_('CUBE_ARCHIVER_CANTWRITE')); return false; } $this->_tarObject = new Archive_Tar($targetArchivePath); $this->_tarObject->owningObject =& $this; parent::initialize($sourceJPAPath, $targetArchivePath, $options); }
/** * Writes a line to the log, if the log level is high enough * * @param integer $level The log level (_JP_LOG_XX constants) * @param string $message The message to write to the log */ function WriteLog($level, $message) { // Load the registry if (!class_exists('JoomlapackModelRegistry')) { jpimport('models.registry', true); } $registry =& JoomlapackModelRegistry::getInstance(); // Fetch log level $configuredLoglevel = $registry->get('logLevel'); if ($configuredLoglevel >= $level && $configuredLoglevel != 0) { $logName = JoomlapackLogger::logName(); $message = str_replace(JPATH_SITE, "<root>", $message); $message = str_replace("\n", ' \\n ', $message); // Fix 1.1.1 - Handle (error) messages containing newlines (by nicholas) switch ($level) { case _JP_LOG_ERROR: $string = "ERROR |"; break; case _JP_LOG_WARNING: $string = "WARNING |"; break; case _JP_LOG_INFO: $string = "INFO |"; break; default: $string = "DEBUG |"; break; } $string .= @strftime("%y%m%d %T") . "|{$message}\r\n"; $fp = @fopen($logName, "at"); if (!($fp === FALSE)) { @fwrite($fp, $string); @fclose($fp); } } }
/** * Returns the CRC32 of a file, selecting the more appropriate algorithm. * * @param string $filename Absolute path to the file being processed * @param integer $JoomlapackPackerZIP_CHUNK_SIZE Obsoleted * @return integer The CRC32 in numerical form */ function crc32_file($filename, $JoomlapackPackerZIP_CHUNK_SIZE) { static $configuration; if (!$configuration) { jpimport('models.registry', true); $configuration =& JoomlapackModelRegistry::getInstance(); } // Keep-alive before CRC32 calculation if ($configuration->get("enableMySQLKeepalive", false)) { list($usec, $sec) = explode(" ", microtime()); $endTime = (double) $usec + (double) $sec; if ($endTime - $this->startTime > 0.5) { $this->startTime = $endTime; JoomlapackCUBETables::WriteVar('dummy', 1); } } if (function_exists("hash_file")) { $res = $this->crc32_file_php512($filename); JoomlapackLogger::WriteLog(_JP_LOG_DEBUG, "File {$filename} - CRC32 = " . dechex($res) . " [PHP512]"); } else { if (function_exists("file_get_contents") && @filesize($filename) <= $JoomlapackPackerZIP_CHUNK_SIZE) { $res = $this->crc32_file_getcontents($filename); JoomlapackLogger::WriteLog(_JP_LOG_DEBUG, "File {$filename} - CRC32 = " . dechex($res) . " [GETCONTENTS]"); } else { $res = $this->crc32_file_php4($filename, $JoomlapackPackerZIP_CHUNK_SIZE); JoomlapackLogger::WriteLog(_JP_LOG_DEBUG, "File {$filename} - CRC32 = " . dechex($res) . " [PHP4]"); } } if ($res === FALSE) { $cube =& JoomlapackCUBE::getInstance(); $cube->addWarning("File {$filename} - NOT READABLE: CRC32 IS WRONG!"); } return $res; }
function _deleteCUBEObject() { $tmpfile = JoomlapackCUBETables::_cubeTmpFile(1); if (!empty($tmpfile)) { JoomlapackLogger::WriteLog(_JP_LOG_INFO, "Removing CUBE temporary file: " . $tmpfile); @unlink($tmpfile); } JoomlapackCUBETables::DeleteVar('cubetmpfile'); }
/** * Populates the _tables array with the metadata of each table and generates * dependency information for views and merge tables */ function _get_tables_data() { JoomlapackLogger::WriteLog(_JP_LOG_DEBUG, "JoomlapackDumperMysqlnew :: Starting CREATE TABLE and dependency scanning"); // Get a database connection $db =& $this->_getDB(); if ($this->getError()) { return; } // Reset internal tables $this->_tables_data = array(); $this->_dependencies = array(); // Get a list of tables where their engine type is shown $sql = 'SHOW TABLE STATUS'; $db->setQuery($sql); $metadata_list = $db->loadRowList(); foreach ($metadata_list as $table_metadata) { // Skip over tables not included in the backup set if (!array_key_exists($table_metadata[0], $this->_table_name_map)) { continue; } // Basic information $table_name = $table_metadata[0]; $table_abstract = $this->_table_name_map[$table_metadata[0]]; $new_entry = array('type' => 'table', 'dump_records' => true); switch ($table_metadata[1]) { // Views case null: $new_entry['type'] = 'view'; $new_entry['dump_records'] = false; break; // Merge tables // Merge tables case 'MRG_MYISAM': $new_entry['type'] = 'merge'; $new_entry['dump_records'] = false; break; // Tables whose data we do not back up (memory, federated and can-have-no-data tables) // Tables whose data we do not back up (memory, federated and can-have-no-data tables) case 'MEMORY': case 'EXAMPLE': case 'BLACKHOLE': case 'FEDERATED': $new_entry['dump_records'] = false; break; // Normal tables // Normal tables default: // @todo Table Data Filter - set dump_records to FALSE if array belongs to those filters break; } // switch $dependencies = array(); $new_entry['create'] = $this->_get_create($table_abstract, $table_name, $new_entry['type'], $dependencies); $new_entry['dependencies'] = $dependencies; $this->_tables_data[$table_name] = $new_entry; } // foreach // If we have MySQL > 5.0 add stored procedures, stored functions and triggers $verParts = explode('.', $db->getVersion()); if ($verParts[0] == 5) { // Get a list of procedures $sql = 'SHOW PROCEDURE STATUS WHERE `Db`=' . $db->Quote($this->_database); $db->setQuery($sql); $metadata_list = $db->loadRowList(); if (is_array($metadata_list)) { if (count($metadata_list)) { foreach ($metadata_list as $entity_metadata) { // Skip over entities not included in the backup set if (!array_key_exists($entity_metadata[1], $this->_table_name_map)) { continue; } // Basic information $entity_name = $entity_metadata[1]; $entity_abstract = $this->_table_name_map[$entity_metadata[1]]; $new_entry = array('type' => 'procedure', 'dump_records' => false); // There's no point trying to add a non-procedure entity if ($entity_metadata[2] != 'PROCEDURE') { continue; } $dependencies = array(); $new_entry['create'] = $this->_get_create($entity_abstract, $entity_name, $new_entry['type'], $dependencies); $new_entry['dependencies'] = $dependencies; $this->_tables_data[$entity_name] = $new_entry; } } } // foreach // Get a list of functions $sql = 'SHOW FUNCTION STATUS WHERE `Db`=' . $db->Quote($this->_database); $db->setQuery($sql); $metadata_list = $db->loadRowList(); if (is_array($metadata_list)) { if (count($metadata_list)) { foreach ($metadata_list as $entity_metadata) { // Skip over entities not included in the backup set if (!array_key_exists($entity_metadata[1], $this->_table_name_map)) { continue; } // Basic information $entity_name = $entity_metadata[1]; $entity_abstract = $this->_table_name_map[$entity_metadata[1]]; $new_entry = array('type' => 'function', 'dump_records' => false); // There's no point trying to add a non-function entity if ($entity_metadata[2] != 'FUNCTION') { continue; } $dependencies = array(); $new_entry['create'] = $this->_get_create($entity_abstract, $entity_name, $new_entry['type'], $dependencies); $new_entry['dependencies'] = $dependencies; $this->_tables_data[$entity_name] = $new_entry; } } } // foreach // Get a list of triggers $sql = 'SHOW TRIGGERS'; $db->setQuery($sql); $metadata_list = $db->loadRowList(); if (is_array($metadata_list)) { if (count($metadata_list)) { foreach ($metadata_list as $entity_metadata) { // Skip over entities not included in the backup set if (!array_key_exists($entity_metadata[0], $this->_table_name_map)) { continue; } // Basic information $entity_name = $entity_metadata[0]; $entity_abstract = $this->_table_name_map[$entity_metadata[0]]; $new_entry = array('type' => 'trigger', 'dump_records' => false); $dependencies = array(); $new_entry['create'] = $this->_get_create($entity_abstract, $entity_name, $new_entry['type'], $dependencies); $new_entry['dependencies'] = $dependencies; $this->_tables_data[$entity_name] = $new_entry; } } } // foreach } // Only store unique values if (count($dependencies) > 0) { $dependencies = array_unique($dependencies); } }
/** * Transforms a JPA archive (containing an installer) to the native archive format * of the class. It actually extracts the source JPA in memory and instructs the * class to include each extracted file. * * @param string $fileName The source JPA archive's filename * @return boolean False if an error occured, true otherwise * @access protected */ function transformJPA($fileName) { JoomlapackLogger::WriteLog(_JP_LOG_DEBUG, 'Initializing with JPA package ' . $fileName); // Try opening the file $this->_xform_source = $fileName; if (file_exists($this->_xform_source)) { $this->_xform_fp = @fopen($this->_xform_source, 'r'); if ($this->_xform_fp === false) { JoomlapackLogger::WriteLog(_JP_LOG_ERROR, __CLASS__ . ":: Can't seed archive with installer package " . $this->_xform_source); return false; } } else { JoomlapackLogger::WriteLog(_JP_LOG_ERROR, __CLASS__ . ":: Installer package " . $this->_xform_source . " does not exist!"); return false; } // Skip over the header and check no problem exists $offset = $this->_xformReadHeader(); if ($offset === false) { JoomlapackLogger::WriteLog(_JP_LOG_WARNING, 'JPA package file was not read'); return false; // Oops! The package file doesn't exist or is corrupt } do { $ret =& $this->_xformExtract($offset); if (is_array($ret)) { $offset = $ret['offset']; if (!$ret['skip'] && !$ret['done']) { JoomlapackLogger::WriteLog(_JP_LOG_DEBUG, ' Adding ' . $ret['filename'] . '; Next offset:' . $offset); $this->addVirtualFile($ret['filename'], '', $ret['data']); } else { $reason = $ret['done'] ? 'Done' : ' Skipping ' . $ret['filename']; JoomlapackLogger::WriteLog(_JP_LOG_DEBUG, $reason); } } else { JoomlapackLogger::WriteLog(_JP_LOG_WARNING, 'JPA extraction returned FALSE'); } } while (!($ret === false) && !$ret['done']); // Close the file fclose($this->_xform_fp); JoomlapackLogger::WriteLog(_JP_LOG_DEBUG, 'Initializing with JPA package has finished'); return true; }
/** * Expands the archive's template name and returns an absolute path * * @param string $extension The extension to append, defaults to '.zip' * @return string The absolute filename of the archive file requested * @static */ function getExpandedTarName($extension = '.zip', $fullPath = true) { $configuration =& JoomlapackModelRegistry::getInstance(); // Get the proper extension $templateName = $configuration->get('TarNameTemplate'); JoomlapackLogger::WriteLog(_JP_LOG_DEBUG, "Archive template name: {$templateName}"); // Get current date/time and express it in user's timezone jimport('joomla.utilities.date'); $user =& JFactory::getUser(); $userTZ = $user->getParam('timezone', 0); $dateNow = new JDate(); $dateNow->setOffset($userTZ); // Parse [DATE] tag $dateExpanded = $dateNow->toFormat("%Y%m%d"); $templateName = str_replace("[DATE]", $dateExpanded, $templateName); // Parse [TIME] tag $timeExpanded = $dateNow->toFormat("%H%M%S"); $templateName = str_replace("[TIME]", $timeExpanded, $templateName); // Parse [HOST] tag $uri =& JURI::getInstance(); $host = $uri->getHost(); $host = empty($host) ? 'unknown_host' : $uri->getHost(); $templateName = str_replace("[HOST]", $_SERVER['SERVER_NAME'], $templateName); // Parse [RANDOM] tag $templateName = str_replace("[RANDOM]", md5(microtime()), $templateName); JoomlapackLogger::WriteLog(_JP_LOG_DEBUG, "Expanded template name: {$templateName}"); if ($fullPath) { $path = $configuration->get('OutputDirectory') . DS . $templateName . $extension; JoomlapackLogger::WriteLog(_JP_LOG_DEBUG, "Calculated archive absolute path: {$path}"); return JoomlapackHelperUtils::TranslateWinPath($path); } else { return $templateName . $extension; } }
/** * Populates _databaseList with the list of databases in the settings * */ function _getDatabaseList() { /* * Logic: * Add an entry for the Joomla! database * If we are in DB Only mode, return * Otherwise, itterate the configured databases and add them if and only if all settings are populated */ // Cleanup the _databaseList array $this->_databaseList = array(); // Add a new record for the core Joomla! database $entry = array('isJoomla' => true, 'useFilters' => true, 'host' => '', 'port' => '', 'username' => '', 'password' => '', 'database' => '', 'dumpFile' => ''); $this->_databaseList[] = $entry; $configuration =& JoomlapackModelRegistry::getInstance(); $onlydb = $configuration->get('BackupType') == 'dbonly'; if ($onlydb) { JoomlapackLogger::WriteLog(_JP_LOG_DEBUG, "JoomlapackCUBEDomainDBBackup :: Skipping extra databases definitions"); return; } // Load multiple database definitions jpimport('models.multidb', true); $multidbmodel =& JoomlapackModelMultidb::getInstance('multidb', 'JoomlapackModel'); $extraDefs = $multidbmodel->getMultiDBList(true); if (count($extraDefs) > 0) { foreach ($extraDefs as $def) { $data = unserialize($def->value); $entry = array('isJoomla' => false, 'useFilters' => false, 'host' => $data['host'], 'port' => $data['port'], 'username' => $data['user'], 'password' => $data['pass'], 'database' => $data['database'], 'dumpFile' => $def->id . '-' . $data['database'] . '.sql'); $this->_databaseList[] = $entry; } } }
/** * Smart step algorithm. Runs the tick() function until we have consumed 75% * of the maximum_execution_time (minus 1 seconds) within this procedure. If * the available time is less than 1 seconds, it defaults to multi-step. * @param JoomlapackCUBEParts $object The CUBE part to step * @return integer 0 if more work is to be done, 1 if we finished correctly, * 2 if error eccured. * @access private */ function _algoSmartStep(&$object) { JoomlapackLogger::WriteLog(_JP_LOG_DEBUG, "Smart Stepping"); // Get the maximum execution time $maxExecTime = ini_get("maximum_execution_time"); $startTime = $this->_microtime_float(); if ($maxExecTime == "" || $maxExecTime == 0) { // If we have no time limit, set a hard limit of about 10 seconds // (safe for Apache and IIS timeouts, verbose enough for users) $maxExecTime = 14; } if ($maxExecTime <= mnMinimumExectime) { // If the available time is less than the trigger value, switch to // multi-step return $this->_algoMultiStep($object); } else { // All checks passes, this is a SmartStep-enabled case $maxRunTime = ($maxExecTime - 1) * mnExectimeBiasPercent; $maxRunTime = max(array(mnMaxExecTimeAllowed, $maxRunTime)); $runTime = 0; $finished = false; $error = false; $opsRemaining = max(1, mnMaxOpsPerStep); // Run at least one step, even if mnMaxOpsPerStep=0 // Loop until time's up, we're done or an error occured while ($runTime <= $maxRunTime && !$finished && !$error && $opsRemaining > 0) { $opsRemaining--; // Decrease the number of possible available operations count $result = $object->tick(); $this->currentDomain = $result['Domain']; $this->currentStep = $result['Step']; $this->currentSubstep = $result['Substep']; $error = false; if ($object->getError()) { $error = true; $this->setError($object->getError()); $result['Error'] = $this->getError(); } $finished = $error ? true : !$result['HasRun']; $endTime = $this->_microtime_float(); $runTime = $endTime - $startTime; //JoomlapackLogger::WriteLog(_JP_LOG_DEBUG, "--- Running time: ".$runTime); } // while // Return the result if (!$error) { JoomlapackLogger::WriteLog(_JP_LOG_DEBUG, "Successful Smart algorithm on " . get_class($object)); } else { JoomlapackLogger::WriteLog(_JP_LOG_ERROR, "Failed Smart algorithm on " . get_class($object)); } // @todo Warnings propagation return $error ? 2 : ($finished ? 1 : 0); } }
/** * Returns a list of (the absolute paths to) old backup files which should be deleted, * based on user's quota settings * * @return array */ function getOldBackupsToDelete() { // If no quota settings are enabled, quit $registry =& JoomlapackModelRegistry::getInstance(); $useCountQuotas = $registry->get('enableCountQuotas'); $useSizeQuotas = $registry->get('enableSizeQuotas'); if (!($useCountQuotas || $useSizeQuotas)) { JoomlapackLogger::WriteLog(_JP_LOG_DEBUG, "No quotas were defined; old backup files will be kept intact"); return array(); // No quota limits were requested } $latestBackup = $this->getLatestBackupFilename(); // Get quota values $countQuota = $registry->get('countQuota'); $sizeQuota = $registry->get('sizeQuota'); // Get valid-looking backup ID's $validIDs =& $this->getValidLookingBackupFiles(); // Create a list of valid files $allFiles = array(); foreach ($validIDs as $id) { $filename = $this->getFilename($id); if (!is_null($filename)) { // Only process existing files if (!file_exists($filename)) { continue; } $filesize = @filesize($filename); $allFiles[] = array('filename' => $filename, 'size' => $filesize); } } unset($validIDs); // If there are no files, exit early if (count($allFiles) == 0) { JoomlapackLogger::WriteLog(_JP_LOG_DEBUG, "There were no old backup files to apply quotas on"); return array(); } // Init arrays $ret = array(); $leftover = array(); // Do we need to apply count quotas? if ($useCountQuotas && is_numeric($countQuota) && !($countQuota <= 0)) { // Are there more files than the quota limit? if (!(count($allFiles) > $countQuota)) { // No, effectively skip the quota checking $leftover =& $allFiles; } else { JoomlapackLogger::WriteLog(_JP_LOG_DEBUG, "Processing count quotas"); // Yes, aply the quota setting. Add to $ret all entries minus the last // $countQuota ones. $count = 0; $checkLimit = count($allFiles) - $countQuota; // Only process if at least one file (current backup!) is to be left if (!($checkLimit == 0)) { foreach ($allFiles as $def) { $count++; if ($count <= $checkLimit) { if ($latestBackup == $def['filename']) { $count--; } else { $ret[] = $def['filename']; } } else { $leftover[] = $def; } } } unset($allFiles); } } else { // No count quotas are applied $leftover =& $allFiles; } // Do we need to apply size quotas? if ($useSizeQuotas && is_numeric($sizeQuota) && !($sizeQuota <= 0) && count($leftover) > 0) { JoomlapackLogger::WriteLog(_JP_LOG_DEBUG, "Processing size quotas"); // OK, let's start counting bytes! $sizeQuota = $sizeQuota * 1024 * 1024; // Convert size quota from Mb to bytes $runningSize = 0; while (count($leftover) > 0) { // Each time, remove the last element of the backup array and calculate // running size. If it's over the limit, add the archive to the return array. $def = array_pop($leftover); $runningSize += $def['size']; if ($runningSize >= $sizeQuota) { if ($latestBackup == $def['filename']) { $runningSize -= $def['size']; } else { $ret[] = $def['filename']; } } } } // Return the rest of the entries, if any return $ret; }
/** * Try to pack some files in the $_fileList, restraining ourselves not to reach the max * number of files or max fragment size while doing so. If this process is over and we are * left without any more files, reset $_doneScanning to false in order to instruct the class * to scan for more files. * * @return bool True if there were files packed, false otherwise (empty filelist) */ function _packSomeFiles() { if (count($this->_fileList) == 0) { // No files left to pack -- This should never happen! We catch this condition at the end of this method! $this->_doneScanning = false; return false; } else { $packedSize = 0; $numberOfFiles = 0; $cube =& JoomlapackCUBE::getInstance(); $provisioning =& $cube->getProvisioning(); $archiver =& $provisioning->getArchiverEngine(); $algoRunner =& JoomlapackCUBEAlgorunner::getInstance(); list($usec, $sec) = explode(" ", microtime()); $opStartTime = (double) $usec + (double) $sec; while (count($this->_fileList) > 0 && $packedSize <= JPMaxFragmentSize && $numberOfFiles <= JPMaxFragmentFiles) { $file = @array_shift($this->_fileList); $size = @filesize($file); // JoomlaPack 2.2: Anticipatory fragment size algorithm if ($packedSize + $size > JPMaxFragmentSize && $numberOfFiles > 0) { // Adding this file exceeds the fragment's capacity. Furthermore, it's NOT // the first file we tried to pack. Therefore, push it back to the list. array_unshift($this->_fileList, $file); // If the file is bigger than a whole fragment's allowed size, break the step // to avoid potential timeouts if ($size > JPMaxFragmentSize) { JoomlapackLogger::WriteLog(_JP_LOG_INFO, "Breaking step _before_ large file: " . $file . " - size: " . $size); $this->setBreakFlag(); } // Mark that we are not done packing files $this->_doneScanning = true; return true; } // JoomlaPack 2.2: Proactive potential timeout detection // Rough estimation of packing speed in bytes per second list($usec, $sec) = explode(" ", microtime()); $opEndTime = (double) $usec + (double) $sec; if ($opEndTime - $opStartTime == 0) { $_packSpeed = 0; } else { $_packSpeed = $packedSize / ($opEndTime - $opStartTime); } // Estimate required time to pack next file. If it's the first file of this operation, // do not impose any limitations. $_reqTime = $_packSpeed - 0.01 <= 0 ? 0 : $size / $_packSpeed; // Do we have enough time? if ($algoRunner->getTimeLeft() < $_reqTime) { array_unshift($this->_fileList, $file); JoomlapackLogger::WriteLog(_JP_LOG_INFO, "Proactive step break - file: " . $file . " - size: " . $size); $this->setBreakFlag(); $this->_doneScanning = true; return true; } $packedSize += $size; $numberOfFiles++; $archiver->addFile($file, $this->_removePath, $this->_addPath); // Error propagation if ($archiver->getError()) { $this->setError($archiver->getError()); return false; } // If this was the first file of the fragment and it exceeded the fragment's capacity, // break the step. Continuing with more operations after packing such a big file is // increasing the risk to hit a timeout. if ($packedSize > JPMaxFragmentSize && $numberOfFiles == 1) { JoomlapackLogger::WriteLog(_JP_LOG_INFO, "Breaking step *after* large file: " . $file . " - size: " . $size); $this->setBreakFlag(); return true; } } $this->_doneScanning = count($this->_fileList) > 0; return true; } }
/** * Retrieves an object for the specified engine. It reads the engine.ini in order to do that. * It will also call the _addEngineInclude to make sure the included file persists during * the backup session. * * @param string $engine The engine type (lister, dumper, packer) * @param string $item The engine class file name (e.g. deafault, jpa, etc) */ function &_getAnEngine($engine, $item) { // Load engine definitions JoomlapackLogger::WriteLog(_JP_LOG_DEBUG, "Creating {$engine} engine of type {$item}"); $sourceINI = JPATH_COMPONENT_ADMINISTRATOR . DS . 'classes' . DS . 'engine' . DS . $engine . DS . 'engine.ini'; JoomlapackLogger::WriteLog(_JP_LOG_DEBUG, "Trying to read engine setup data from {$sourceINI}"); $engineArray = JoomlapackHelperUtils::parse_ini_file($sourceINI, true); if (isset($engineArray[$item])) { $engineDescriptor = $engineArray[$item]; $dotted = 'engine.' . $engine . '.' . $engineDescriptor['include']; JoomlapackLogger::WriteLog(_JP_LOG_DEBUG, "Trying to include engine file {$dotted}"); $this->_addEngineInclude($dotted); jpimport($dotted); JoomlapackLogger::WriteLog(_JP_LOG_DEBUG, "Instanciating " . $engineDescriptor['class']); $instance = new $engineDescriptor['class'](); // If we are getting an archiver class, also populate the _archiveExtension field if ($engine == 'packer') { $this->archiveExtension = $engineDescriptor['extension']; } return $instance; } else { $this->setError(JText::sprintf('CUBE_PROVISIONING_ENGINENOTFOUND', $engine . '.' . $item)); return false; } }
function _createNewPart($finalPart = false) { $this->_totalFragments++; $this->_currentFragment = $this->_totalFragments; if ($finalPart) { $this->_dataFileName = $this->_dataFileNameBase . '.jpa'; } else { $this->_dataFileName = $this->_dataFileNameBase . '.j' . sprintf('%02d', $this->_currentFragment); } JoomlapackLogger::WriteLog(_JP_LOG_INFO, 'Creating new JPA part #' . $this->_currentFragment . ', file ' . $this->_dataFileName); // Inform CUBE that we have chenged the multipart number $cube =& JoomlapackCUBE::getInstance(); $cube->updateMultipart($this->_totalFragments); // Try to remove any existing file @unlink($this->_dataFileName); // Touch the new file return @touch($this->_dataFileName); }
/** * Retrieves an object for the specified engine. It reads the engine.ini in order to do that. * It will also call the _addEngineInclude to make sure the included file persists during * the backup session. * * @param string $engine The engine type (lister, dumper, packer) * @param string $item The engine class file name (e.g. deafault, jpa, etc) */ function &_getAnEngine($engine, $item) { // Load engine definitions JoomlapackLogger::WriteLog(_JP_LOG_DEBUG, "Creating {$engine} engine of type {$item}"); JoomlapackLogger::WriteLog(_JP_LOG_DEBUG, "Trying to read engine setup data for {$engine}"); // Find and parse all ini files in the given directory $ini_path = JPATH_COMPONENT_ADMINISTRATOR . DS . 'classes' . DS . 'engine' . DS . $engine; jimport('joomla.filesystem.folder'); $ini_files = JFolder::files($ini_path, '\\.ini$'); $engineArray = array(); if (count($ini_files)) { foreach ($ini_files as $sourceINI) { $myData = JoomlapackHelperUtils::parse_ini_file($ini_path . DS . $sourceINI, true); foreach ($myData as $key => $value) { $engineArray[$key] = $value; } } } if (isset($engineArray[$item])) { $engineDescriptor = $engineArray[$item]; $dotted = 'engine.' . $engine . '.' . $engineDescriptor['include']; JoomlapackLogger::WriteLog(_JP_LOG_DEBUG, "Trying to include engine file {$dotted}"); $this->_addEngineInclude($dotted); jpimport($dotted); JoomlapackLogger::WriteLog(_JP_LOG_DEBUG, "Instanciating " . $engineDescriptor['class']); $instance = new $engineDescriptor['class'](); // If we are getting an archiver class, also populate the _archiveExtension field if ($engine == 'packer') { $this->archiveExtension = $engineDescriptor['extension']; } return $instance; } else { $this->setError(JText::sprintf('CUBE_PROVISIONING_ENGINENOTFOUND', $engine . '.' . $item)); return false; } }
/** * Smart step algorithm. Runs the tick() function until we have consumed 75% * of the maximum_execution_time (minus 1 seconds) within this procedure. If * the available time is less than 1 seconds, it defaults to multi-step. * @param JoomlapackCUBEParts $object The CUBE part to step * @return integer 0 if more work is to be done, 1 if we finished correctly, * 2 if error eccured. * @access private */ function _algoSmartStep(&$object) { JoomlapackLogger::WriteLog(_JP_LOG_DEBUG, "Smart Stepping"); if ($this->_maxExecTime <= mnMinimumExectime) { // If the available time is less than the trigger value, switch to // multi-step return $this->_algoMultiStep($object); } else { // All checks pass, this is a SmartStep-enabled case $runTime = 0; $finished = false; $error = false; $breakFlag = false; // BREAKFLAG is optionally passed by domains to force-break current operation $opsRemaining = max(1, mnMaxOpsPerStep); // Run at least one step, even if mnMaxOpsPerStep=0 // Loop until time's up, we're done or an error occured, or BREAKFLAG is set while ($this->getTimeLeft() > 0 && !$finished && !$error && $opsRemaining > 0 && !$breakFlag) { $opsRemaining--; // Decrease the number of possible available operations count $result = $object->tick(); // Advance operation counter $cube =& JoomlapackCUBE::getInstance(); $cube->operationCounter++; $currentOperationNumber = $cube->operationCounter; unset($cube); // Process return array $this->currentDomain = $result['Domain']; $this->currentStep = $result['Step']; $this->currentSubstep = $result['Substep']; // Check for BREAKFLAG if (isset($result['BREAKFLAG'])) { $breakFlag = $result['BREAKFLAG']; } // Process errors $error = false; if ($object->getError()) { $error = true; $this->setError($object->getError()); $result['Error'] = $this->getError(); } // Check if the backup procedure should finish now $finished = $error ? true : !$result['HasRun']; // Log operation end JoomlapackLogger::WriteLog(_JP_LOG_DEBUG, '----- Finished operation ' . $currentOperationNumber . ' ------'); } // while // Return the result if (!$error) { JoomlapackLogger::WriteLog(_JP_LOG_DEBUG, "Successful Smart algorithm on " . get_class($object)); } else { JoomlapackLogger::WriteLog(_JP_LOG_ERROR, "Failed Smart algorithm on " . get_class($object)); } // @todo Warnings propagation return $error ? 2 : ($finished ? 1 : 0); } }
/** * Transforms a JPA archive (containing an installer) to the native archive format * of the class. It actually extracts the source JPA in memory and instructs the * class to include each extracted file. * * @param int $offset The source JPA archive's offset to use * @return boolean False if an error occured, true otherwise * @access protected */ function transformJPA($offset) { // Do we have to open the file? if (!$this->_xform_fp) { // Try opening the file if (file_exists($this->_xform_source)) { $this->_xform_fp = @fopen($this->_xform_source, 'r'); if ($this->_xform_fp === false) { //JoomlapackLogger::WriteLog(_JP_LOG_ERROR , __CLASS__ . ":: Can't seed archive with installer package ".$this->_xform_source); $this->setError(__CLASS__ . ":: Can't seed archive with installer package " . $this->_xform_source); return false; } } else { //JoomlapackLogger::WriteLog(_JP_LOG_ERROR , __CLASS__ . ":: Installer package ".$this->_xform_source." does not exist!"); $this->setError(__CLASS__ . ":: Installer package " . $this->_xform_source . " does not exist!"); return false; } } if (!$offset) { // First run detected! JoomlapackLogger::WriteLog(_JP_LOG_DEBUG, 'Initializing with JPA package '); $offset = 0; // Skip over the header and check no problem exists $offset = $this->_xformReadHeader(); if ($offset === false) { $this->setError('JPA package file was not read'); return false; // Oops! The package file doesn't exist or is corrupt } } $ret =& $this->_xformExtract($offset); if (is_array($ret)) { $offset = $ret['offset']; if (!$ret['skip'] && !$ret['done']) { JoomlapackLogger::WriteLog(_JP_LOG_DEBUG, ' Adding ' . $ret['filename'] . '; Next offset:' . $offset); $this->addVirtualFile($ret['filename'], '', $ret['data']); if ($this->getError()) { return false; } } else { $reason = $ret['done'] ? 'Done' : ' Skipping ' . $ret['filename']; JoomlapackLogger::WriteLog(_JP_LOG_DEBUG, $reason); } } else { $this->setError('JPA extraction returned FALSE'); return false; } if ($ret['done']) { // We are finished! Close the file fclose($this->_xform_fp); JoomlapackLogger::WriteLog(_JP_LOG_DEBUG, 'Initializing with JPA package has finished'); } return $ret; }
/** * The most basic file transaction: add a single entry (file or directory) to * the archive. * * @param bool $isVirtual If true, the next parameter contains file data instead of a file name * @param string $sourceNameOrData Absolute file name to read data from or the file data itself is $isVirtual is true * @param string $targetName The (relative) file name under which to store the file in the archive * @return True on success, false otherwise * @since 1.2.1 * @access protected * @abstract */ function _addFile($isVirtual, &$sourceNameOrData, $targetName) { static $configuration; if (!$configuration) { jpimport('models.registry', true); $configuration =& JoomlapackModelRegistry::getInstance(); } // See if it's a directory $isDir = $isVirtual ? false : is_dir($sourceNameOrData); // Get real size before compression if ($isVirtual) { $fileSize = strlen($sourceNameOrData); } else { $fileSize = $isDir ? 0 : filesize($sourceNameOrData); } // Decide if we will compress if ($isDir) { $compressionMethod = 0; // don't compress directories... } else { // Do we have plenty of memory left? $memLimit = ini_get("memory_limit"); if (is_numeric($memLimit) && $memLimit < 0) { $memLimit = ""; } // 1.2a3 -- Rare case with memory_limit < 0, e.g. -1Mb! if ($memLimit == "" || $fileSize >= _JoomlapackPackerZIP_COMPRESSION_THRESHOLD) { // No memory limit, or over 1Mb files => always compress up to 1Mb files (otherwise it times out) $compressionMethod = $fileSize <= _JoomlapackPackerZIP_COMPRESSION_THRESHOLD ? 1 : 0; } elseif (function_exists("memory_get_usage")) { // PHP can report memory usage, see if there's enough available memory; Joomla! alone eats about 5-6Mb! This code is called on files <= 1Mb $memLimit = $this->_return_bytes($memLimit); $availableRAM = $memLimit - memory_get_usage(); $compressionMethod = $availableRAM / 2.5 >= $fileSize ? 1 : 0; } else { // PHP can't report memory usage, compress only files up to 512Kb (conservative approach) and hope it doesn't break $compressionMethod = $fileSize <= 524288 ? 1 : 0; } } $compressionMethod = function_exists("gzcompress") ? $compressionMethod : 0; $storedName = $targetName; /* "Entity Description BLock" segment. */ $unc_len =& $fileSize; // File size $storedName .= $isDir ? "/" : ""; if ($compressionMethod == 1) { if ($isVirtual) { $udata =& $sourceNameOrData; } else { // Get uncompressed data if (function_exists("file_get_contents") && _JoomlapackPackerZIP_FORCE_FOPEN == false) { $udata = @file_get_contents($sourceNameOrData); // PHP > 4.3.0 saves us the trouble } else { // Argh... the hard way! $udatafp = @fopen($sourceNameOrData, "rb"); if (!($udatafp === false)) { $udata = ""; while (!feof($udatafp)) { // Keep-alive on file reading if ($configuration->get("enableMySQLKeepalive", false)) { list($usec, $sec) = explode(" ", microtime()); $endTime = (double) $usec + (double) $sec; if ($endTime - $this->startTime > 0.5) { $this->startTime = $endTime; JoomlapackCUBETables::WriteVar('dummy', 1); } } $udata .= fread($udatafp, JPPACK_CHUNK); } fclose($udatafp); } else { $udata = false; } } } if ($udata === FALSE) { // Unreadable file, skip it. JoomlapackLogger::WriteLog(_JP_LOG_WARNING, JText::sprintf('CUBE_WARN_UNREADABLEFILE', $sourceNameOrData)); return false; } else { // Proceed with compression $zdata = @gzcompress($udata); if ($zdata === false) { // If compression fails, let it behave like no compression was available $c_len =& $unc_len; $compressionMethod = 0; } else { unset($udata); $zdata = substr(substr($zdata, 0, strlen($zdata) - 4), 2); $c_len = strlen($zdata); } } } else { $c_len = $unc_len; } $this->_compressedSize += $c_len; // Update global data $this->_uncompressedSize += $fileSize; // Update global data $this->_fileCount++; // Get file permissions $perms = $isVirtual ? 0777 : @fileperms($sourceNameOrData); // Calculate Entity Description Block length $blockLength = 21 + strlen($storedName); // Open data file for output $fp = @fopen($this->_dataFileName, "ab"); if ($fp === false) { $this->setError("Could not open archive file '{$this->_dataFileName}' for append!"); return; } $this->_fwrite($fp, $this->_fileHeader); // Entity Description Block header if ($this->getError()) { return; } $this->_fwrite($fp, pack('v', $blockLength)); // Entity Description Block header length $this->_fwrite($fp, pack('v', strlen($storedName))); // Length of entity path $this->_fwrite($fp, $storedName); // Entity path $this->_fwrite($fp, pack('C', $isDir ? 0 : 1)); // Entity type $this->_fwrite($fp, pack('C', $compressionMethod)); // Compression method $this->_fwrite($fp, pack('V', $c_len)); // Compressed size $this->_fwrite($fp, pack('V', $unc_len)); // Uncompressed size $this->_fwrite($fp, pack('V', $perms)); // Entity permissions /* "File data" segment. */ if ($compressionMethod == 1) { // Just dump the compressed data $this->_fwrite($fp, $zdata); if ($this->getError()) { return; } unset($zdata); } elseif (!$isDir) { if ($isVirtual) { $this->_fwrite($fp, $sourceNameOrData); if ($this->getError()) { return; } } else { // Copy the file contents, ignore directories $zdatafp = @fopen($sourceNameOrData, "rb"); if ($zdatafp === FALSE) { JoomlapackLogger::WriteLog(_JP_LOG_WARNING, JText::sprintf('CUBE_WARN_UNREADABLEFILE', $sourceNameOrData)); return false; } else { while (!feof($zdatafp)) { $zdata = fread($zdatafp, JPPACK_CHUNK); $this->_fwrite($fp, $zdata); if ($this->getError()) { return; } } fclose($zdatafp); } } } fclose($fp); // ... and return TRUE = success return TRUE; }
/** * Gets the row count for table $tableAbstract. Also updates the $this->_maxRange variable. * * @param string $tableAbstract The abstract name of the table (works with canonical names too, though) * @return integer Row count of the table */ function _getRowCount($tableAbstract) { $db =& $this->_getDB(); if ($this->getError()) { return; } $sql = "SELECT COUNT(*) FROM `{$tableAbstract}`"; $db->setQuery($sql); $this->_maxRange = $this->_hasJoomFish ? $db->loadResult(false) : $db->loadResult(); JoomlapackLogger::WriteLog(_JP_LOG_DEBUG, "Rows on " . $this->_nextTable . " : " . $this->_maxRange); return $this->_maxRange; }