public function __construct() { $this->object = 'dir'; $this->subtype = 'children'; $this->method = 'direct'; $this->filter_name = 'PlatformSkipdirs'; // We take advantage of the filter class magic to inject our custom filters $configuration =& AEFactory::getConfiguration(); if(defined('AKEEBACLI')) { $tmpdir = AEUtilJconfig::getValue('tmp_path'); } else { $jreg =& JFactory::getConfig(); $tmpdir = $jreg->getValue('config.tmp_path'); } $this->filter_data['[SITEROOT]'] = array ( // Output & temp directory of the component self::treatDirectory($configuration->get('akeeba.basic.output_directory')), self::treatDirectory($configuration->get('akeeba.basic.temporary_directory')), // Joomla! temporary directory self::treatDirectory($tmpdir), // Joomla! front- and back-end cache, as reported by Joomla! self::treatDirectory(JPATH_CACHE), self::treatDirectory(JPATH_ADMINISTRATOR.DS.'cache'), self::treatDirectory(JPATH_ROOT.DS.'cache'), // This is not needed except on sites running SVN or beta releases self::treatDirectory(JPATH_ROOT.DS.'installation'), // Joomla! front- and back-end cache, as calculated by us (redundancy, for funky server setups) self::treatDirectory( AEPlatform::get_site_root().DS.'cache' ), self::treatDirectory( AEPlatform::get_site_root().DS.'administrator'.DS.'cache'), 'administrator/components/com_akeeba/backup', // MyBlog's cache self::treatDirectory( AEPlatform::get_site_root().DS.'components'.DS.'libraries'.DS.'cmslib'.DS.'cache' ), // The logs directory 'logs' ); parent::__construct(); }
/** * Scans a directory for files and directories, updating the directory_list and file_list * private fields * * @return bool True if more work has to be done, false if the dirextory stack is empty */ private function scan_directory( ) { // Are we supposed to scan for more files? if( $this->done_scanning ) return true; // Get the next directory to scan, if the folders and files of the last directory // have been scanned. if($this->done_subdir_scanning && $this->done_file_scanning) { if( count($this->directory_list) == 0 ) { // No directories left to scan return false; } else { // Get and remove the last entry from the $directory_list array $this->current_directory = array_pop($this->directory_list); $this->setStep($this->current_directory); $this->done_subdir_scanning = false; $this->done_file_scanning = false; $this->processed_files_counter = 0; } } $engine =& AEFactory::getScanEngine(); // Break directory components $root = $this->root; $translated_root = AEUtilFilesystem::TranslateWinPath($this->root); if($this->root == '[SITEROOT]') { $translated_root = AEUtilFilesystem::TranslateWinPath(AEPlatform::get_site_root()); } else { $translated_root = $this->remove_path_prefix; } $dir = AEUtilFilesystem::TrimTrailingSlash($this->current_directory); if(substr($dir,0,strlen($translated_root)) == $translated_root) $dir = substr($dir,strlen($translated_root)); if(substr($dir,0,1) == '/') $dir = substr($dir,1); // get a filters instance $filters =& AEFactory::getFilters(); // Scan subdirectories, if they have not yet been scanned. if(!$this->done_subdir_scanning) { // Apply DEF (directory exclusion filters) //if (in_array( $this->current_directory, $this->_ExcludeDirs )) { if($filters->isFiltered($dir, $root, 'dir', 'all') ) { AEUtilLogger::WriteLog(_AE_LOG_INFO, "Skipping directory ".$this->current_directory); $this->done_subdir_scanning = true; $this->done_file_scanning = true; return true; } // Apply Skip Contained Directories Filters //if (in_array( $this->current_directory, $this->_skipContainedDirectories )) { if($filters->isFiltered($dir, $root, 'dir', 'children') ) { AEUtilLogger::WriteLog(_AE_LOG_INFO, "Skipping subdirectories of directory ".$this->current_directory); $this->done_subdir_scanning = true; } else { AEUtilLogger::WriteLog(_AE_LOG_INFO, "Scanning directories of ".$this->current_directory); // Get subdirectories $subdirs = $engine->getFolders($this->current_directory); // Error propagation $this->propagateFromObject($engine); // If the list contains "too many" items, please break this step! $registry =& AEFactory::getConfiguration(); if($registry->get('volatile.breakflag', false)) { // Log the step break decision, for debugging reasons AEUtilLogger::WriteLog(_AE_LOG_INFO, "Large directory ".$this->current_directory." while scanning for subdirectories; I will resume scanning in next step."); // Return immediately, marking that we are not done yet! return true; } // Error control if($this->getError()) { return false; } if(!empty($subdirs) && is_array($subdirs)) { $registry =& AEFactory::getConfiguration(); $dereferencesymlinks = $registry->get('engine.archiver.common.dereference_symlinks'); if($dereferencesymlinks) { // Treat symlinks to directories as actual directories foreach($subdirs as $subdir) { $this->directory_list[] = $subdir; $this->progressAddFolder(); } } else { // Treat symlinks to directories as simple symlink files (ONLY WORKS WITH CERTAIN ARCHIVERS!) foreach($subdirs as $subdir) { if(is_link($subdir)) { // Symlink detected; apply file filters to it if(empty($dir)) { $dirSlash = $dir; } else { $dirSlash = $dir.'/'; } $check = $dir.basename($subdir); if(_AKEEBA_IS_WINDOWS) $check = AEUtilFilesystem::TranslateWinPath ($check); // Do I need this? $dir contains a path relative to the root anyway... $check = ltrim(str_replace($translated_root, '', $check),'/'); if($filters->isFiltered($check, $root, 'file', 'all') ) { AEUtilLogger::WriteLog(_AE_LOG_INFO, "Skipping directory symlink ".$check); } else { AEUtilLogger::WriteLog(_AE_LOG_DEBUG, 'Adding symlink to folder as file: '.$check); $this->file_list[] = $subdir; $this->progressAddFile(); } } else { $this->directory_list[] = $subdir; $this->progressAddFolder(); } } } } } $this->done_subdir_scanning = true; return true; // Break operation } // If we are here, we have not yet scanned the directory for files, so there // is no need to test for done_file_scanning (saves a tiny amount of CPU time) // Apply Skipfiles if($filters->isFiltered($dir, $root, 'dir', 'content') ) { AEUtilLogger::WriteLog(_AE_LOG_INFO, "Skipping files of directory ".$this->current_directory); // Try to find and include .htaccess and index.htm(l) files // # Fix 2.4: Do not add DS if we are on the site's root and it's an empty string $ds = ($this->current_directory == '') || ($this->current_directory == '/') ? '' : DS; $checkForTheseFiles = array( $this->current_directory.$ds.'.htaccess', $this->current_directory.$ds.'index.html', $this->current_directory.$ds.'index.htm', $this->current_directory.$ds.'robots.txt' ); $this->processed_files_counter = 0; foreach($checkForTheseFiles as $fileName) { if(@file_exists($fileName)) { // Fix 3.3 - We have to also put them through other filters, ahem! if(!$filters->isFiltered($fileName, $root, 'file', 'all')) { $this->file_list[] = $fileName; $this->processed_files_counter++; } } } $this->done_file_scanning = true; } else { AEUtilLogger::WriteLog(_AE_LOG_INFO, "Scanning files of ".$this->current_directory); // Get file listing $fileList =& $engine->getFiles( $this->current_directory ); // Error propagation $this->propagateFromObject($engine); // If the list contains "too many" items, please break this step! $registry =& AEFactory::getConfiguration(); if($registry->get('volatile.breakflag', false)) { // Log the step break decision, for debugging reasons AEUtilLogger::WriteLog(_AE_LOG_INFO, "Large directory ".$this->current_directory." while scanning for files; I will resume scanning in next step."); // Return immediately, marking that we are not done yet! return true; } // Error control if($this->getError()) { return false; } $this->processed_files_counter = 0; if (($fileList === false)) { // A non-browsable directory; however, it seems that I never get FALSE reported here?! $this->setWarning('Unreadable directory '.$this->current_directory); } else { if(is_array($fileList) && !empty($fileList)) { // Add required trailing slash to $dir if(!empty($dir)) $dir.='/'; // Scan all directory entries foreach($fileList as $fileName) { $check = $dir.basename($fileName); if(_AKEEBA_IS_WINDOWS) $check = AEUtilFilesystem::TranslateWinPath ($check); // Do I need this? $dir contains a path relative to the root anyway... $check = ltrim(str_replace($translated_root, '', $check),'/'); $skipThisFile = $filters->isFiltered($check, $root, 'file', 'all'); if ($skipThisFile) { AEUtilLogger::WriteLog(_AE_LOG_INFO, "Skipping file $fileName"); } else { $this->file_list[] = $fileName; $this->processed_files_counter++; $this->progressAddFile(); } } // end foreach } // end if } // end filelist not false $this->done_file_scanning = true; } // Check to see if there were no contents of this directory added to our search list if ( $this->processed_files_counter == 0 ) { $archiver =& AEFactory::getArchiverEngine(); if($this->current_directory != $this->remove_path_prefix) { $archiver->addFile($this->current_directory, $this->remove_path_prefix, $this->path_prefix); } // Error propagation $this->propagateFromObject($archiver); if($this->getError()) { return false; } AEUtilLogger::WriteLog(_AE_LOG_INFO, "Empty directory ".$this->current_directory); unset($archiver); $this->done_scanning = false; // Because it was an empty dir $file_list is empty and we have to scan for more files } else { // Next up, add the files to the archive! $this->done_scanning = true; } // We're done listing the contents of this directory unset($engine); return true; }
/** * Q003 - HIGH - Backup output or temporary set to site's root * * @return bool */ private static function q003() { $stock_dirs = AEPlatform::get_stock_directories(); $registry =& AEFactory::getConfiguration(); $outdir = $registry->get('akeeba.basic.output_directory'); foreach( $stock_dirs as $macro => $replacement ) { $outdir = str_replace($macro, $replacement, $outdir); } $tempdir = $registry->get('akeeba.basic.temporary_directory'); foreach( $stock_dirs as $macro => $replacement ) { $tempdir = str_replace($macro, $replacement, $tempdir); } $outdir_real = @realpath($outdir); if(!empty($outdir_real)) $outdir = $outdir_real; $tempdir_real = @realpath($tempdir); if(!empty($tempdir_real)) $tempdir = $tempdir_real; $siteroot = AEPlatform::get_site_root(); $siteroot_real = @realpath($siteroot); if(!empty($siteroot_real)) $siteroot = $siteroot_real; return ($siteroot == $outdir) || ($siteroot == $tempdir); }
/** * Writes a line to the log, if the log level is high enough * * @param int|bool $level The log level (_AE_LOG_XX constants). Use FALSE to pause logging, TRUE to resume logging * @param string $message The message to write to the log */ static function WriteLog( $level, $message = '' ) { static $oldLog = null; static $configuredLoglevel; static $site_root_untranslated; static $site_root; static $fp = null; // Make sure we have a log name if(empty(self::$logName)) { self::$logName = self::logName(); } // Check for log name changes if(is_null($oldLog)) { $oldLog = self::$logName; } elseif($oldLog != self::$logName) { // The log file changed. Close the old log. if(is_resource($fp)) @fclose($fp); $fp = null; } // Close the log file if the level is set to NULL if( is_null($level) && !is_null($fp) ) { @fclose($fp); $fp = null; return; } if(empty($site_root) || empty($site_root_untranslated)) { $site_root_untranslated = AEPlatform::get_site_root(); $site_root = AEUtilFilesystem::TranslateWinPath( $site_root_untranslated ); } if(empty($configuredLoglevel) or ($level === true)) { // Load the registry and fetch log level $registry =& AEFactory::getConfiguration(); $configuredLoglevel = $registry->get('akeeba.basic.log_level'); $configuredLoglevel = $configuredLoglevel * 1; return; } if($level === false) { // Pause logging $configuredLogLevel = false; return; } // Catch paused logging if($configuredLoglevel === false) return; if( ($configuredLoglevel >= $level) && ($configuredLoglevel != 0)) { $message = str_replace( $site_root_untranslated, "<root>", $message ); $message = str_replace( $site_root, "<root>", $message ); $message = str_replace( "\n", ' \n ', $message ); switch( $level ) { case _AE_LOG_ERROR: $string = "ERROR |"; break; case _AE_LOG_WARNING: $string = "WARNING |"; break; case _AE_LOG_INFO: $string = "INFO |"; break; default: $string = "DEBUG |"; break; } $string .= @strftime( "%y%m%d %H:%M:%S" ) . "|$message\r\n"; if(is_null($fp)) { $fp = @fopen( AEUtilLogger::$logName, "a" ); } if (!($fp === FALSE)) { $result = @fwrite( $fp, $string ); if($result === false) { // Try harder with the file pointer, will ya? $fp = @fopen( AEUtilLogger::$logName, "a" ); $result = @fwrite( $fp, $string ); } } } }