private function TarArchiveReader::extractAllToDirectory in Backup and Migrate 5.0.x
Parameters
$directory: The directory to extract the files to.
Return value
bool
Throws
\Drupal\backup_migrate\Core\Exception\BackupMigrateException
1 call to TarArchiveReader::extractAllToDirectory()
- TarArchiveReader::extractTo in src/
Core/ Service/ TarArchiveReader.php - Extract all files to the given directory.
File
- src/
Core/ Service/ TarArchiveReader.php, line 64
Class
- TarArchiveReader
- @package Drupal\backup_migrate\Core\Service
Namespace
Drupal\backup_migrate\Core\ServiceCode
private function extractAllToDirectory($directory) {
clearstatcache();
// Read a header block.
while (strlen($block = $this->archive
->readBytes(512)) != 0) {
$header = $this
->readHeader($block);
if (!$header) {
return FALSE;
}
if ($header['filename'] == '') {
continue;
}
// Check for potentially malicious files (containing '..' etc.).
if ($this
->maliciousFilename($header['filename'])) {
throw new BackupMigrateException('Malicious .tar detected, file %filename. Will not install in desired directory tree', [
'%filename' => $header['filename'],
]);
}
// Ignore extended / pax headers.
if ($header['typeflag'] == 'x' || $header['typeflag'] == 'g') {
$this->archive
->seekBytes(ceil($header['size'] / 512));
continue;
}
// Add the destination directory to the path.
if (substr($header['filename'], 0, 1) == '/') {
$header['filename'] = $directory . $header['filename'];
}
else {
$header['filename'] = $directory . '/' . $header['filename'];
}
// If the file already exists, make sure we can overwrite it.
if (file_exists($header['filename'])) {
// Cannot overwrite a directory with a file.
if (@is_dir($header['filename']) && $header['typeflag'] == '') {
throw new BackupMigrateException('File %filename already exists as a directory', [
'%filename' => $header['filename'],
]);
}
// Cannot overwrite a file with a directory.
if (@is_file($header['filename']) && !@is_link($header['filename']) && $header['typeflag'] == "5") {
throw new BackupMigrateException('Directory %filename already exists as file', [
'%filename' => $header['filename'],
]);
}
// Cannot overwrite a read-only file.
if (!is_writable($header['filename'])) {
throw new BackupMigrateException('File %filename already exists and is write protected', [
'%filename' => $header['filename'],
]);
}
}
// Extract a directory.
if ($header['typeflag'] == "5") {
if (!$this
->createDir($header['filename'])) {
throw new BackupMigrateException('Unable to create directory %filename', [
'%filename' => $header['filename'],
]);
}
}
else {
if (!$this
->createDir(dirname($header['filename']))) {
throw new BackupMigrateException('Unable to create directory for %filename', [
'%filename' => $header['filename'],
]);
}
// Symlink.
if ($header['typeflag'] == "2") {
if (@file_exists($header['filename'])) {
@unlink($header['filename']);
}
if (!@symlink($header['link'], $header['filename'])) {
throw new BackupMigrateException('Unable to extract symbolic link: %filename', [
'%filename' => $header['filename'],
]);
}
}
else {
// Open the file for writing.
if (($dest_file = @fopen($header['filename'], "wb")) == 0) {
throw new BackupMigrateException('Error while opening %filename in write binary mode', [
'%filename' => $header['filename'],
]);
}
// Write the file.
$n = floor($header['size'] / 512);
for ($i = 0; $i < $n; $i++) {
$content = $this->archive
->readBytes(512);
fwrite($dest_file, $content, 512);
}
if ($header['size'] % 512 != 0) {
$content = $this->archive
->readBytes(512);
fwrite($dest_file, $content, $header['size'] % 512);
}
@fclose($dest_file);
// Change the file mode, mtime.
@touch($header['filename'], $header['mtime']);
if ($header['mode'] & 0111) {
// Make file executable, obey umask.
$mode = fileperms($header['filename']) | ~umask() & 0111;
@chmod($header['filename'], $mode);
}
clearstatcache();
// Check if the file exists.
if (!is_file($header['filename'])) {
throw new BackupMigrateException('Extracted file %filename does not exist. Archive may be corrupted.', [
'%filename' => $header['filename'],
]);
}
// Check the file size.
$file_size = filesize($header['filename']);
if ($file_size != $header['size']) {
throw new BackupMigrateException('Extracted file %filename does not have the correct file size. File is %actual bytes (%expected bytes expected). Archive may be corrupted', [
'%filename' => $header['filename'],
'%expected' => (int) $header['size'],
(int) '%actual' => $file_size,
]);
}
}
}
}
return TRUE;
}