diff --git a/README.md b/README.md index 37995ba..482cb2f 100644 --- a/README.md +++ b/README.md @@ -32,6 +32,7 @@ ArchiveInfo (extends ArchiveReader) Example class that provides a facade for all the readers in the library, and also allows recursive inspection of archives packed within archives. +- 2.0 Improved error reporting for recursive extraction - 1.9 Added support for recursive extraction using external clients - 1.8 Restricted stored archives to supported types only - 1.7 Added ability to reset the readers list dynamically diff --git a/archiveinfo.php b/archiveinfo.php index 7210788..740fb3c 100644 --- a/archiveinfo.php +++ b/archiveinfo.php @@ -72,7 +72,7 @@ * @author Hecks * @copyright (c) 2010-2013 Hecks * @license Modified BSD - * @version 1.9 + * @version 2.0 */ class ArchiveInfo extends ArchiveReader { @@ -183,9 +183,6 @@ public function getSummary($full=false) 'data_size' => $this->dataSize, 'use_range' => "{$this->start}-{$this->end}", ); - if ($this->error) { - $summary['error'] = $this->error; - } if ($this->reader) { $args = func_get_args(); $summary += $this->__call('getSummary', $args); @@ -196,6 +193,9 @@ public function getSummary($full=false) if ($this->tempFiles) { $summary['temp_files'] = array_keys($this->tempFiles); } + if ($this->error) { + $summary['error'] = $this->error; + } return $summary; } @@ -278,7 +278,8 @@ public function containsArchive() */ public function canExtract() { - return $this->reader && !empty($this->externalClients[$this->type]); + return $this->reader && (!empty($this->externalClients[$this->type]) + || !empty($this->reader->externalClient)); } /** @@ -355,9 +356,13 @@ public function getArchive($filename) @chmod($temp, 0777); $this->tempFiles[$hash] = $temp; } - $archive->open($temp, $this->isFragment); - $archive->isTemporary = true; - + if ($this->reader->error) { + $archive->error = $this->reader->error; + $archive->readers = array(); + } else { + $archive->open($temp, $this->isFragment); + $archive->isTemporary = true; + } return $archive; } @@ -537,7 +542,7 @@ public function extractFile($filename, $destination=null, $password=null, $sourc { // Check that a valid reader is available if (!($archive = $this->getArchiveFromSource($source)) || !($reader = $archive->reader)) { - $this->error = "Archive source does exist: {$source}"; + $this->error = "Not a valid archive source: {$source}"; return false; } if (!method_exists($reader, 'extractFile')) { diff --git a/tests/ArchiveInfoTest.php b/tests/ArchiveInfoTest.php index cce3008..3dbfa36 100644 --- a/tests/ArchiveInfoTest.php +++ b/tests/ArchiveInfoTest.php @@ -845,4 +845,44 @@ public function testExtractsEmbeddedFilesWithMultipleExternalClients() $this->assertSame('entry #1', $text); } + /** + * Some recursion errors using external clients can be difficult to debug, so + * we should be able to report any error messages in the archive listings. + * + * @depends testExtractsEmbeddedFilesWithMultipleExternalClients + * @group external + */ + public function testReportsErrorsWithRecursiveExtraction() + { + if (!($unzip = $this->get7zPath())) { + $this->markTestSkipped(); + } + $archive = new ArchiveInfo; + + $archive->setReaders(array( + ArchiveInfo::TYPE_RAR => 'TestRarInfo', + ArchiveInfo::TYPE_ZIP => 'ZipInfo', + ), true); + + $archive->setExternalClients(array( + ArchiveInfo::TYPE_ZIP => $unzip, + )); + + $archive->open($this->fixturesDir.'/misc/misc_comp_in_rar.rar'); + $this->assertEmpty($archive->error); + $files = $archive->getArchiveFileList(true); + $this->assertCount(6, $files); + $this->assertArrayHasKey('error', $files[5]); + $this->assertSame('main > zip_comp_in_rar.rar > pecl_test.zip', $files[5]['source']); + $summary = $archive->getSummary(true); + $this->assertArrayHasKey('error', $summary['archives']['zip_comp_in_rar.rar']); + $this->assertArrayHasKey('error', $summary['archives']['zip_comp_in_rar.rar']['archives']['pecl_test.zip']); + } + } // End ArchiveInfoTest + +class TestRarInfo extends RarInfo +{ + // Made public for test convenience + public $externalClient = 'does_not_exist.exe'; +}