| Server IP : 213.186.33.4 / Your IP : 216.73.216.193 Web Server : Apache System : Linux webm006.cluster103.gra.hosting.ovh.net 5.15.206-ovh-vps-grsec-zfs-classid #1 SMP Fri May 15 02:41:25 UTC 2026 x86_64 User : awebpaca ( 35430) PHP Version : 8.5.0 Disable Function : _dyuweyrj4,_dyuweyrj4r,dl MySQL : OFF | cURL : ON | WGET : ON | Perl : ON | Python : ON | Sudo : OFF | Pkexec : OFF Directory : /home/awebpaca/visitevirtuelle/administrator/components/com_akeeba/akeeba/engines/archiver/ |
Upload File : |
<?php
/**
* Akeeba Engine
* The modular PHP5 site backup engine
* @copyright Copyright (c)2009-2014 Nicholas K. Dionysopoulos
* @license GNU GPL version 3 or, at your option, any later version
* @package akeebaengine
*
*/
// Protection against direct access
defined('AKEEBAENGINE') or die();
if (!function_exists('akstringlen'))
{
function akstringlen($string)
{
return function_exists('mb_strlen') ? mb_strlen($string, '8bit') : strlen($string);
}
}
/**
* JoomlaPack Archive creation class
*
* JPA Format 1.0 implemented, minus BZip2 compression support
*/
class AEArchiverJpa extends AEAbstractArchiver
{
/** @var integer How many files are contained in the archive */
private $_fileCount = 0;
/** @var integer The total size of files contained in the archive as they are stored */
private $_compressedSize = 0;
/** @var integer The total size of files contained in the archive when they are extracted to disk. */
private $_uncompressedSize = 0;
/** @var string The name of the file holding the ZIP's data, which becomes the final archive */
private $_dataFileName;
/** @var string Standard Header signature */
private $_archive_signature = "\x4A\x50\x41";
/** @var string Entity Block signature */
private $_fileHeader = "\x4A\x50\x46";
/** @var string Marks the split archive's extra header */
private $_extraHeaderSplit = "\x4A\x50\x01\x01"; //
/** @var bool Should I use Split ZIP? */
private $_useSplitZIP = false;
/** @var int Maximum fragment size, in bytes */
private $_fragmentSize = 0;
/** @var int Current fragment number */
private $_currentFragment = 1;
/** @var int Total number of fragments */
private $_totalFragments = 1;
/** @var string Archive full path without extension */
private $_dataFileNameBase = '';
/** @var bool Should I store symlinks as such (no dereferencing?) */
private $_symlink_store_target = false;
/**
* Extend the bootstrap code to add some define's used by the JPA format engine
*
* @see AEAbstractArchiver::__bootstrap_code()
* @codeCoverageIgnore
*
*/
protected function __bootstrap_code()
{
if (!defined('_AKEEBA_COMPRESSION_THRESHOLD'))
{
$config = AEFactory::getConfiguration();
define("_AKEEBA_COMPRESSION_THRESHOLD", $config->get('engine.archiver.common.big_file_threshold')); // Don't compress files over this size
/**
* Akeeba Backup and JPA Format version change chart:
* Akeeba Backup 3.0: JPA Format 1.1 is used
* Akeeba Backup 3.1: JPA Format 1.2 with file modification timestamp is used
*/
define('_JPA_MAJOR', 1); // JPA Format major version number
define('_JPA_MINOR', 2); // JPA Format minor version number
}
parent::__bootstrap_code();
}
/**
* 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)
*
* @access public
*/
public function initialize($targetArchivePath, $options = array())
{
AEUtilLogger::WriteLog(_AE_LOG_DEBUG, "AEArchiverJpa :: new instance - archive $targetArchivePath");
$this->_dataFileName = $targetArchivePath;
// NEW 2.3: Should we enable Split ZIP feature?
$registry = AEFactory::getConfiguration();
$fragmentsize = $registry->get('engine.archiver.common.part_size', 0);
if ($fragmentsize >= 65536)
{
// If the fragment size is AT LEAST 64Kb, enable Split ZIP
$this->_useSplitZIP = true;
$this->_fragmentSize = $fragmentsize;
// Indicate that we have at least 1 part
$statistics = AEFactory::getStatistics();
$statistics->updateMultipart(1);
$this->_totalFragments = 1;
AEUtilLogger::WriteLog(_AE_LOG_INFO, "AEArchiverJpa :: Spanned JPA creation enabled");
$this->_dataFileNameBase = dirname($targetArchivePath) . '/' . basename($targetArchivePath, '.jpa');
$this->_dataFileName = $this->_dataFileNameBase . '.j01';
}
// NEW 2.3: Should I use Symlink Target Storage?
$dereferencesymlinks = $registry->get('engine.archiver.common.dereference_symlinks', true);
if (!$dereferencesymlinks)
{
// We are told not to dereference symlinks. Are we on Windows?
if (function_exists('php_uname'))
{
$isWindows = stristr(php_uname(), 'windows');
}
else
{
$isWindows = (DIRECTORY_SEPARATOR == '\\');
}
// If we are not on Windows, enable symlink target storage
$this->_symlink_store_target = !$isWindows;
}
// Try to kill the archive if it exists
AEUtilLogger::WriteLog(_AE_LOG_DEBUG, "AEArchiverJpa :: Killing old archive");
$this->fp = $this->_fopen($this->_dataFileName, "wb");
if (!($this->fp === false))
{
@ftruncate($this->fp, 0);
}
else
{
if (file_exists($this->_dataFileName))
{
@unlink($this->_dataFileName);
}
@touch($this->_dataFileName);
if (function_exists('chmod'))
{
chmod($this->_dataFileName, 0666);
}
}
// Write the initial instance of the archive header
$this->_writeArchiveHeader();
if ($this->getError())
{
return;
}
}
/**
* Updates the Standard Header with current information
*/
public function finalize()
{
if (is_resource($this->fp))
{
$this->_fclose($this->fp);
}
if (is_resource($this->cdfp))
{
$this->_fclose($this->cdfp);
}
$this->_closeAllFiles();
// If Spanned JPA and there is no .jpa file, rename the last fragment to .jpa
if ($this->_useSplitZIP)
{
$extension = substr($this->_dataFileName, -4);
if ($extension != '.jpa')
{
AEUtilLogger::WriteLog(_AE_LOG_DEBUG, 'Renaming last JPA part to .JPA extension');
$newName = $this->_dataFileNameBase . '.jpa';
if (!@rename($this->_dataFileName, $newName))
{
$this->setError('Could not rename last JPA part to .JPA extension.');
return false;
}
$this->_dataFileName = $newName;
}
// Finally, point to the first part so that we can re-write the correct header information
if ($this->_totalFragments > 1)
{
$this->_dataFileName = $this->_dataFileNameBase . '.j01';
}
}
// Re-write the archive header
$this->_writeArchiveHeader();
if ($this->getError())
{
return;
}
}
/**
* Returns a string with the extension (including the dot) of the files produced
* by this class.
* @return string
*/
public function getExtension()
{
return '.jpa';
}
/**
* 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
*/
protected function _addFile($isVirtual, &$sourceNameOrData, $targetName)
{
static $configuration;
static $memLimit = null;
if (is_null($memLimit))
{
$memLimit = ini_get("memory_limit");
if ((is_numeric($memLimit) && ($memLimit < 0)) || !is_numeric($memLimit))
{
$memLimit = 0; // 1.2a3 -- Rare case with memory_limit < 0, e.g. -1Mb!
}
$memLimit = $this->_return_bytes($memLimit);
}
$isDir = false;
$isSymlink = false;
if (is_null($isVirtual))
{
$isVirtual = false;
}
$compressionMethod = 0;
if ($isVirtual)
{
AEUtilLogger::WriteLog(_AE_LOG_DEBUG, "-- Adding $targetName to archive (virtual data)");
}
else
{
AEUtilLogger::WriteLog(_AE_LOG_DEBUG, "-- Adding $targetName to archive (source: $sourceNameOrData)");
}
if (!$configuration)
{
$configuration = AEFactory::getConfiguration();
}
$timer = AEFactory::getTimer();
// Initialize inode change timestamp
$filectime = 0;
// Open data file for output
if (is_null($this->fp))
{
$this->fp = $this->_fopen($this->_dataFileName, "ab");
}
if ($this->fp === false)
{
$this->fp = null;
$this->setError("Could not open archive file '{$this->_dataFileName}' for append!");
return false;
}
if (!$configuration->get('volatile.engine.archiver.processingfile', false))
{
// Uncache data -- WHY DO THAT?!
/**
* $configuration->set('volatile.engine.archiver.sourceNameOrData', null);
* $configuration->set('volatile.engine.archiver.unc_len', null);
* $configuration->set('volatile.engine.archiver.resume', null);
* $configuration->set('volatile.engine.archiver.processingfile',false);
* /**/
// See if it's a directory
$isDir = $isVirtual ? false : is_dir($sourceNameOrData);
// See if it's a symlink (w/out dereference)
$isSymlink = false;
if ($this->_symlink_store_target && !$isVirtual)
{
$isSymlink = is_link($sourceNameOrData);
}
// Get real size before compression
if ($isVirtual)
{
$fileSize = akstringlen($sourceNameOrData);
$filectime = time();
}
else
{
if ($isSymlink)
{
$fileSize = akstringlen(@readlink($sourceNameOrData));
}
else
{
// Is the file readable?
if (!is_readable($sourceNameOrData) && !$isDir)
{
// Unreadable files won't be recorded in the archive file
$this->setWarning('Unreadable file ' . $sourceNameOrData . '. Check permissions');
return false;
}
// Get the filesize
$fileSize = $isDir ? 0 : @filesize($sourceNameOrData);
$filectime = $isDir ? 0 : @filemtime($sourceNameOrData);
}
}
// Decide if we will compress
if ($isDir || $isSymlink)
{
$compressionMethod = 0; // don't compress directories...
}
else
{
if (!$memLimit || ($fileSize >= _AKEEBA_COMPRESSION_THRESHOLD))
{
// No memory limit, or over 1Mb files => always compress up to 1Mb files (otherwise it times out)
$compressionMethod = ($fileSize <= _AKEEBA_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
$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
$udata = @file_get_contents($sourceNameOrData); // PHP > 4.3.0 saves us the trouble
}
if ($udata === false)
{
// Unreadable file, skip it.
$this->setWarning('Unreadable file ' . $sourceNameOrData . '. Check permissions');
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, -4), 2);
$c_len = akstringlen($zdata);
}
}
}
else
{
$c_len = $unc_len;
// Test for unreadable files
if (!$isVirtual && !$isSymlink && !$isDir)
{
$myfp = @fopen($sourceNameOrData, 'rb');
if ($myfp === false)
{
// Unreadable file, skip it.
$this->setWarning('Unreadable file ' . $sourceNameOrData . '. Check permissions');
return false;
}
@fclose($myfp);
}
}
$this->_compressedSize += $c_len; // Update global data
$this->_uncompressedSize += $fileSize; // Update global data
$this->_fileCount++;
// Get file permissions
$perms = 0755;
if (!$isVirtual)
{
if (@file_exists($sourceNameOrData))
{
if (@is_file($sourceNameOrData) || @is_link($sourceNameOrData))
{
if (@is_readable($sourceNameOrData))
{
$perms = @fileperms($sourceNameOrData);
}
}
}
}
// Calculate Entity Description Block length
$blockLength = 21 + akstringlen($storedName);
if ($filectime > 0)
{
$blockLength += 8;
} // If we need to store the file mod date
// Get file type
if ((!$isDir) && (!$isSymlink))
{
$fileType = 1;
}
elseif ($isSymlink)
{
$fileType = 2;
}
elseif ($isDir)
{
$fileType = 0;
}
// If it's a split ZIP file, we've got to make sure that the header can fit in the part
if ($this->_useSplitZIP)
{
// Compare to free part space
clearstatcache();
$current_part_size = @filesize($this->_dataFileName);
$free_space = $this->_fragmentSize - ($current_part_size === false ? 0 : $current_part_size);
if ($free_space <= $blockLength)
{
// Not enough space on current part, create new part
if (!$this->_createNewPart())
{
$this->setError('Could not create new JPA part file ' . basename($this->_dataFileName));
return false;
}
}
}
$this->_fwrite($this->fp, $this->_fileHeader); // Entity Description Block header
if ($this->getError())
{
return false;
}
$this->_fwrite($this->fp, pack('v', $blockLength)); // Entity Description Block header length
$this->_fwrite($this->fp, pack('v', akstringlen($storedName))); // Length of entity path
$this->_fwrite($this->fp, $storedName); // Entity path
$this->_fwrite($this->fp, pack('C', $fileType)); // Entity type
$this->_fwrite($this->fp, pack('C', $compressionMethod)); // Compression method
$this->_fwrite($this->fp, pack('V', $c_len)); // Compressed size
$this->_fwrite($this->fp, pack('V', $unc_len)); // Uncompressed size
$this->_fwrite($this->fp, pack('V', $perms)); // Entity permissions
// Timestamp Extra Field, only for files
if ($filectime > 0)
{
$this->_fwrite($this->fp, "\x00\x01"); // Extra Field Identifier
$this->_fwrite($this->fp, pack('v', 8)); // Extra Field Length
$this->_fwrite($this->fp, pack('V', $filectime)); // Timestamp
}
// Cache useful information about the file
if (!$isDir && !$isSymlink && !$isVirtual)
{
$configuration->set('volatile.engine.archiver.unc_len', $unc_len);
$configuration->set('volatile.engine.archiver.sourceNameOrData', $sourceNameOrData);
}
}
else
{
// If we are continuing file packing we have an uncompressed, non-virtual file.
// We need to set up these variables so as not to throw any PHP notices.
$isDir = false;
$isSymlink = false;
$isVirtual = false;
$compressionMethod = 0;
}
/* "File data" segment. */
if ($compressionMethod == 1)
{
if (!$this->_useSplitZIP)
{
// Just dump the compressed data
$this->_fwrite($this->fp, $zdata);
if ($this->getError())
{
return false;
}
}
else
{
// Split ZIP. Check if we need to split the part in the middle of the data.
clearstatcache();
$current_part_size = @filesize($this->_dataFileName);
$free_space = $this->_fragmentSize - ($current_part_size === false ? 0 : $current_part_size);
if ($free_space >= akstringlen($zdata))
{
// Write in one part
$this->_fwrite($this->fp, $zdata);
if ($this->getError())
{
return false;
}
}
else
{
$bytes_left = akstringlen($zdata);
while ($bytes_left > 0)
{
clearstatcache();
$current_part_size = @filesize($this->_dataFileName);
$free_space = $this->_fragmentSize - ($current_part_size === false ? 0 : $current_part_size);
// Split between parts - Write first part
$this->_fwrite($this->fp, $zdata, min(akstringlen($zdata), $free_space));
if ($this->getError())
{
return false;
}
// Get the rest of the data
$bytes_left = akstringlen($zdata) - $free_space;
if ($bytes_left > 0)
{
// Create new part
$this->_fclose($this->fp);
$this->fp = null;
if (!$this->_createNewPart())
{
// Die if we couldn't create the new part
$this->setError('Could not create new JPA part file ' . basename($this->_dataFileName));
return false;
}
else
{
// Open data file for output
$this->fp = $this->_fopen($this->_dataFileName, "ab");
if ($this->fp === false)
{
$this->fp = null;
$this->setError("Could not open archive file {$this->_dataFileName} for append!");
return false;
}
}
$zdata = substr($zdata, -$bytes_left);
}
}
}
}
unset($zdata);
}
elseif ((!$isDir) && (!$isSymlink))
{
if ($isVirtual)
{
if (!$this->_useSplitZIP)
{
// Just dump the data
$this->_fwrite($this->fp, $sourceNameOrData);
if ($this->getError())
{
return false;
}
}
else
{
// Split JPA. Check if we need to split the part in the middle of the data.
clearstatcache();
$current_part_size = @filesize($this->_dataFileName);
$free_space = $this->_fragmentSize - ($current_part_size === false ? 0 : $current_part_size);
if ($free_space >= akstringlen($sourceNameOrData))
{
// Write in one part
$this->_fwrite($this->fp, $sourceNameOrData);
if ($this->getError())
{
return false;
}
}
else
{
$bytes_left = akstringlen($sourceNameOrData);
while ($bytes_left > 0)
{
clearstatcache();
$current_part_size = @filesize($this->_dataFileName);
$free_space = $this->_fragmentSize - ($current_part_size === false ? 0 : $current_part_size);
// Split between parts - Write first part
$this->_fwrite($this->fp, $sourceNameOrData, min(akstringlen($sourceNameOrData), $free_space));
if ($this->getError())
{
return false;
}
// Get the rest of the data
$rest_size = akstringlen($sourceNameOrData) - $free_space;
if ($rest_size > 0)
{
$this->_fclose($this->fp);
$this->fp = null;
// Create new part
if (!$this->_createNewPart())
{
// Die if we couldn't create the new part
$this->setError('Could not create new JPA part file ' . basename($this->_dataFileName));
return false;
}
else
{
// Open data file for output
$this->fp = $this->_fopen($this->_dataFileName, "ab");
if ($this->fp === false)
{
$this->fp = null;
$this->setError("Could not open archive file {$this->_dataFileName} for append!");
return false;
}
}
$zdata = substr($sourceNameOrData, -$rest_size);
}
$bytes_left = $rest_size;
} // end while
}
}
}
else
{
// IMPORTANT! Only this case can be spanned across steps: uncompressed, non-virtual data
// Load cached data if we're resuming file packing
if ($configuration->get('volatile.engine.archiver.processingfile', false))
{
$sourceNameOrData = $configuration->get('volatile.engine.archiver.sourceNameOrData', '');
$unc_len = $configuration->get('volatile.engine.archiver.unc_len', 0);
$resume = $configuration->get('volatile.engine.archiver.resume', 0);
}
// Copy the file contents, ignore directories
$zdatafp = @fopen($sourceNameOrData, "rb");
if ($zdatafp === false)
{
$this->setWarning('Unreadable file ' . $sourceNameOrData . '. Check permissions');
return false;
}
else
{
// Seek to the resume point if required
if ($configuration->get('volatile.engine.archiver.processingfile', false))
{
// Seek to new offset
$seek_result = @fseek($zdatafp, $resume);
if ($seek_result === -1)
{
// What?! We can't resume!
$this->setError(sprintf('Could not resume packing of file %s. Your archive is damaged!', $sourceNameOrData));
@fclose($zdatafp);
return false;
}
// Doctor the uncompressed size to match the remainder of the data
$unc_len = $unc_len - $resume;
}
if (!$this->_useSplitZIP)
{
while (!feof($zdatafp) && ($timer->getTimeLeft() > 0) && ($unc_len > 0))
{
$zdata = fread($zdatafp, AKEEBA_CHUNK);
$this->_fwrite($this->fp, $zdata, min(akstringlen($zdata), AKEEBA_CHUNK));
$unc_len -= min(akstringlen($zdata), AKEEBA_CHUNK);
if ($this->getError())
{
@fclose($zdatafp);
return false;
}
}
// WARNING!!! The extra $unc_len != 0 check is necessary as PHP won't reach EOF for 0-byte files.
if (!feof($zdatafp) && ($unc_len != 0))
{
// We have to break, or we'll time out!
$resume = @ftell($zdatafp);
$configuration->set('volatile.engine.archiver.resume', $resume);
$configuration->set('volatile.engine.archiver.processingfile', true);
@fclose($zdatafp);
return true;
}
}
else
{
// Split JPA - Do we have enough space to host the whole file?
clearstatcache();
$current_part_size = @filesize($this->_dataFileName);
$free_space = $this->_fragmentSize - ($current_part_size === false ? 0 : $current_part_size);
if ($free_space >= $unc_len)
{
// Yes, it will fit inside this part, do quick copy
while (!feof($zdatafp) && ($timer->getTimeLeft() > 0) && ($unc_len > 0))
{
$zdata = fread($zdatafp, AKEEBA_CHUNK);
$this->_fwrite($this->fp, $zdata, min(akstringlen($zdata), AKEEBA_CHUNK));
//$unc_len -= min(akstringlen($zdata), AKEEBA_CHUNK);
$unc_len -= AKEEBA_CHUNK;
if ($this->getError())
{
@fclose($zdatafp);
return false;
}
}
//if(!feof($zdatafp) && ($unc_len != 0))
if (!feof($zdatafp) && ($unc_len > 0))
{
// We have to break, or we'll time out!
$resume = @ftell($zdatafp);
$configuration->set('volatile.engine.archiver.resume', $resume);
$configuration->set('volatile.engine.archiver.processingfile', true);
@fclose($zdatafp);
return true;
}
}
else
{
// No, we'll have to split between parts. We'll loop until we run
// out of space.
while (!feof($zdatafp) && ($timer->getTimeLeft() > 0))
{
clearstatcache();
$current_part_size = @filesize($this->_dataFileName);
$free_space = $this->_fragmentSize - ($current_part_size === false ? 0 : $current_part_size);
// Find optimal chunk size
$chunk_size_primary = min(AKEEBA_CHUNK, $free_space);
if ($chunk_size_primary <= 0)
{
$chunk_size_primary = max(AKEEBA_CHUNK, $free_space);
}
// Calculate if we have to read some more data (smaller chunk size)
// and how many times we must read w/ the primary chunk size
$chunk_size_secondary = $free_space % $chunk_size_primary;
$loop_times = ($free_space - $chunk_size_secondary) / $chunk_size_primary;
// Read and write with the primary chunk size
for ($i = 1; $i <= $loop_times; $i++)
{
$zdata = fread($zdatafp, $chunk_size_primary);
$this->_fwrite($this->fp, $zdata, min(akstringlen($zdata), $chunk_size_primary));
//$unc_len -= min(akstringlen($zdata), $chunk_size_primary);
$unc_len -= $chunk_size_primary;
if ($this->getError())
{
@fclose($zdatafp);
return false;
}
// Do we have enough time to proceed?
//if( (!feof($zdatafp)) && ($unc_len != 0) && ($timer->getTimeLeft() <= 0) ) {
if ((!feof($zdatafp)) && ($unc_len >= 0) && ($timer->getTimeLeft() <= 0))
{
// No, we have to break, or we'll time out!
$resume = @ftell($zdatafp);
$configuration->set('volatile.engine.archiver.resume', $resume);
$configuration->set('volatile.engine.archiver.processingfile', true);
@fclose($zdatafp);
return true;
}
}
// Read and write w/ secondary chunk size, if non-zero
if ($chunk_size_secondary > 0)
{
$zdata = fread($zdatafp, $chunk_size_secondary);
$this->_fwrite($this->fp, $zdata, min(akstringlen($zdata), $chunk_size_secondary));
//$unc_len -= min(akstringlen($zdata), $chunk_size_secondary);
$unc_len -= $chunk_size_secondary;
if ($this->getError())
{
@fclose($zdatafp);
return false;
}
}
// Do we have enough time to proceed?
//if( (!feof($zdatafp)) && ($unc_len != 0) && ($timer->getTimeLeft() <= 0) ) {
if ((!feof($zdatafp)) && ($unc_len >= 0) && ($timer->getTimeLeft() <= 0))
{
// No, we have to break, or we'll time out!
$resume = @ftell($zdatafp);
$configuration->set('volatile.engine.archiver.resume', $resume);
$configuration->set('volatile.engine.archiver.processingfile', true);
// ...and create a new part as well
if (!$this->_createNewPart())
{
// Die if we couldn't create the new part
$this->setError('Could not create new JPA part file ' . basename($this->_dataFileName));
@fclose($zdatafp);
return false;
}
// ...then, return
@fclose($zdatafp);
return true;
}
// Create new JPA part, but only if we'll have more data to write
//if(!feof($zdatafp) && ($unc_len != 0) && ($unc_len > 0) )
if (!feof($zdatafp) && ($unc_len > 0))
{
$this->_fclose($this->fp);
$this->fp = null;
if (!$this->_createNewPart())
{
// Die if we couldn't create the new part
$this->setError('Could not create new JPA part file ' . basename($this->_dataFileName));
@fclose($zdatafp);
return false;
}
else
{
// We have created the part. If the user asked for immediate post-proc, break step now.
if ($configuration->get('engine.postproc.common.after_part', 0))
{
$resume = @ftell($zdatafp);
$configuration->set('volatile.engine.archiver.resume', $resume);
$configuration->set('volatile.engine.archiver.processingfile', true);
$configuration->set('volatile.breakflag', true);
@fclose($zdatafp);
return true;
}
// Open data file for output
$this->fp = $this->_fopen($this->_dataFileName, "ab");
if ($this->fp === false)
{
$this->setError("Could not open archive file {$this->_dataFileName} for append!");
@fclose($zdatafp);
return false;
}
}
}
} // end while
}
}
@fclose($zdatafp);
}
}
}
elseif ($isSymlink)
{
$this->_fwrite($this->fp, @readlink($sourceNameOrData));
}
//AEUtilLogger::WriteLog(_AE_LOG_DEBUG, "DEBUG -- Added $targetName to archive");
// Uncache data
$configuration->set('volatile.engine.archiver.sourceNameOrData', null);
$configuration->set('volatile.engine.archiver.unc_len', null);
$configuration->set('volatile.engine.archiver.resume', null);
$configuration->set('volatile.engine.archiver.processingfile', false);
// ... and return TRUE = success
return true;
}
// ------------------------------------------------------------------------
// Archiver-specific utility functions
// ------------------------------------------------------------------------
/**
* Outputs a Standard Header at the top of the file
*
*/
private function _writeArchiveHeader()
{
if (!is_null($this->fp))
{
$this->_fclose($this->fp);
$this->fp = null;
}
$this->fp = $this->_fopen($this->_dataFileName, 'cb');
if ($this->fp === false)
{
$this->setError('Could not open ' . $this->_dataFileName . ' for writing. Check permissions and open_basedir restrictions.');
return false;
}
// Calculate total header size
$headerSize = 19; // Standard Header
if ($this->_useSplitZIP)
{
// Spanned JPA header
$headerSize += 8;
}
$this->_fwrite($this->fp, $this->_archive_signature); // ID string (JPA)
if ($this->getError())
{
return false;
}
$this->_fwrite($this->fp, pack('v', $headerSize)); // Header length; fixed to 19 bytes
$this->_fwrite($this->fp, pack('C', _JPA_MAJOR)); // Major version
$this->_fwrite($this->fp, pack('C', _JPA_MINOR)); // Minor version
$this->_fwrite($this->fp, pack('V', $this->_fileCount)); // File count
$this->_fwrite($this->fp, pack('V', $this->_uncompressedSize)); // Size of files when extracted
$this->_fwrite($this->fp, pack('V', $this->_compressedSize)); // Size of files when stored
// Do I need to add a split archive's header too?
if ($this->_useSplitZIP)
{
$this->_fwrite($this->fp, $this->_extraHeaderSplit); // Signature
$this->_fwrite($this->fp, pack('v', 4)); // Extra field length
$this->_fwrite($this->fp, pack('v', $this->_totalFragments)); // Number of parts
}
$this->_fclose($this->fp);
if (function_exists('chmod'))
{
@chmod($this->_dataFileName, 0755);
}
}
private function _createNewPart($finalPart = false)
{
// Close any open file pointers
if (is_resource($this->fp))
{
$this->_fclose($this->fp);
}
if (is_resource($this->cdfp))
{
$this->_fclose($this->cdfp);
}
// Remove the just finished part from the list of resumable offsets
$this->_removeFromOffsetsList($this->_dataFileName);
// Set the file pointers to null
$this->fp = null;
$this->cdfp = null;
// Push the previous part if we have to post-process it immediately
$configuration = AEFactory::getConfiguration();
if ($configuration->get('engine.postproc.common.after_part', 0))
{
// The first part needs its header overwritten during archive
// finalization. Skip it from immediate processing.
if ($this->_currentFragment != 1)
{
$this->finishedPart[] = $this->_dataFileName;
}
}
$this->_totalFragments++;
$this->_currentFragment = $this->_totalFragments;
if ($finalPart)
{
$this->_dataFileName = $this->_dataFileNameBase . '.jpa';
}
else
{
$this->_dataFileName = $this->_dataFileNameBase . '.j' . sprintf('%02d', $this->_currentFragment);
}
AEUtilLogger::WriteLog(_AE_LOG_INFO, 'Creating new JPA part #' . $this->_currentFragment . ', file ' . $this->_dataFileName);
$statistics = AEFactory::getStatistics();
$statistics->updateMultipart($this->_totalFragments);
// Try to remove any existing file
@unlink($this->_dataFileName);
// Touch the new file
$result = @touch($this->_dataFileName);
if (function_exists('chmod'))
{
chmod($this->_dataFileName, 0666);
}
// Try to write 6 bytes to it
if ($result)
{
$result = @file_put_contents($this->_dataFileName, 'AKEEBA') == 6;
}
if ($result)
{
@unlink($this->_dataFileName);
$result = @touch($this->_dataFileName);
if (function_exists('chmod'))
{
chmod($this->_dataFileName, 0666);
}
}
return $result;
}
}