PageRenderTime 56ms CodeModel.GetById 27ms RepoModel.GetById 0ms app.codeStats 1ms

/joomla/administrator/components/com_joomlapack/classes/core/domain/pack.php

https://github.com/joomla-example/joomla-repo
PHP | 643 lines | 402 code | 64 blank | 177 comment | 67 complexity | d5b8643ad460f3159ef35a9318c2b750 MD5 | raw file
Possible License(s): Apache-2.0, LGPL-2.1
  1. <?php
  2. /**
  3. * @package JoomlaPack
  4. * @copyright Copyright (C) 2006-2009 JoomlaPack Developers. All rights reserved.
  5. * @version $Id$
  6. * @license http://www.gnu.org/copyleft/gpl.html GNU/GPL
  7. * @since 1.2.1
  8. *
  9. * JoomlaPack is free software. This version may have been modified pursuant
  10. * to the GNU General Public License, and as distributed it includes or
  11. * is derivative of works licensed under the GNU General Public License or
  12. * other free or open source software licenses.
  13. **/
  14. defined('_JEXEC') or die('Restricted access');
  15. $config =& JoomlapackModelRegistry::getInstance();
  16. define('JPMaxFragmentSize', $config->get('mnMaxFragmentSize')); // Maximum bytes a fragment can have (default: 1Mb)
  17. define('JPMaxFragmentFiles', $config->get('mnMaxFragmentFiles')); // Maximum number of files a fragment can have (default: 50 files)
  18. /**
  19. * Packing engine. Takes care of putting gathered files (the file list) into
  20. * an archive.
  21. */
  22. class JoomlapackCUBEDomainPack extends JoomlapackCUBEParts {
  23. /**
  24. * @var array Directories to exclude
  25. */
  26. var $_ExcludeDirs;
  27. /**
  28. * @var array Files to exclude
  29. */
  30. var $_ExcludeFiles;
  31. /**
  32. * Directories to exclude their files from the backup
  33. *
  34. * @var array
  35. */
  36. var $_skipContainedFiles;
  37. /**
  38. * Directories to exclude their subdirectories from the backup
  39. *
  40. * @var array
  41. */
  42. var $_skipContainedDirectories;
  43. /**
  44. * @var array Directories left to be scanned
  45. */
  46. var $_directoryList;
  47. /**
  48. * @var array Files left to be put into the archive
  49. */
  50. var $_fileList;
  51. /**
  52. * Operation toggle. When it is true, files are added in the archive. When it is off, the
  53. * directories are scanned for files and directories.
  54. *
  55. * @var bool
  56. */
  57. var $_doneScanning = false;
  58. /**
  59. * Operation toggle #2. Scanning is separated in two sub-operations: scanning for
  60. * subdirectories (when this flag is false) and scanning for files (when this flag is
  61. * true).
  62. *
  63. * @var bool
  64. */
  65. var $_doneSubdirectoryScanning = false;
  66. /**
  67. * Operation toggle #3. Since the scanning of a folder for files might be interrupted
  68. * for some reason, when this variable is false the algorithm is forced NOT to skip
  69. * to the next item of the directory list.
  70. *
  71. * @var bool
  72. */
  73. var $_doneFileScanning = true;
  74. /**
  75. * Path to add to scanned files
  76. *
  77. * @var string
  78. */
  79. var $_addPath;
  80. /**
  81. * Path to remove from scanned files
  82. *
  83. * @var string
  84. */
  85. var $_removePath;
  86. /**
  87. * An array of EFF-defined directories
  88. *
  89. * @var array
  90. */
  91. var $_extraDirs = array();
  92. var $_processedFiles;
  93. var $_dirName;
  94. // ============================================================================================
  95. // IMPLEMENTATION OF JoomlapackEngineParts METHODS
  96. // ============================================================================================
  97. /**
  98. * Public constructor of the class
  99. *
  100. * @return JoomlapackCUBEDomainPack
  101. */
  102. function JoomlapackCUBEDomainPack(){
  103. $this->_DomainName = "Packing";
  104. JoomlapackLogger::WriteLog(_JP_LOG_DEBUG, "JoomlapackCUBEDomainPack :: new instance");
  105. }
  106. /**
  107. * Implements the _prepare() abstract method
  108. *
  109. */
  110. function _prepare()
  111. {
  112. JoomlapackLogger::WriteLog(_JP_LOG_DEBUG, "JoomlapackCUBEDomainPack :: Starting _prepare()");
  113. $cube =& JoomlapackCUBE::getInstance();
  114. // Grab the EFF filters
  115. JoomlapackLogger::WriteLog(_JP_LOG_DEBUG, "JoomlapackCUBEDomainPack :: Getting off-site directory inclusion filters (EFF)");
  116. jpimport('models.eff', true);
  117. $effModel = new JoomlapackModelEff();
  118. $this->_extraDirs =& $effModel->getMapping();
  119. // Add the mapping text file if there are EFFs defined!
  120. if(count($this->_extraDirs) > 0)
  121. {
  122. // We add a README.txt file in our virtual directory...
  123. JoomlapackLogger::WriteLog(_JP_LOG_DEBUG, "Creating README.txt in the EFF virtual folder");
  124. $virtualContents = JText::_('EFF_MAPTEXT_INTRO')."\n\n";
  125. foreach($this->_extraDirs as $dir)
  126. {
  127. $virtualContents .= JText::sprintf('EFF_MAPTEXT_LINE', $dir['vdir'], $dir['fsdir'])."\n";
  128. }
  129. // Add the file to our archive
  130. $registry =& JoomlapackModelRegistry::getInstance();
  131. $provisioning =& $cube->getProvisioning();
  132. $archiver =& $provisioning->getArchiverEngine();
  133. $archiver->addVirtualFile('README.txt', $registry->get('effvfolder'), $virtualContents);
  134. }
  135. // Get the directory exclusion filters - this only needs to be done once
  136. JoomlapackLogger::WriteLog(_JP_LOG_DEBUG, "JoomlapackCUBEDomainPack :: Getting exclusion filters");
  137. $this->_loadAndCacheFilters();
  138. if($this->getError()) return false;
  139. // FIX 1.1.0 $mosConfig_absolute_path may contain trailing slashes or backslashes incompatible with exclusion filters
  140. // FIX 1.2.2 Some hosts yield an empty string on realpath(JPATH_SITE)
  141. // FIX 2.2 On Windows, realpath might fail
  142. jpimport('helpers.utils', true);
  143. // FIX 2.4: Make an assumption (wild guess...)
  144. if(JPATH_BASE == '/administrator')
  145. {
  146. $cube->addWarning("Your site's root is an empty string. I am trying a workaround.");
  147. $jpath_site_real = '/';
  148. }
  149. else
  150. {
  151. // Fix 2.4: Make sure that $jpath_site_real contains something even if realpath fails
  152. $jpath_site_real = @realpath(trim(JPATH_SITE));
  153. $jpath_site_real = ($jpath_site_real === false) ? trim(JPATH_SITE) : $jpath_site_real;
  154. $jpath_site_real = JoomlapackHelperUtils::TranslateWinPath($jpath_site_real);
  155. }
  156. if( $jpath_site_real == '' )
  157. {
  158. // The JPATH_SITE is resolved to an empty string; attempt a workaround
  159. // Windows hosts
  160. if(DIRECTORY_SEPARATOR == '\\')
  161. {
  162. if( (trim(JPATH_SITE) != '') && (trim(JPATH_SITE) != '\\') && (trim(JPATH_SITE) != '/'))
  163. {
  164. $cube->addWarning("The site's root couldn't be normalized on a Windows host. Attempting workaround (filters might not work)");
  165. $jpath_site_real = JPATH_SITE; // Forcibly use the configured JPATH_SITE
  166. }
  167. else
  168. {
  169. $cube->addWarning("The normalized path to your site's root seems to be an empty string; I will attempt a workaround (Windows host)");
  170. $jpath_site_real = '/'; // Start scanning from filesystem root (workaround mode)
  171. }
  172. }
  173. // *NIX hosts
  174. else
  175. {
  176. $cube->addWarning("The normalized path to your site's root seems to be an empty string; I will attempt a workaround (*NIX host)");
  177. # Fix 2.1 Since JPATH_SITE is an empty string, shouldn't I begin scanning from the FS root, for crying out loud? What was I thinking putting JPATH_SITE there?
  178. $jpath_site_real = '/'; // Start scanning from filesystem root (workaround mode)
  179. }
  180. }
  181. // Fix 2.4.b1 : Add the trailing slash
  182. if( (substr($jpath_site_real,-1) != '/') && !empty($jpath_site_real) )
  183. {
  184. $jpath_site_real .= '/';
  185. }
  186. $this->_directoryList[] = $jpath_site_real; // Start scanning from Joomla! root, as decided above
  187. $this->_doneScanning = false; // Instruct the class to scan for files and directories
  188. $this->_doneSubdirectoryScanning = true;
  189. $this->_doneFileScanning = true;
  190. $this->_addPath = ''; // No added path for main site
  191. // Fix 2.4.b1 -- Since JPATH_SITE might have been post-processed, used the post-processed variable instead
  192. $this->_removePath = $jpath_site_real; // Remove absolute path to site's root for main site
  193. $this->setState('prepared');
  194. JoomlapackLogger::WriteLog(_JP_LOG_DEBUG, "JoomlapackCUBEDomainPack :: prepared");
  195. }
  196. function _run()
  197. {
  198. if ($this->_getState() == 'postrun') {
  199. JoomlapackLogger::WriteLog(_JP_LOG_DEBUG, "JoomlapackCUBEDomainPack :: Already finished");
  200. $this->_Step = "-";
  201. $this->_Substep = "";
  202. }
  203. else
  204. {
  205. if($this->_doneScanning)
  206. {
  207. $this->_packSomeFiles();
  208. if($this->getError()) return false;
  209. }
  210. else
  211. {
  212. $result = $this->_scanNextDirectory();
  213. if($this->getError()) return false;
  214. if(!$result)
  215. {
  216. // We have finished with our directory list. Hmm... Do we have extra directories?
  217. if(count($this->_extraDirs) > 0)
  218. {
  219. JoomlapackLogger::WriteLog(_JP_LOG_DEBUG, "More EFF definitions detected");
  220. $registry =& JoomlapackModelRegistry::getInstance();
  221. // Whack filters (not applicable for off-site directories)
  222. $this->_ExcludeDirs = array();
  223. $this->_ExcludeFiles = array();
  224. $this->_skipContainedDirectories = array();
  225. $this->_skipContainedFiles = array();
  226. // Calculate add/remove paths
  227. $myEntry = array_shift($this->_extraDirs);
  228. $this->_removePath = $myEntry['fsdir'];
  229. $this->_addPath = $registry->get('effvfolder').DS.$myEntry['vdir'];
  230. // Start the filelist building!
  231. $this->_directoryList[] = $this->_removePath;
  232. $this->_doneScanning = false; // Make sure we process this file list!
  233. JoomlapackLogger::WriteLog(_JP_LOG_INFO, "Including new off-site directory to ".$myEntry['vdir']);
  234. }
  235. else
  236. // Nope, we are completely done!
  237. $this->setState('postrun');
  238. }
  239. }
  240. }
  241. }
  242. /**
  243. * Implements the _finalize() abstract method
  244. *
  245. */
  246. function _finalize()
  247. {
  248. JoomlapackLogger::WriteLog(_JP_LOG_INFO, "Finalizing archive");
  249. $cube =& JoomlapackCUBE::getInstance();
  250. $provisioning =& $cube->getProvisioning();
  251. $archive =& $provisioning->getArchiverEngine();
  252. $archive->finalize();
  253. // Error propagation
  254. if($archive->getError())
  255. {
  256. $this->setError($archive->getError());
  257. return false;
  258. }
  259. JoomlapackLogger::WriteLog(_JP_LOG_DEBUG, "Archive is finalized");
  260. $this->setState('finished');
  261. }
  262. // ============================================================================================
  263. // PRIVATE METHODS
  264. // ============================================================================================
  265. /**
  266. * Loads the exclusion filters off the db and caches them inside the object
  267. */
  268. function _loadAndCacheFilters() {
  269. jpimport('core.utility.filtermanager');
  270. JoomlapackLogger::WriteLog(_JP_LOG_DEBUG, "JoomlapackCUBEDomainPack :: Initializing filter manager");
  271. $filterManager = new JoomlapackCUBEFilterManager();
  272. $filterManager->init();
  273. JoomlapackLogger::WriteLog(_JP_LOG_DEBUG, "JoomlapackCUBEDomainPack :: Getting Directory Exclusion Filters");
  274. $this->_ExcludeDirs = $filterManager->getFilters('folder');
  275. JoomlapackLogger::WriteLog(_JP_LOG_DEBUG, "JoomlapackCUBEDomainPack :: Getting Single File Filters");
  276. $this->_ExcludeFiles = $filterManager->getFilters('singlefile');
  277. JoomlapackLogger::WriteLog(_JP_LOG_DEBUG, "JoomlapackCUBEDomainPack :: Getting Contained Files Filters");
  278. $this->_skipContainedFiles = $filterManager->getFilters('containedfiles');
  279. JoomlapackLogger::WriteLog(_JP_LOG_DEBUG, "JoomlapackCUBEDomainPack :: Getting Contained Directories Filters");
  280. $this->_skipContainedDirectories = $filterManager->getFilters('containeddirectories');
  281. JoomlapackLogger::WriteLog(_JP_LOG_DEBUG, "JoomlapackCUBEDomainPack :: Done with filter manager");
  282. unset($filterManager);
  283. }
  284. /**
  285. * Scans a directory for files and directories, updating the _directoryList and _fileList
  286. * private fields
  287. *
  288. * @return bool True if more work has to be done, false if the dirextory stack is empty
  289. */
  290. function _scanNextDirectory( )
  291. {
  292. // Are we supposed to scan for more files?
  293. if( $this->_doneScanning ) return true;
  294. // Get the next directory to scan, if the folders and files of the last directory
  295. // have been scanned.
  296. if($this->_doneSubdirectoryScanning && $this->_doneFileScanning)
  297. {
  298. if( count($this->_directoryList) == 0 )
  299. {
  300. // No directories left to scan
  301. return false;
  302. }
  303. else
  304. {
  305. // Get and remove the last entry from the $_directoryList array
  306. $this->_dirName = array_pop($this->_directoryList);
  307. $this->_Step = $this->_dirName;
  308. $this->_doneSubdirectoryScanning = false;
  309. $this->_doneFileScanning = false;
  310. $this->_processedFiles = 0;
  311. }
  312. }
  313. $cube =& JoomlapackCUBE::getInstance();
  314. $provisioning =& $cube->getProvisioning();
  315. $engine =& $provisioning->getListerEngine();
  316. // Scan subdirectories, if they have not yet been scanned.
  317. if(!$this->_doneSubdirectoryScanning)
  318. {
  319. // Apply DEF (directory exclusion filters)
  320. if (in_array( $this->_dirName, $this->_ExcludeDirs )) {
  321. JoomlapackLogger::WriteLog(_JP_LOG_INFO, "Skipping directory ".$this->_dirName);
  322. $this->_doneSubdirectoryScanning = true;
  323. $this->_doneFileScanning = true;
  324. return true;
  325. }
  326. // Apply Skip Contained Directories Filters
  327. if (in_array( $this->_dirName, $this->_skipContainedDirectories )) {
  328. JoomlapackLogger::WriteLog(_JP_LOG_INFO, "Skipping subdirectories of directory ".$this->_dirName);
  329. $this->_doneSubdirectoryScanning = true;
  330. }
  331. else
  332. {
  333. JoomlapackLogger::WriteLog(_JP_LOG_INFO, "Scanning directories of ".$this->_dirName);
  334. // Get subdirectories
  335. $subdirs = $engine->getFolders($this->_dirName);
  336. // If the list contains "too many" items, please break this step!
  337. if($engine->BREAKFLAG)
  338. {
  339. // Unset the BREAKFLAG of the engine
  340. $engine->BREAKFLAG = false;
  341. // Set the BREAKFLAG of our class
  342. $this->setBreakFlag();
  343. // Log this decision, for debugging reasons
  344. JoomlapackLogger::WriteLog(_JP_LOG_INFO, "Large directory ".$this->_dirName." while scanning for subdirectories; I will resume scanning in next step.");
  345. // Return immediately, marking that we are not done yet!
  346. return true;
  347. }
  348. // Error propagation
  349. if($engine->getError())
  350. {
  351. $this->setError($engine->getError());
  352. return false;
  353. }
  354. if(!empty($subdirs) && is_array($subdirs))
  355. {
  356. $registry =& JoomlapackModelRegistry::getInstance();
  357. $dereferencesymlinks = $registry->get('dereferencesymlinks');
  358. if($dereferencesymlinks)
  359. {
  360. // Treat symlinks to directories as actual directories
  361. foreach($subdirs as $subdir)
  362. {
  363. $this->_directoryList[] = $subdir;
  364. }
  365. }
  366. else
  367. {
  368. // Treat symlinks to directories as simple symlink files (ONLY WORKS WITH CERTAIN ARCHIVERS!)
  369. foreach($subdirs as $subdir)
  370. {
  371. if(is_link($subdir))
  372. {
  373. JoomlapackLogger::WriteLog(_JP_LOG_DEBUG, 'Symlink found: '.$subdir);
  374. $this->_fileList[] = $subdir;
  375. }
  376. else
  377. {
  378. $this->_directoryList[] = $subdir;
  379. }
  380. }
  381. }
  382. }
  383. }
  384. $this->_doneSubdirectoryScanning = true;
  385. return true; // Break operation
  386. }
  387. // If we are here, we have not yet scanned the directory for files, so there
  388. // is no need to test for _doneFileScanning (saves a tiny amount of CPU time)
  389. // Apply Skipfiles, a.k.a. CFF (Contained Files Filter)
  390. if (in_array( $this->_dirName, $this->_skipContainedFiles )) {
  391. JoomlapackLogger::WriteLog(_JP_LOG_INFO, "Skipping files of directory ".$this->_dirName);
  392. // Try to find and include .htaccess and index.htm(l) files
  393. jimport('joomla.filesystem.file');
  394. // # Fix 2.4: Do not add DS if we are on the site's root and it's an empty string
  395. $ds = ($this->_dirName == '') || ($this->_dirName == '/') ? '' : DS;
  396. $checkForTheseFiles = array(
  397. $this->_dirName.$ds.'.htaccess',
  398. $this->_dirName.$ds.'index.html',
  399. $this->_dirName.$ds.'index.htm',
  400. $this->_dirName.$ds.'robots.txt'
  401. );
  402. $this->_processedFiles = 0;
  403. foreach($checkForTheseFiles as $fileName)
  404. {
  405. if(JFile::exists($fileName))
  406. {
  407. $this->_fileList[] = $fileName;
  408. $this->_processedFiles++;
  409. }
  410. }
  411. $this->_doneFileScanning = true;
  412. }
  413. else
  414. {
  415. JoomlapackLogger::WriteLog(_JP_LOG_INFO, "Scanning files of ".$this->_dirName);
  416. // Get file listing
  417. $fileList =& $engine->getFiles( $this->_dirName );
  418. // If the list contains "too many" items, please break this step!
  419. if($engine->BREAKFLAG)
  420. {
  421. // Unset the BREAKFLAG of the engine
  422. $engine->BREAKFLAG = false;
  423. // Set the BREAKFLAG of our class
  424. $this->setBreakFlag();
  425. // Log this decision, for debugging reasons
  426. JoomlapackLogger::WriteLog(_JP_LOG_INFO, "Large directory ".$this->_dirName." while scanning for files; I will resume scanning in next step.");
  427. // Return immediately, marking that we are not done yet!
  428. return true;
  429. }
  430. // Error propagation
  431. if($engine->getError())
  432. {
  433. $this->setError($engine->getError());
  434. return false;
  435. }
  436. $this->_processedFiles = 0;
  437. if (($fileList === false)) {
  438. // A non-browsable directory; however, it seems that I never get FALSE reported here?!
  439. $cube->addWarning(JText::sprintf('CUBE_WARN_UNREADABLEDIR', $this->_dirName));
  440. }
  441. else
  442. {
  443. if(is_array($fileList) && !empty($fileList))
  444. {
  445. // Scan all directory entries
  446. foreach($fileList as $fileName) {
  447. $skipThisFile = is_array($this->_ExcludeFiles) ? in_array( $fileName, $this->_ExcludeFiles ) : false;
  448. if ($skipThisFile) {
  449. JoomlapackLogger::WriteLog(_JP_LOG_INFO, "Skipping file $fileName");
  450. } else {
  451. $this->_fileList[] = $fileName;
  452. $this->_processedFiles++;
  453. }
  454. } // end foreach
  455. } // end if
  456. } // end filelist not false
  457. $this->_doneFileScanning = true;
  458. }
  459. // Check to see if there were no contents of this directory added to our search list
  460. if ( $this->_processedFiles == 0 ) {
  461. $archiver =& $provisioning->getArchiverEngine();
  462. $archiver->addFile($this->_dirName, $this->_removePath, $this->_addPath);
  463. if($archiver->getError())
  464. {
  465. $this->setError($archiver->getError());
  466. return false;
  467. }
  468. JoomlapackLogger::WriteLog(_JP_LOG_INFO, "Empty directory ".$this->_dirName);
  469. unset($archiver);
  470. $this->_doneScanning = false; // Because it was an empty dir $_fileList is empty and we have to scan for more files
  471. }
  472. else
  473. {
  474. // Next up, add the files to the archive!
  475. $this->_doneScanning = true;
  476. }
  477. // We're done listing the contents of this directory
  478. unset($engine);
  479. unset($provisioning);
  480. unset($cube);
  481. return true;
  482. }
  483. /**
  484. * Try to pack some files in the $_fileList, restraining ourselves not to reach the max
  485. * number of files or max fragment size while doing so. If this process is over and we are
  486. * left without any more files, reset $_doneScanning to false in order to instruct the class
  487. * to scan for more files.
  488. *
  489. * @return bool True if there were files packed, false otherwise (empty filelist)
  490. */
  491. function _packSomeFiles()
  492. {
  493. if( count($this->_fileList) == 0 )
  494. {
  495. // No files left to pack -- This should never happen! We catch this condition at the end of this method!
  496. $this->_doneScanning = false;
  497. return false;
  498. }
  499. else
  500. {
  501. $packedSize = 0;
  502. $numberOfFiles = 0;
  503. $cube =& JoomlapackCUBE::getInstance();
  504. $provisioning =& $cube->getProvisioning();
  505. $archiver =& $provisioning->getArchiverEngine();
  506. $algoRunner =& JoomlapackCUBEAlgorunner::getInstance();
  507. list($usec, $sec) = explode(" ", microtime());
  508. $opStartTime = ((float)$usec + (float)$sec);
  509. while( (count($this->_fileList) > 0) && ($packedSize <= JPMaxFragmentSize) && ($numberOfFiles <= JPMaxFragmentFiles) )
  510. {
  511. $file = @array_shift($this->_fileList);
  512. $size = @filesize($file);
  513. // JoomlaPack 2.2: Anticipatory fragment size algorithm
  514. if( ($packedSize + $size > JPMaxFragmentSize) && ($numberOfFiles > 0) )
  515. {
  516. // Adding this file exceeds the fragment's capacity. Furthermore, it's NOT
  517. // the first file we tried to pack. Therefore, push it back to the list.
  518. array_unshift($this->_fileList, $file);
  519. // If the file is bigger than a whole fragment's allowed size, break the step
  520. // to avoid potential timeouts
  521. if($size > JPMaxFragmentSize)
  522. {
  523. JoomlapackLogger::WriteLog(_JP_LOG_INFO, "Breaking step _before_ large file: ".$file." - size: ".$size);
  524. $this->setBreakFlag();
  525. }
  526. // Mark that we are not done packing files
  527. $this->_doneScanning = true;
  528. return true;
  529. }
  530. // JoomlaPack 2.2: Proactive potential timeout detection
  531. // Rough estimation of packing speed in bytes per second
  532. list($usec, $sec) = explode(" ", microtime());
  533. $opEndTime = ((float)$usec + (float)$sec);
  534. if( ($opEndTime - $opStartTime) == 0 )
  535. {
  536. $_packSpeed = 0;
  537. }
  538. else
  539. {
  540. $_packSpeed = $packedSize / ($opEndTime - $opStartTime);
  541. }
  542. // Estimate required time to pack next file. If it's the first file of this operation,
  543. // do not impose any limitations.
  544. $_reqTime = ($_packSpeed - 0.01) <= 0 ? 0 : $size / $_packSpeed;
  545. // Do we have enough time?
  546. if($algoRunner->getTimeLeft() < $_reqTime )
  547. {
  548. array_unshift($this->_fileList, $file);
  549. JoomlapackLogger::WriteLog(_JP_LOG_INFO, "Proactive step break - file: ".$file." - size: ".$size);
  550. $this->setBreakFlag();
  551. $this->_doneScanning = true;
  552. return true;
  553. }
  554. $packedSize += $size;
  555. $numberOfFiles++;
  556. $archiver->addFile($file, $this->_removePath, $this->_addPath);
  557. // Error propagation
  558. if($archiver->getError())
  559. {
  560. $this->setError($archiver->getError());
  561. return false;
  562. }
  563. // If this was the first file of the fragment and it exceeded the fragment's capacity,
  564. // break the step. Continuing with more operations after packing such a big file is
  565. // increasing the risk to hit a timeout.
  566. if( ($packedSize > JPMaxFragmentSize) && ($numberOfFiles == 1) )
  567. {
  568. JoomlapackLogger::WriteLog(_JP_LOG_INFO, "Breaking step *after* large file: ".$file." - size: ".$size);
  569. $this->setBreakFlag();
  570. return true;
  571. }
  572. }
  573. $this->_doneScanning = count($this->_fileList) > 0;
  574. return true;
  575. }
  576. }
  577. }