2
0

ZipFileTest.php 69 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128
  1. <?php
  2. namespace PhpZip;
  3. use PhpZip\Model\ZipEntry;
  4. use PhpZip\Model\ZipInfo;
  5. use PhpZip\Util\CryptoUtil;
  6. use PhpZip\Util\FilesUtil;
  7. use Psr\Http\Message\ResponseInterface;
  8. /**
  9. * ZipFile test
  10. */
  11. class ZipFileTest extends ZipTestCase
  12. {
  13. /**
  14. * @expectedException \PhpZip\Exception\InvalidArgumentException
  15. * @expectedExceptionMessage can't exists
  16. */
  17. public function testOpenFileCantExists()
  18. {
  19. $zipFile = new ZipFile();
  20. $zipFile->openFile(uniqid());
  21. }
  22. /**
  23. * @expectedException \PhpZip\Exception\ZipException
  24. * @expectedExceptionMessage can't open
  25. */
  26. public function testOpenFileCantOpen()
  27. {
  28. self::assertNotFalse(file_put_contents($this->outputFilename, 'content'));
  29. self::assertTrue(chmod($this->outputFilename, 0222));
  30. $zipFile = new ZipFile();
  31. $zipFile->openFile($this->outputFilename);
  32. }
  33. /**
  34. * @expectedException \PhpZip\Exception\ZipException
  35. * @expectedExceptionMessage Invalid zip file
  36. */
  37. public function testOpenFileEmptyFile()
  38. {
  39. self::assertNotFalse(touch($this->outputFilename));
  40. $zipFile = new ZipFile();
  41. $zipFile->openFile($this->outputFilename);
  42. }
  43. /**
  44. * @expectedException \PhpZip\Exception\ZipException
  45. * @expectedExceptionMessage Expected Local File Header or (ZIP64) End Of Central Directory Record
  46. */
  47. public function testOpenFileInvalidZip()
  48. {
  49. self::assertNotFalse(file_put_contents($this->outputFilename, CryptoUtil::randomBytes(255)));
  50. $zipFile = new ZipFile();
  51. $zipFile->openFile($this->outputFilename);
  52. }
  53. /**
  54. * @expectedException \PhpZip\Exception\InvalidArgumentException
  55. * @expectedExceptionMessage Data not available
  56. */
  57. public function testOpenFromStringNullString()
  58. {
  59. $zipFile = new ZipFile();
  60. $zipFile->openFromString(null);
  61. }
  62. /**
  63. * @expectedException \PhpZip\Exception\InvalidArgumentException
  64. * @expectedExceptionMessage Data not available
  65. */
  66. public function testOpenFromStringEmptyString()
  67. {
  68. $zipFile = new ZipFile();
  69. $zipFile->openFromString("");
  70. }
  71. /**
  72. * @expectedException \PhpZip\Exception\ZipException
  73. * @expectedExceptionMessage Expected Local File Header or (ZIP64) End Of Central Directory Record
  74. */
  75. public function testOpenFromStringInvalidZip()
  76. {
  77. $zipFile = new ZipFile();
  78. $zipFile->openFromString(CryptoUtil::randomBytes(255));
  79. }
  80. public function testOpenFromString()
  81. {
  82. $zipFile = new ZipFile();
  83. $zipFile->addFromString('file', 'content');
  84. $zipFile['file2'] = 'content 2';
  85. $zipContents = $zipFile->outputAsString();
  86. $zipFile->close();
  87. $zipFile->openFromString($zipContents);
  88. self::assertEquals($zipFile->count(), 2);
  89. self::assertTrue(isset($zipFile['file']));
  90. self::assertTrue(isset($zipFile['file2']));
  91. self::assertEquals($zipFile['file'], 'content');
  92. self::assertEquals($zipFile['file2'], 'content 2');
  93. $zipFile->close();
  94. }
  95. /**
  96. * @expectedException \PhpZip\Exception\InvalidArgumentException
  97. * @expectedExceptionMessage Invalid stream resource
  98. */
  99. public function testOpenFromStreamNullStream()
  100. {
  101. $zipFile = new ZipFile();
  102. $zipFile->openFromStream(null);
  103. }
  104. /**
  105. * @expectedException \PhpZip\Exception\InvalidArgumentException
  106. * @expectedExceptionMessage Invalid stream resource
  107. */
  108. public function testOpenFromStreamInvalidResourceType()
  109. {
  110. $zipFile = new ZipFile();
  111. /** @noinspection PhpParamsInspection */
  112. $zipFile->openFromStream("stream resource");
  113. }
  114. /**
  115. * @expectedException \PhpZip\Exception\InvalidArgumentException
  116. * @expectedExceptionMessage Invalid resource type - gd.
  117. */
  118. public function testOpenFromStreamInvalidResourceType2()
  119. {
  120. $zipFile = new ZipFile();
  121. if (!extension_loaded("gd")) {
  122. $this->markTestSkipped('not extension gd');
  123. }
  124. $zipFile->openFromStream(imagecreate(1, 1));
  125. }
  126. /**
  127. * @expectedException \PhpZip\Exception\InvalidArgumentException
  128. * @expectedExceptionMessage Invalid stream type - dir.
  129. */
  130. public function testOpenFromStreamInvalidResourceType3()
  131. {
  132. $zipFile = new ZipFile();
  133. $zipFile->openFromStream(opendir(__DIR__));
  134. }
  135. /**
  136. * @expectedException \PhpZip\Exception\InvalidArgumentException
  137. * @expectedExceptionMessage Resource cannot seekable stream.
  138. */
  139. public function testOpenFromStreamNoSeekable()
  140. {
  141. if (!$fp = @fopen("http://localhost", 'r')) {
  142. if (!$fp = @fopen("http://example.org", 'r')) {
  143. $this->markTestSkipped('not connected to localhost or remote host');
  144. return;
  145. }
  146. }
  147. $zipFile = new ZipFile();
  148. $zipFile->openFromStream($fp);
  149. }
  150. /**
  151. * @expectedException \PhpZip\Exception\ZipException
  152. * @expectedExceptionMessage Invalid zip file
  153. */
  154. public function testOpenFromStreamEmptyContents()
  155. {
  156. $fp = fopen($this->outputFilename, 'w+b');
  157. $zipFile = new ZipFile();
  158. $zipFile->openFromStream($fp);
  159. }
  160. /**
  161. * @expectedException \PhpZip\Exception\ZipException
  162. * @expectedExceptionMessage Expected Local File Header or (ZIP64) End Of Central Directory Record
  163. */
  164. public function testOpenFromStreamInvalidZip()
  165. {
  166. $fp = fopen($this->outputFilename, 'w+b');
  167. fwrite($fp, CryptoUtil::randomBytes(255));
  168. $zipFile = new ZipFile();
  169. $zipFile->openFromStream($fp);
  170. }
  171. public function testOpenFromStream()
  172. {
  173. $zipFile = new ZipFile();
  174. $zipFile
  175. ->addFromString('file', 'content')
  176. ->saveAsFile($this->outputFilename)
  177. ->close();
  178. $handle = fopen($this->outputFilename, 'rb');
  179. $zipFile->openFromStream($handle);
  180. self::assertEquals($zipFile->count(), 1);
  181. self::assertTrue(isset($zipFile['file']));
  182. self::assertEquals($zipFile['file'], 'content');
  183. $zipFile->close();
  184. }
  185. /**
  186. * Test create, open and extract empty archive.
  187. */
  188. public function testEmptyArchive()
  189. {
  190. $zipFile = new ZipFile();
  191. $zipFile
  192. ->saveAsFile($this->outputFilename)
  193. ->close();
  194. self::assertCorrectEmptyZip($this->outputFilename);
  195. self::assertTrue(mkdir($this->outputDirname, 0755, true));
  196. $zipFile->openFile($this->outputFilename);
  197. self::assertEquals($zipFile->count(), 0);
  198. $zipFile
  199. ->extractTo($this->outputDirname)
  200. ->close();
  201. self::assertTrue(FilesUtil::isEmptyDir($this->outputDirname));
  202. }
  203. /**
  204. * No modified archive
  205. *
  206. * @see ZipOutputFile::create()
  207. */
  208. public function testNoModifiedArchive()
  209. {
  210. self::assertTrue(mkdir($this->outputDirname, 0755, true));
  211. $fileActual = $this->outputDirname . DIRECTORY_SEPARATOR . 'file_actual.zip';
  212. $fileExpected = $this->outputDirname . DIRECTORY_SEPARATOR . 'file_expected.zip';
  213. $zipFile = new ZipFile();
  214. $zipFile->addDirRecursive(__DIR__.'/../../src');
  215. $sourceCount = $zipFile->count();
  216. self::assertTrue($sourceCount > 0);
  217. $zipFile
  218. ->saveAsFile($fileActual)
  219. ->close();
  220. self::assertCorrectZipArchive($fileActual);
  221. $zipFile
  222. ->openFile($fileActual)
  223. ->saveAsFile($fileExpected);
  224. self::assertCorrectZipArchive($fileExpected);
  225. $zipFileExpected = new ZipFile();
  226. $zipFileExpected->openFile($fileExpected);
  227. self::assertEquals($zipFile->count(), $sourceCount);
  228. self::assertEquals($zipFileExpected->count(), $zipFile->count());
  229. self::assertEquals($zipFileExpected->getListFiles(), $zipFile->getListFiles());
  230. foreach ($zipFile as $entryName => $content) {
  231. self::assertEquals($zipFileExpected[$entryName], $content);
  232. }
  233. $zipFileExpected->close();
  234. $zipFile->close();
  235. }
  236. /**
  237. * Create archive and add files.
  238. *
  239. * @see ZipOutputFile::addFromString()
  240. * @see ZipOutputFile::addFromFile()
  241. * @see ZipOutputFile::addFromStream()
  242. * @see ZipFile::getEntryContents()
  243. */
  244. public function testCreateArchiveAndAddFiles()
  245. {
  246. $outputFromString = file_get_contents(__FILE__);
  247. $outputFromString2 = file_get_contents(dirname(dirname(__DIR__)) . DIRECTORY_SEPARATOR . 'README.md');
  248. $outputFromFile = file_get_contents(dirname(dirname(__DIR__)) . DIRECTORY_SEPARATOR . 'phpunit.xml');
  249. $outputFromStream = file_get_contents(dirname(dirname(__DIR__)) . DIRECTORY_SEPARATOR . 'composer.json');
  250. $filenameFromString = basename(__FILE__);
  251. $filenameFromString2 = 'test_file.txt';
  252. $filenameFromFile = 'data/test file.txt';
  253. $filenameFromStream = 'data/ডিরেক্টরি/αρχείο.json';
  254. $emptyDirName = 'empty dir/пустой каталог/空目錄/ไดเรกทอรีที่ว่างเปล่า/';
  255. $emptyDirName2 = 'empty dir/пустой каталог/';
  256. $emptyDirName3 = 'empty dir/пустой каталог/ещё один пустой каталог/';
  257. $tempFile = tempnam(sys_get_temp_dir(), 'txt');
  258. file_put_contents($tempFile, $outputFromFile);
  259. $tempStream = tmpfile();
  260. fwrite($tempStream, $outputFromStream);
  261. $zipFile = new ZipFile;
  262. $zipFile
  263. ->addFromString($filenameFromString, $outputFromString)
  264. ->addFile($tempFile, $filenameFromFile)
  265. ->addFromStream($tempStream, $filenameFromStream)
  266. ->addEmptyDir($emptyDirName);
  267. $zipFile[$filenameFromString2] = $outputFromString2;
  268. $zipFile[$emptyDirName2] = null;
  269. $zipFile[$emptyDirName3] = 'this content ignoring';
  270. self::assertEquals(count($zipFile), 7);
  271. $zipFile
  272. ->saveAsFile($this->outputFilename)
  273. ->close();
  274. unlink($tempFile);
  275. self::assertCorrectZipArchive($this->outputFilename);
  276. $zipFile->openFile($this->outputFilename);
  277. self::assertEquals(count($zipFile), 7);
  278. self::assertEquals($zipFile[$filenameFromString], $outputFromString);
  279. self::assertEquals($zipFile[$filenameFromFile], $outputFromFile);
  280. self::assertEquals($zipFile[$filenameFromStream], $outputFromStream);
  281. self::assertEquals($zipFile[$filenameFromString2], $outputFromString2);
  282. self::assertTrue(isset($zipFile[$emptyDirName]));
  283. self::assertTrue(isset($zipFile[$emptyDirName2]));
  284. self::assertTrue(isset($zipFile[$emptyDirName3]));
  285. self::assertTrue($zipFile->isDirectory($emptyDirName));
  286. self::assertTrue($zipFile->isDirectory($emptyDirName2));
  287. self::assertTrue($zipFile->isDirectory($emptyDirName3));
  288. $listFiles = $zipFile->getListFiles();
  289. self::assertEquals($listFiles[0], $filenameFromString);
  290. self::assertEquals($listFiles[1], $filenameFromFile);
  291. self::assertEquals($listFiles[2], $filenameFromStream);
  292. self::assertEquals($listFiles[3], $emptyDirName);
  293. self::assertEquals($listFiles[4], $filenameFromString2);
  294. self::assertEquals($listFiles[5], $emptyDirName2);
  295. self::assertEquals($listFiles[6], $emptyDirName3);
  296. $zipFile->close();
  297. }
  298. public function testEmptyContent()
  299. {
  300. $zipFile = new ZipFile();
  301. $zipFile['file'] = '';
  302. $zipFile->saveAsFile($this->outputFilename);
  303. $zipFile->close();
  304. $zipFile->openFile($this->outputFilename);
  305. self::assertEquals($zipFile['file'], '');
  306. $zipFile->close();
  307. }
  308. /**
  309. * Test compression method from image file.
  310. */
  311. public function testCompressionMethodFromImageMimeType()
  312. {
  313. if (!function_exists('mime_content_type')) {
  314. $this->markTestSkipped('Function mime_content_type not exists');
  315. }
  316. $outputFilename = $this->outputFilename;
  317. $this->outputFilename .= '.gif';
  318. self::assertNotFalse(
  319. file_put_contents(
  320. $this->outputFilename,
  321. base64_decode('R0lGODlhAQABAJAAAP8AAAAAACH5BAUQAAAALAAAAAABAAEAAAICBAEAOw==')
  322. )
  323. );
  324. $basename = basename($this->outputFilename);
  325. $zipFile = new ZipFile();
  326. $zipFile->addFile($this->outputFilename, $basename);
  327. $zipFile->saveAsFile($outputFilename);
  328. unlink($this->outputFilename);
  329. $this->outputFilename = $outputFilename;
  330. $zipFile->openFile($this->outputFilename);
  331. $info = $zipFile->getEntryInfo($basename);
  332. self::assertEquals($info->getMethodName(), 'No compression');
  333. $zipFile->close();
  334. }
  335. /**
  336. * Rename zip entry name.
  337. */
  338. public function testRename()
  339. {
  340. $oldName = basename(__FILE__);
  341. $newName = 'tests/' . $oldName;
  342. $zipFile = new ZipFile();
  343. $zipFile->addDir(__DIR__);
  344. $zipFile->saveAsFile($this->outputFilename);
  345. $zipFile->close();
  346. self::assertCorrectZipArchive($this->outputFilename);
  347. $zipFile->openFile($this->outputFilename);
  348. $zipFile->rename($oldName, $newName);
  349. $zipFile->addFromString('file1.txt', 'content');
  350. $zipFile->rename('file1.txt', 'file2.txt');
  351. $zipFile->saveAsFile($this->outputFilename);
  352. $zipFile->close();
  353. self::assertCorrectZipArchive($this->outputFilename);
  354. $zipFile->openFile($this->outputFilename);
  355. self::assertFalse(isset($zipFile[$oldName]));
  356. self::assertTrue(isset($zipFile[$newName]));
  357. self::assertFalse(isset($zipFile['file1.txt']));
  358. self::assertTrue(isset($zipFile['file2.txt']));
  359. $zipFile->close();
  360. }
  361. /**
  362. * @expectedException \PhpZip\Exception\InvalidArgumentException
  363. * @expectedExceptionMessage name is null
  364. */
  365. public function testRenameEntryNull()
  366. {
  367. $zipFile = new ZipFile();
  368. $zipFile->rename(null, 'new-file');
  369. }
  370. /**
  371. * @expectedException \PhpZip\Exception\InvalidArgumentException
  372. * @expectedExceptionMessage name is null
  373. */
  374. public function testRenameEntryNull2()
  375. {
  376. $zipFile = new ZipFile();
  377. $zipFile->rename('old-file', null);
  378. }
  379. /**
  380. * @expectedException \PhpZip\Exception\InvalidArgumentException
  381. * @expectedExceptionMessage is exists
  382. */
  383. public function testRenameEntryNewEntyExists()
  384. {
  385. $zipFile = new ZipFile();
  386. $zipFile['file'] = 'content';
  387. $zipFile['file2'] = 'content 2';
  388. $zipFile->saveAsFile($this->outputFilename);
  389. $zipFile->close();
  390. $zipFile = new ZipFile();
  391. $zipFile->openFile($this->outputFilename);
  392. $zipFile->rename('file2', 'file');
  393. }
  394. /**
  395. * @expectedException \PhpZip\Exception\ZipNotFoundEntry
  396. */
  397. public function testRenameEntryNotFound()
  398. {
  399. $zipFile = new ZipFile();
  400. $zipFile['file'] = 'content';
  401. $zipFile['file2'] = 'content 2';
  402. $zipFile->saveAsFile($this->outputFilename);
  403. $zipFile->close();
  404. $zipFile = new ZipFile();
  405. $zipFile->openFile($this->outputFilename);
  406. $zipFile->rename('file2.bak', 'file3');
  407. }
  408. /**
  409. * Delete entry from name.
  410. */
  411. public function testDeleteFromName()
  412. {
  413. $inputDir = dirname(dirname(__DIR__)) . DIRECTORY_SEPARATOR;
  414. $deleteEntryName = 'composer.json';
  415. $zipFile = new ZipFile();
  416. $zipFile->addDir($inputDir);
  417. $zipFile->saveAsFile($this->outputFilename);
  418. $zipFile->close();
  419. self::assertCorrectZipArchive($this->outputFilename);
  420. $zipFile->openFile($this->outputFilename);
  421. $zipFile->deleteFromName($deleteEntryName);
  422. $zipFile->saveAsFile($this->outputFilename);
  423. $zipFile->close();
  424. self::assertCorrectZipArchive($this->outputFilename);
  425. $zipFile->openFile($this->outputFilename);
  426. self::assertFalse(isset($zipFile[$deleteEntryName]));
  427. $zipFile->close();
  428. }
  429. public function testDeleteNewEntry()
  430. {
  431. $zipFile = new ZipFile();
  432. $zipFile['entry1'] = '';
  433. $zipFile['entry2'] = '';
  434. $zipFile->deleteFromName('entry2');
  435. $zipFile->saveAsFile($this->outputFilename);
  436. $zipFile->close();
  437. $zipFile->openFile($this->outputFilename);
  438. self::assertEquals(sizeof($zipFile), 1);
  439. self::assertTrue(isset($zipFile['entry1']));
  440. self::assertFalse(isset($zipFile['entry2']));
  441. $zipFile->close();
  442. }
  443. /**
  444. * @expectedException \PhpZip\Exception\ZipNotFoundEntry
  445. */
  446. public function testDeleteFromNameNotFoundEntry()
  447. {
  448. $zipFile = new ZipFile();
  449. $zipFile->deleteFromName('entry');
  450. }
  451. /**
  452. * Delete zip entries from glob pattern
  453. */
  454. public function testDeleteFromGlob()
  455. {
  456. $inputDir = dirname(dirname(__DIR__));
  457. $zipFile = new ZipFile();
  458. $zipFile->addFilesFromGlobRecursive($inputDir, '**.{xml,json,md}', '/');
  459. self::assertTrue(isset($zipFile['composer.json']));
  460. self::assertTrue(isset($zipFile['phpunit.xml']));
  461. $zipFile->saveAsFile($this->outputFilename);
  462. $zipFile->close();
  463. self::assertCorrectZipArchive($this->outputFilename);
  464. $zipFile->openFile($this->outputFilename);
  465. self::assertTrue(isset($zipFile['composer.json']));
  466. self::assertTrue(isset($zipFile['phpunit.xml']));
  467. $zipFile->deleteFromGlob('**.{xml,json}');
  468. self::assertFalse(isset($zipFile['composer.json']));
  469. self::assertFalse(isset($zipFile['phpunit.xml']));
  470. $zipFile->saveAsFile($this->outputFilename);
  471. $zipFile->close();
  472. self::assertCorrectZipArchive($this->outputFilename);
  473. $zipFile->openFile($this->outputFilename);
  474. self::assertTrue($zipFile->count() > 0);
  475. foreach ($zipFile->getListFiles() as $name) {
  476. self::assertStringEndsWith('.md', $name);
  477. }
  478. $zipFile->close();
  479. }
  480. /**
  481. * @expectedException \PhpZip\Exception\InvalidArgumentException
  482. * @expectedExceptionMessage Glob pattern is empty
  483. */
  484. public function testDeleteFromGlobFailNull()
  485. {
  486. $zipFile = new ZipFile();
  487. $zipFile->deleteFromGlob(null);
  488. }
  489. /**
  490. * @expectedException \PhpZip\Exception\InvalidArgumentException
  491. * @expectedExceptionMessage Glob pattern is empty
  492. */
  493. public function testDeleteFromGlobFailEmpty()
  494. {
  495. $zipFile = new ZipFile();
  496. $zipFile->deleteFromGlob('');
  497. }
  498. /**
  499. * Delete entries from regex pattern
  500. */
  501. public function testDeleteFromRegex()
  502. {
  503. $inputDir = dirname(dirname(__DIR__));
  504. $zipFile = new ZipFile();
  505. $zipFile->addFilesFromRegexRecursive($inputDir, '~\.(xml|json)$~i', 'Path');
  506. $zipFile->saveAsFile($this->outputFilename);
  507. $zipFile->close();
  508. self::assertCorrectZipArchive($this->outputFilename);
  509. $zipFile->openFile($this->outputFilename);
  510. $zipFile->deleteFromRegex('~\.(json)$~i');
  511. $zipFile->addFromString('test.txt', 'content');
  512. $zipFile->deleteFromRegex('~\.txt$~');
  513. $zipFile->saveAsFile($this->outputFilename);
  514. $zipFile->close();
  515. self::assertCorrectZipArchive($this->outputFilename);
  516. $zipFile->openFile($this->outputFilename);
  517. self::assertFalse(isset($zipFile['Path/composer.json']));
  518. self::assertFalse(isset($zipFile['Path/test.txt']));
  519. self::assertTrue(isset($zipFile['Path/phpunit.xml']));
  520. $zipFile->close();
  521. }
  522. /**
  523. * @expectedException \PhpZip\Exception\InvalidArgumentException
  524. * @expectedExceptionMessage Regex pattern is empty.
  525. */
  526. public function testDeleteFromRegexFailNull()
  527. {
  528. $zipFile = new ZipFile();
  529. $zipFile->deleteFromRegex(null);
  530. }
  531. /**
  532. * @expectedException \PhpZip\Exception\InvalidArgumentException
  533. * @expectedExceptionMessage Regex pattern is empty.
  534. */
  535. public function testDeleteFromRegexFailEmpty()
  536. {
  537. $zipFile = new ZipFile();
  538. $zipFile->deleteFromRegex('');
  539. }
  540. /**
  541. * Delete all entries
  542. */
  543. public function testDeleteAll()
  544. {
  545. $zipFile = new ZipFile();
  546. $zipFile->addDirRecursive(dirname(dirname(__DIR__)) .DIRECTORY_SEPARATOR. 'src');
  547. self::assertTrue($zipFile->count() > 0);
  548. $zipFile->saveAsFile($this->outputFilename);
  549. $zipFile->close();
  550. self::assertCorrectZipArchive($this->outputFilename);
  551. $zipFile->openFile($this->outputFilename);
  552. self::assertTrue($zipFile->count() > 0);
  553. $zipFile->deleteAll();
  554. $zipFile->saveAsFile($this->outputFilename);
  555. $zipFile->close();
  556. self::assertCorrectEmptyZip($this->outputFilename);
  557. $zipFile->openFile($this->outputFilename);
  558. self::assertEquals($zipFile->count(), 0);
  559. $zipFile->close();
  560. }
  561. /**
  562. * Test zip archive comment.
  563. */
  564. public function testArchiveComment()
  565. {
  566. $comment = "This zip file comment" . PHP_EOL
  567. . "Αυτό το σχόλιο αρχείο zip" . PHP_EOL
  568. . "Это комментарий zip архива" . PHP_EOL
  569. . "這個ZIP文件註釋" . PHP_EOL
  570. . "ეს zip ფაილის კომენტარი" . PHP_EOL
  571. . "このzipファイルにコメント" . PHP_EOL
  572. . "ความคิดเห็นนี้ไฟล์ซิป";
  573. $zipFile = new ZipFile();
  574. $zipFile->setArchiveComment($comment);
  575. $zipFile->addFile(__FILE__);
  576. $zipFile->saveAsFile($this->outputFilename);
  577. $zipFile->close();
  578. self::assertCorrectZipArchive($this->outputFilename);
  579. $zipFile->openFile($this->outputFilename);
  580. self::assertEquals($zipFile->getArchiveComment(), $comment);
  581. $zipFile->setArchiveComment(null); // remove archive comment
  582. $zipFile->saveAsFile($this->outputFilename);
  583. $zipFile->close();
  584. self::assertCorrectZipArchive($this->outputFilename);
  585. // check empty comment
  586. $zipFile->openFile($this->outputFilename);
  587. self::assertEquals($zipFile->getArchiveComment(), "");
  588. $zipFile->close();
  589. }
  590. /**
  591. * Test very long archive comment.
  592. *
  593. * @expectedException \PhpZip\Exception\InvalidArgumentException
  594. */
  595. public function testVeryLongArchiveComment()
  596. {
  597. $comment = "Very long comment" . PHP_EOL .
  598. "Очень длинный комментарий" . PHP_EOL;
  599. $comment = str_repeat($comment, ceil(0xffff / strlen($comment)) + strlen($comment) + 1);
  600. $zipFile = new ZipFile();
  601. $zipFile->setArchiveComment($comment);
  602. }
  603. /**
  604. * Test zip entry comment.
  605. */
  606. public function testEntryComment()
  607. {
  608. $entries = [
  609. '文件1.txt' => [
  610. 'data' => CryptoUtil::randomBytes(255),
  611. 'comment' => "這是註釋的條目。",
  612. ],
  613. 'file2.txt' => [
  614. 'data' => CryptoUtil::randomBytes(255),
  615. 'comment' => null
  616. ],
  617. 'file3.txt' => [
  618. 'data' => CryptoUtil::randomBytes(255),
  619. 'comment' => CryptoUtil::randomBytes(255),
  620. ],
  621. 'file4.txt' => [
  622. 'data' => CryptoUtil::randomBytes(255),
  623. 'comment' => "Комментарий файла"
  624. ],
  625. 'file5.txt' => [
  626. 'data' => CryptoUtil::randomBytes(255),
  627. 'comment' => "ไฟล์แสดงความคิดเห็น"
  628. ],
  629. 'file6 emoji 🙍🏼.txt' => [
  630. 'data' => CryptoUtil::randomBytes(255),
  631. 'comment' => "Emoji comment file - 😀 ⛈ ❤️ 🤴🏽"
  632. ],
  633. ];
  634. // create archive with entry comments
  635. $zipFile = new ZipFile();
  636. foreach ($entries as $entryName => $item) {
  637. $zipFile->addFromString($entryName, $item['data']);
  638. $zipFile->setEntryComment($entryName, $item['comment']);
  639. }
  640. $zipFile->saveAsFile($this->outputFilename);
  641. $zipFile->close();
  642. self::assertCorrectZipArchive($this->outputFilename);
  643. // check and modify comments
  644. $zipFile->openFile($this->outputFilename);
  645. foreach ($zipFile->getListFiles() as $entryName) {
  646. $entriesItem = $entries[$entryName];
  647. self::assertNotEmpty($entriesItem);
  648. self::assertEquals($zipFile[$entryName], $entriesItem['data']);
  649. self::assertEquals($zipFile->getEntryComment($entryName), (string)$entriesItem['comment']);
  650. }
  651. // modify comment
  652. $entries['file5.txt']['comment'] = mt_rand(1, 100000000);
  653. $zipFile->setEntryComment('file5.txt', $entries['file5.txt']['comment']);
  654. $zipFile->saveAsFile($this->outputFilename);
  655. $zipFile->close();
  656. self::assertCorrectZipArchive($this->outputFilename);
  657. // check modify comments
  658. $zipFile->openFile($this->outputFilename);
  659. foreach ($entries as $entryName => $entriesItem) {
  660. self::assertTrue(isset($zipFile[$entryName]));
  661. self::assertEquals($zipFile->getEntryComment($entryName), (string)$entriesItem['comment']);
  662. self::assertEquals($zipFile[$entryName], $entriesItem['data']);
  663. }
  664. $zipFile->close();
  665. }
  666. /**
  667. * Test zip entry very long comment.
  668. *
  669. * @expectedException \PhpZip\Exception\ZipException
  670. * @expectedExceptionMessage Comment too long
  671. */
  672. public function testVeryLongEntryComment()
  673. {
  674. $comment = "Very long comment" . PHP_EOL .
  675. "Очень длинный комментарий" . PHP_EOL;
  676. $comment = str_repeat($comment, ceil(0xffff / strlen($comment)) + strlen($comment) + 1);
  677. $zipFile = new ZipFile();
  678. $zipFile->addFile(__FILE__, 'test');
  679. $zipFile->setEntryComment('test', $comment);
  680. }
  681. /**
  682. * @expectedException \PhpZip\Exception\ZipNotFoundEntry
  683. */
  684. public function testSetEntryCommentNotFoundEntry()
  685. {
  686. $zipFile = new ZipFile();
  687. $zipFile->setEntryComment('test', 'comment');
  688. }
  689. /**
  690. * Test all available support compression methods.
  691. */
  692. public function testCompressionMethod()
  693. {
  694. $entries = [
  695. '1' => [
  696. 'data' => CryptoUtil::randomBytes(255),
  697. 'method' => ZipFileInterface::METHOD_STORED,
  698. 'expected' => 'No compression',
  699. ],
  700. '2' => [
  701. 'data' => CryptoUtil::randomBytes(255),
  702. 'method' => ZipFileInterface::METHOD_DEFLATED,
  703. 'expected' => 'Deflate',
  704. ],
  705. ];
  706. if (extension_loaded("bz2")) {
  707. $entries['3'] = [
  708. 'data' => CryptoUtil::randomBytes(255),
  709. 'method' => ZipFileInterface::METHOD_BZIP2,
  710. 'expected' => 'Bzip2',
  711. ];
  712. }
  713. $zipFile = new ZipFile();
  714. foreach ($entries as $entryName => $item) {
  715. $zipFile->addFromString($entryName, $item['data'], $item['method']);
  716. }
  717. $zipFile->saveAsFile($this->outputFilename);
  718. $zipFile->close();
  719. self::assertCorrectZipArchive($this->outputFilename);
  720. $zipFile->openFile($this->outputFilename);
  721. $zipFile->setCompressionLevel(ZipFileInterface::LEVEL_BEST_COMPRESSION);
  722. $zipAllInfo = $zipFile->getAllInfo();
  723. foreach ($zipAllInfo as $entryName => $info) {
  724. self::assertEquals($zipFile[$entryName], $entries[$entryName]['data']);
  725. self::assertEquals($info->getMethodName(), $entries[$entryName]['expected']);
  726. $entryInfo = $zipFile->getEntryInfo($entryName);
  727. self::assertEquals($entryInfo, $info);
  728. }
  729. $zipFile->close();
  730. }
  731. /**
  732. * @expectedException \PhpZip\Exception\InvalidArgumentException
  733. * @expectedExceptionMessage Invalid compression level. Minimum level -1. Maximum level 9
  734. */
  735. public function testSetInvalidCompressionLevel()
  736. {
  737. $zipFile = new ZipFile();
  738. $zipFile->setCompressionLevel(-2);
  739. }
  740. /**
  741. * /**
  742. * @expectedException \PhpZip\Exception\InvalidArgumentException
  743. * @expectedExceptionMessage Invalid compression level. Minimum level -1. Maximum level 9
  744. */
  745. public function testSetInvalidCompressionLevel2()
  746. {
  747. $zipFile = new ZipFile();
  748. $zipFile->setCompressionLevel(10);
  749. }
  750. /**
  751. * Test extract all files.
  752. */
  753. public function testExtract()
  754. {
  755. $entries = [
  756. 'test1.txt' => CryptoUtil::randomBytes(255),
  757. 'test2.txt' => CryptoUtil::randomBytes(255),
  758. 'test/test 2/test3.txt' => CryptoUtil::randomBytes(255),
  759. 'test empty/dir' => null,
  760. ];
  761. $zipFile = new ZipFile();
  762. foreach ($entries as $entryName => $value) {
  763. if ($value === null) {
  764. $zipFile->addEmptyDir($entryName);
  765. } else {
  766. $zipFile->addFromString($entryName, $value);
  767. }
  768. }
  769. $zipFile->saveAsFile($this->outputFilename);
  770. $zipFile->close();
  771. self::assertTrue(mkdir($this->outputDirname, 0755, true));
  772. $zipFile->openFile($this->outputFilename);
  773. $zipFile->extractTo($this->outputDirname);
  774. foreach ($entries as $entryName => $value) {
  775. $fullExtractedFilename = $this->outputDirname . DIRECTORY_SEPARATOR . $entryName;
  776. if ($value === null) {
  777. self::assertTrue(is_dir($fullExtractedFilename));
  778. self::assertTrue(FilesUtil::isEmptyDir($fullExtractedFilename));
  779. } else {
  780. self::assertTrue(is_file($fullExtractedFilename));
  781. $contents = file_get_contents($fullExtractedFilename);
  782. self::assertEquals($contents, $value);
  783. }
  784. }
  785. $zipFile->close();
  786. }
  787. /**
  788. * Test extract some files
  789. */
  790. public function testExtractSomeFiles()
  791. {
  792. $entries = [
  793. 'test1.txt' => CryptoUtil::randomBytes(255),
  794. 'test2.txt' => CryptoUtil::randomBytes(255),
  795. 'test3.txt' => CryptoUtil::randomBytes(255),
  796. 'test4.txt' => CryptoUtil::randomBytes(255),
  797. 'test5.txt' => CryptoUtil::randomBytes(255),
  798. 'test/test/test.txt' => CryptoUtil::randomBytes(255),
  799. 'test/test/test 2.txt' => CryptoUtil::randomBytes(255),
  800. 'test empty/dir/' => null,
  801. 'test empty/dir2/' => null,
  802. ];
  803. $extractEntries = [
  804. 'test1.txt',
  805. 'test3.txt',
  806. 'test5.txt',
  807. 'test/test/test 2.txt',
  808. 'test empty/dir2/'
  809. ];
  810. self::assertTrue(mkdir($this->outputDirname, 0755, true));
  811. $zipFile = new ZipFile();
  812. $zipFile->addAll($entries);
  813. $zipFile->saveAsFile($this->outputFilename);
  814. $zipFile->close();
  815. $zipFile->openFile($this->outputFilename);
  816. $zipFile->extractTo($this->outputDirname, $extractEntries);
  817. foreach ($entries as $entryName => $value) {
  818. $fullExtractFilename = $this->outputDirname . DIRECTORY_SEPARATOR . $entryName;
  819. if (in_array($entryName, $extractEntries)) {
  820. if ($value === null) {
  821. self::assertTrue(is_dir($fullExtractFilename));
  822. self::assertTrue(FilesUtil::isEmptyDir($fullExtractFilename));
  823. } else {
  824. self::assertTrue(is_file($fullExtractFilename));
  825. $contents = file_get_contents($fullExtractFilename);
  826. self::assertEquals($contents, $value);
  827. }
  828. } else {
  829. if ($value === null) {
  830. self::assertFalse(is_dir($fullExtractFilename));
  831. } else {
  832. self::assertFalse(is_file($fullExtractFilename));
  833. }
  834. }
  835. }
  836. self::assertFalse(is_file($this->outputDirname . DIRECTORY_SEPARATOR . 'test/test/test.txt'));
  837. $zipFile->extractTo($this->outputDirname, 'test/test/test.txt');
  838. self::assertTrue(is_file($this->outputDirname . DIRECTORY_SEPARATOR . 'test/test/test.txt'));
  839. $zipFile->close();
  840. }
  841. /**
  842. * @expectedException \PhpZip\Exception\ZipException
  843. * @expectedExceptionMessage not found
  844. */
  845. public function testExtractFail()
  846. {
  847. $zipFile = new ZipFile();
  848. $zipFile['file'] = 'content';
  849. $zipFile->saveAsFile($this->outputFilename);
  850. $zipFile->close();
  851. $zipFile->openFile($this->outputFilename);
  852. $zipFile->extractTo('path/to/path');
  853. }
  854. /**
  855. * @expectedException \PhpZip\Exception\ZipException
  856. * @expectedExceptionMessage Destination is not directory
  857. */
  858. public function testExtractFail2()
  859. {
  860. $zipFile = new ZipFile();
  861. $zipFile['file'] = 'content';
  862. $zipFile->saveAsFile($this->outputFilename);
  863. $zipFile->close();
  864. $zipFile->openFile($this->outputFilename);
  865. $zipFile->extractTo($this->outputFilename);
  866. }
  867. /**
  868. * @expectedException \PhpZip\Exception\ZipException
  869. * @expectedExceptionMessage Destination is not writable directory
  870. */
  871. public function testExtractFail3()
  872. {
  873. $zipFile = new ZipFile();
  874. $zipFile['file'] = 'content';
  875. $zipFile->saveAsFile($this->outputFilename);
  876. $zipFile->close();
  877. self::assertTrue(mkdir($this->outputDirname, 0444, true));
  878. self::assertTrue(chmod($this->outputDirname, 0444));
  879. $zipFile->openFile($this->outputFilename);
  880. $zipFile->extractTo($this->outputDirname);
  881. }
  882. /**
  883. * @expectedException \PhpZip\Exception\InvalidArgumentException
  884. * @expectedExceptionMessage entryName is null
  885. */
  886. public function testAddFromArrayAccessNullName()
  887. {
  888. $zipFile = new ZipFile();
  889. $zipFile[null] = 'content';
  890. }
  891. /**
  892. * @expectedException \PhpZip\Exception\InvalidArgumentException
  893. * @expectedExceptionMessage entryName is empty
  894. */
  895. public function testAddFromArrayAccessEmptyName()
  896. {
  897. $zipFile = new ZipFile();
  898. $zipFile[''] = 'content';
  899. }
  900. /**
  901. * @expectedException \PhpZip\Exception\InvalidArgumentException
  902. * @expectedExceptionMessage Contents is null
  903. */
  904. public function testAddFromStringNullContents()
  905. {
  906. $zipFile = new ZipFile();
  907. $zipFile->addFromString('file', null);
  908. }
  909. /**
  910. * @expectedException \PhpZip\Exception\InvalidArgumentException
  911. * @expectedExceptionMessage Incorrect entry name
  912. */
  913. public function testAddFromStringNullEntryName()
  914. {
  915. $zipFile = new ZipFile();
  916. $zipFile->addFromString(null, 'contents');
  917. }
  918. /**
  919. * @expectedException \PhpZip\Exception\ZipUnsupportMethod
  920. * @expectedExceptionMessage Unsupported compression method
  921. */
  922. public function testAddFromStringUnsupportedMethod()
  923. {
  924. $zipFile = new ZipFile();
  925. $zipFile->addFromString('file', 'contents', ZipEntry::METHOD_WINZIP_AES);
  926. }
  927. /**
  928. * @expectedException \PhpZip\Exception\InvalidArgumentException
  929. * @expectedExceptionMessage Incorrect entry name
  930. */
  931. public function testAddFromStringEmptyEntryName()
  932. {
  933. $zipFile = new ZipFile();
  934. $zipFile->addFromString('', 'contents');
  935. }
  936. /**
  937. * Test compression method from add string.
  938. */
  939. public function testAddFromStringCompressionMethod()
  940. {
  941. $fileStored = sys_get_temp_dir() . '/zip-stored.txt';
  942. $fileDeflated = sys_get_temp_dir() . '/zip-deflated.txt';
  943. self::assertNotFalse(file_put_contents($fileStored, 'content'));
  944. self::assertNotFalse(file_put_contents($fileDeflated, str_repeat('content', 200)));
  945. $zipFile = new ZipFile();
  946. $zipFile->addFromString(basename($fileStored), file_get_contents($fileStored));
  947. $zipFile->addFromString(basename($fileDeflated), file_get_contents($fileDeflated));
  948. $zipFile->saveAsFile($this->outputFilename);
  949. $zipFile->close();
  950. unlink($fileStored);
  951. unlink($fileDeflated);
  952. $zipFile->openFile($this->outputFilename);
  953. $infoStored = $zipFile->getEntryInfo(basename($fileStored));
  954. $infoDeflated = $zipFile->getEntryInfo(basename($fileDeflated));
  955. self::assertEquals($infoStored->getMethodName(), 'No compression');
  956. self::assertEquals($infoDeflated->getMethodName(), 'Deflate');
  957. $zipFile->close();
  958. }
  959. /**
  960. * @expectedException \PhpZip\Exception\InvalidArgumentException
  961. * @expectedExceptionMessage stream is not resource
  962. */
  963. public function testAddFromStreamInvalidResource()
  964. {
  965. $zipFile = new ZipFile();
  966. /** @noinspection PhpParamsInspection */
  967. $zipFile->addFromStream("invalid resource", "name");
  968. }
  969. /**
  970. * @expectedException \PhpZip\Exception\InvalidArgumentException
  971. * @expectedExceptionMessage Incorrect entry name
  972. */
  973. public function testAddFromStreamEmptyEntryName()
  974. {
  975. $handle = fopen(__FILE__, 'rb');
  976. $zipFile = new ZipFile();
  977. $zipFile->addFromStream($handle, "");
  978. }
  979. /**
  980. * @expectedException \PhpZip\Exception\ZipUnsupportMethod
  981. * @expectedExceptionMessage Unsupported method
  982. */
  983. public function testAddFromStreamUnsupportedMethod()
  984. {
  985. $handle = fopen(__FILE__, 'rb');
  986. $zipFile = new ZipFile();
  987. $zipFile->addFromStream($handle, basename(__FILE__), ZipEntry::METHOD_WINZIP_AES);
  988. }
  989. /**
  990. * Test compression method from add stream.
  991. */
  992. public function testAddFromStreamCompressionMethod()
  993. {
  994. $fileStored = sys_get_temp_dir() . '/zip-stored.txt';
  995. $fileDeflated = sys_get_temp_dir() . '/zip-deflated.txt';
  996. self::assertNotFalse(file_put_contents($fileStored, 'content'));
  997. self::assertNotFalse(file_put_contents($fileDeflated, str_repeat('content', 200)));
  998. $fpStored = fopen($fileStored, 'rb');
  999. $fpDeflated = fopen($fileDeflated, 'rb');
  1000. $zipFile = new ZipFile();
  1001. $zipFile->addFromStream($fpStored, basename($fileStored));
  1002. $zipFile->addFromStream($fpDeflated, basename($fileDeflated));
  1003. $zipFile->saveAsFile($this->outputFilename);
  1004. $zipFile->close();
  1005. unlink($fileStored);
  1006. unlink($fileDeflated);
  1007. $zipFile->openFile($this->outputFilename);
  1008. $infoStored = $zipFile->getEntryInfo(basename($fileStored));
  1009. $infoDeflated = $zipFile->getEntryInfo(basename($fileDeflated));
  1010. self::assertEquals($infoStored->getMethodName(), 'No compression');
  1011. self::assertEquals($infoDeflated->getMethodName(), 'Deflate');
  1012. $zipFile->close();
  1013. }
  1014. /**
  1015. * @expectedException \PhpZip\Exception\InvalidArgumentException
  1016. * @expectedExceptionMessage Filename is null
  1017. */
  1018. public function testAddFileNullFileName()
  1019. {
  1020. $zipFile = new ZipFile();
  1021. $zipFile->addFile(null);
  1022. }
  1023. /**
  1024. * @expectedException \PhpZip\Exception\InvalidArgumentException
  1025. * @expectedExceptionMessage is not exists
  1026. */
  1027. public function testAddFileCantExists()
  1028. {
  1029. $zipFile = new ZipFile();
  1030. $zipFile->addFile('path/to/file');
  1031. }
  1032. /**
  1033. * @expectedException \PhpZip\Exception\ZipUnsupportMethod
  1034. * @expectedExceptionMessage Unsupported method
  1035. */
  1036. public function testAddFileUnsupportedMethod()
  1037. {
  1038. $zipFile = new ZipFile();
  1039. $zipFile->addFile(__FILE__, null, ZipEntry::METHOD_WINZIP_AES);
  1040. }
  1041. /**
  1042. * @expectedException \PhpZip\Exception\InvalidArgumentException
  1043. * @expectedExceptionMessage can not open
  1044. */
  1045. public function testAddFileCantOpen()
  1046. {
  1047. self::assertNotFalse(file_put_contents($this->outputFilename, ''));
  1048. self::assertTrue(chmod($this->outputFilename, 0244));
  1049. $zipFile = new ZipFile();
  1050. $zipFile->addFile($this->outputFilename);
  1051. }
  1052. /**
  1053. * @expectedException \PhpZip\Exception\InvalidArgumentException
  1054. * @expectedExceptionMessage Input dir empty
  1055. */
  1056. public function testAddDirNullDirname()
  1057. {
  1058. $zipFile = new ZipFile();
  1059. $zipFile->addDir(null);
  1060. }
  1061. /**
  1062. * @expectedException \PhpZip\Exception\InvalidArgumentException
  1063. * @expectedExceptionMessage Input dir empty
  1064. */
  1065. public function testAddDirEmptyDirname()
  1066. {
  1067. $zipFile = new ZipFile();
  1068. $zipFile->addDir("");
  1069. }
  1070. /**
  1071. * @expectedException \PhpZip\Exception\InvalidArgumentException
  1072. * @expectedExceptionMessage can't exists
  1073. */
  1074. public function testAddDirCantExists()
  1075. {
  1076. $zipFile = new ZipFile();
  1077. $zipFile->addDir(uniqid());
  1078. }
  1079. /**
  1080. * @expectedException \PhpZip\Exception\InvalidArgumentException
  1081. * @expectedExceptionMessage Input dir empty
  1082. */
  1083. public function testAddDirRecursiveNullDirname()
  1084. {
  1085. $zipFile = new ZipFile();
  1086. $zipFile->addDirRecursive(null);
  1087. }
  1088. /**
  1089. * @expectedException \PhpZip\Exception\InvalidArgumentException
  1090. * @expectedExceptionMessage Input dir empty
  1091. */
  1092. public function testAddDirRecursiveEmptyDirname()
  1093. {
  1094. $zipFile = new ZipFile();
  1095. $zipFile->addDirRecursive("");
  1096. }
  1097. /**
  1098. * @expectedException \PhpZip\Exception\InvalidArgumentException
  1099. * @expectedExceptionMessage can't exists
  1100. */
  1101. public function testAddDirRecursiveCantExists()
  1102. {
  1103. $zipFile = new ZipFile();
  1104. $zipFile->addDirRecursive(uniqid());
  1105. }
  1106. /**
  1107. * @expectedException \PhpZip\Exception\InvalidArgumentException
  1108. * @expectedExceptionMessage Input dir empty
  1109. */
  1110. public function testAddFilesFromGlobNull()
  1111. {
  1112. $zipFile = new ZipFile();
  1113. $zipFile->addFilesFromGlob(null, '*.png');
  1114. }
  1115. /**
  1116. * @expectedException \PhpZip\Exception\InvalidArgumentException
  1117. * @expectedExceptionMessage Input dir empty
  1118. */
  1119. public function testAddFilesFromGlobEmpty()
  1120. {
  1121. $zipFile = new ZipFile();
  1122. $zipFile->addFilesFromGlob("", '*.png');
  1123. }
  1124. /**
  1125. * @expectedException \PhpZip\Exception\InvalidArgumentException
  1126. * @expectedExceptionMessage can't exists
  1127. */
  1128. public function testAddFilesFromGlobCantExists()
  1129. {
  1130. $zipFile = new ZipFile();
  1131. $zipFile->addFilesFromGlob("path/to/path", '*.png');
  1132. }
  1133. /**
  1134. * @expectedException \PhpZip\Exception\InvalidArgumentException
  1135. * @expectedExceptionMessage glob pattern empty
  1136. */
  1137. public function testAddFilesFromGlobNullPattern()
  1138. {
  1139. $zipFile = new ZipFile();
  1140. $zipFile->addFilesFromGlob(__DIR__, null);
  1141. }
  1142. /**
  1143. * @expectedException \PhpZip\Exception\InvalidArgumentException
  1144. * @expectedExceptionMessage glob pattern empty
  1145. */
  1146. public function testAddFilesFromGlobEmptyPattern()
  1147. {
  1148. $zipFile = new ZipFile();
  1149. $zipFile->addFilesFromGlob(__DIR__, '');
  1150. }
  1151. /**
  1152. * @expectedException \PhpZip\Exception\InvalidArgumentException
  1153. * @expectedExceptionMessage Input dir empty
  1154. */
  1155. public function testAddFilesFromGlobRecursiveNull()
  1156. {
  1157. $zipFile = new ZipFile();
  1158. $zipFile->addFilesFromGlobRecursive(null, '*.png');
  1159. }
  1160. /**
  1161. * @expectedException \PhpZip\Exception\InvalidArgumentException
  1162. * @expectedExceptionMessage Input dir empty
  1163. */
  1164. public function testAddFilesFromGlobRecursiveEmpty()
  1165. {
  1166. $zipFile = new ZipFile();
  1167. $zipFile->addFilesFromGlobRecursive("", '*.png');
  1168. }
  1169. /**
  1170. * @expectedException \PhpZip\Exception\InvalidArgumentException
  1171. * @expectedExceptionMessage can't exists
  1172. */
  1173. public function testAddFilesFromGlobRecursiveCantExists()
  1174. {
  1175. $zipFile = new ZipFile();
  1176. $zipFile->addFilesFromGlobRecursive("path/to/path", '*.png');
  1177. }
  1178. /**
  1179. * @expectedException \PhpZip\Exception\InvalidArgumentException
  1180. * @expectedExceptionMessage glob pattern empty
  1181. */
  1182. public function testAddFilesFromGlobRecursiveNullPattern()
  1183. {
  1184. $zipFile = new ZipFile();
  1185. $zipFile->addFilesFromGlobRecursive(__DIR__, null);
  1186. }
  1187. /**
  1188. * @expectedException \PhpZip\Exception\InvalidArgumentException
  1189. * @expectedExceptionMessage glob pattern empty
  1190. */
  1191. public function testAddFilesFromGlobRecursiveEmptyPattern()
  1192. {
  1193. $zipFile = new ZipFile();
  1194. $zipFile->addFilesFromGlobRecursive(__DIR__, '');
  1195. }
  1196. /**
  1197. * @expectedException \PhpZip\Exception\InvalidArgumentException
  1198. * @expectedExceptionMessage Input dir empty
  1199. */
  1200. public function testAddFilesFromRegexDirectoryNull()
  1201. {
  1202. $zipFile = new ZipFile();
  1203. $zipFile->addFilesFromRegex(null, '~\.png$~i');
  1204. }
  1205. /**
  1206. * @expectedException \PhpZip\Exception\InvalidArgumentException
  1207. * @expectedExceptionMessage Input dir empty
  1208. */
  1209. public function testAddFilesFromRegexDirectoryEmpty()
  1210. {
  1211. $zipFile = new ZipFile();
  1212. $zipFile->addFilesFromRegex("", '~\.png$~i');
  1213. }
  1214. /**
  1215. * @expectedException \PhpZip\Exception\InvalidArgumentException
  1216. * @expectedExceptionMessage can't exists
  1217. */
  1218. public function testAddFilesFromRegexCantExists()
  1219. {
  1220. $zipFile = new ZipFile();
  1221. $zipFile->addFilesFromRegex("path/to/path", '~\.png$~i');
  1222. }
  1223. /**
  1224. * @expectedException \PhpZip\Exception\InvalidArgumentException
  1225. * @expectedExceptionMessage regex pattern empty
  1226. */
  1227. public function testAddFilesFromRegexNullPattern()
  1228. {
  1229. $zipFile = new ZipFile();
  1230. $zipFile->addFilesFromRegex(__DIR__, null);
  1231. }
  1232. /**
  1233. * @expectedException \PhpZip\Exception\InvalidArgumentException
  1234. * @expectedExceptionMessage regex pattern empty
  1235. */
  1236. public function testAddFilesFromRegexEmptyPattern()
  1237. {
  1238. $zipFile = new ZipFile();
  1239. $zipFile->addFilesFromRegex(__DIR__, '');
  1240. }
  1241. /**
  1242. * @expectedException \PhpZip\Exception\InvalidArgumentException
  1243. * @expectedExceptionMessage Input dir empty
  1244. */
  1245. public function testAddFilesFromRegexRecursiveDirectoryNull()
  1246. {
  1247. $zipFile = new ZipFile();
  1248. $zipFile->addFilesFromRegexRecursive(null, '~\.png$~i');
  1249. }
  1250. /**
  1251. * @expectedException \PhpZip\Exception\InvalidArgumentException
  1252. * @expectedExceptionMessage Input dir empty
  1253. */
  1254. public function testAddFilesFromRegexRecursiveEmpty()
  1255. {
  1256. $zipFile = new ZipFile();
  1257. $zipFile->addFilesFromRegexRecursive("", '~\.png$~i');
  1258. }
  1259. /**
  1260. * @expectedException \PhpZip\Exception\InvalidArgumentException
  1261. * @expectedExceptionMessage can't exists
  1262. */
  1263. public function testAddFilesFromRegexRecursiveCantExists()
  1264. {
  1265. $zipFile = new ZipFile();
  1266. $zipFile->addFilesFromGlobRecursive("path/to/path", '~\.png$~i');
  1267. }
  1268. /**
  1269. * @expectedException \PhpZip\Exception\InvalidArgumentException
  1270. * @expectedExceptionMessage regex pattern empty
  1271. */
  1272. public function testAddFilesFromRegexRecursiveNullPattern()
  1273. {
  1274. $zipFile = new ZipFile();
  1275. $zipFile->addFilesFromRegexRecursive(__DIR__, null);
  1276. }
  1277. /**
  1278. * @expectedException \PhpZip\Exception\InvalidArgumentException
  1279. * @expectedExceptionMessage regex pattern empty
  1280. */
  1281. public function testAddFilesFromRegexRecursiveEmptyPattern()
  1282. {
  1283. $zipFile = new ZipFile();
  1284. $zipFile->addFilesFromRegexRecursive(__DIR__, '');
  1285. }
  1286. /**
  1287. * @expectedException \PhpZip\Exception\InvalidArgumentException
  1288. * @expectedExceptionMessage handle is not resource
  1289. */
  1290. public function testSaveAsStreamBadStream()
  1291. {
  1292. $zipFile = new ZipFile();
  1293. /** @noinspection PhpParamsInspection */
  1294. $zipFile->saveAsStream("bad stream");
  1295. }
  1296. /**
  1297. * @expectedException \PhpZip\Exception\InvalidArgumentException
  1298. * @expectedExceptionMessage can not open from write
  1299. */
  1300. public function testSaveAsFileNotWritable()
  1301. {
  1302. self::assertTrue(mkdir($this->outputDirname, 0444, true));
  1303. self::assertTrue(chmod($this->outputDirname, 0444));
  1304. $this->outputFilename = $this->outputDirname . DIRECTORY_SEPARATOR . basename($this->outputFilename);
  1305. $zipFile = new ZipFile();
  1306. $zipFile->saveAsFile($this->outputFilename);
  1307. }
  1308. /**
  1309. * Test `ZipFile` implemented \ArrayAccess, \Countable and |iterator.
  1310. */
  1311. public function testZipFileArrayAccessAndCountableAndIterator()
  1312. {
  1313. $files = [];
  1314. $numFiles = mt_rand(20, 100);
  1315. for ($i = 0; $i < $numFiles; $i++) {
  1316. $files['file' . $i . '.txt'] = CryptoUtil::randomBytes(255);
  1317. }
  1318. $methods = [ZipFileInterface::METHOD_STORED, ZipFileInterface::METHOD_DEFLATED];
  1319. if (extension_loaded("bz2")) {
  1320. $methods[] = ZipFileInterface::METHOD_BZIP2;
  1321. }
  1322. $zipFile = new ZipFile();
  1323. $zipFile->setCompressionLevel(ZipFileInterface::LEVEL_BEST_SPEED);
  1324. foreach ($files as $entryName => $content) {
  1325. $zipFile->addFromString($entryName, $content, $methods[array_rand($methods)]);
  1326. }
  1327. $zipFile->saveAsFile($this->outputFilename);
  1328. $zipFile->close();
  1329. self::assertCorrectZipArchive($this->outputFilename);
  1330. $zipFile->openFile($this->outputFilename);
  1331. // Test \Countable
  1332. self::assertEquals($zipFile->count(), $numFiles);
  1333. self::assertEquals(count($zipFile), $numFiles);
  1334. // Test \ArrayAccess
  1335. reset($files);
  1336. foreach ($zipFile as $entryName => $content) {
  1337. self::assertEquals($entryName, key($files));
  1338. self::assertEquals($content, current($files));
  1339. next($files);
  1340. }
  1341. // Test \Iterator
  1342. reset($files);
  1343. $iterator = new \ArrayIterator($zipFile);
  1344. $iterator->rewind();
  1345. while ($iterator->valid()) {
  1346. $key = $iterator->key();
  1347. $value = $iterator->current();
  1348. self::assertEquals($key, key($files));
  1349. self::assertEquals($value, current($files));
  1350. next($files);
  1351. $iterator->next();
  1352. }
  1353. $zipFile->close();
  1354. $zipFile = new ZipFile();
  1355. $zipFile['file1.txt'] = 'content 1';
  1356. $zipFile['dir/file2.txt'] = 'content 1';
  1357. $zipFile['dir/empty dir/'] = null;
  1358. $zipFile->saveAsFile($this->outputFilename);
  1359. $zipFile->close();
  1360. self::assertCorrectZipArchive($this->outputFilename);
  1361. $zipFile->openFile($this->outputFilename);
  1362. self::assertTrue(isset($zipFile['file1.txt']));
  1363. self::assertTrue(isset($zipFile['dir/file2.txt']));
  1364. self::assertTrue(isset($zipFile['dir/empty dir/']));
  1365. self::assertFalse(isset($zipFile['dir/empty dir/2/']));
  1366. $zipFile['dir/empty dir/2/'] = null;
  1367. unset($zipFile['dir/file2.txt'], $zipFile['dir/empty dir/']);
  1368. $zipFile->saveAsFile($this->outputFilename);
  1369. $zipFile->close();
  1370. self::assertCorrectZipArchive($this->outputFilename);
  1371. $zipFile->openFile($this->outputFilename);
  1372. self::assertTrue(isset($zipFile['file1.txt']));
  1373. self::assertFalse(isset($zipFile['dir/file2.txt']));
  1374. self::assertFalse(isset($zipFile['dir/empty dir/']));
  1375. self::assertTrue(isset($zipFile['dir/empty dir/2/']));
  1376. $zipFile->close();
  1377. }
  1378. public function testArrayAccessAddFile()
  1379. {
  1380. $entryName = 'path/to/file.dat';
  1381. $entryNameStream = 'path/to/' . basename(__FILE__);
  1382. $zipFile = new ZipFile();
  1383. $zipFile[$entryName] = new \SplFileInfo(__FILE__);
  1384. $zipFile[$entryNameStream] = fopen(__FILE__, 'r');
  1385. $zipFile->saveAsFile($this->outputFilename);
  1386. $zipFile->close();
  1387. self::assertCorrectZipArchive($this->outputFilename);
  1388. $zipFile->openFile($this->outputFilename);
  1389. self::assertEquals(sizeof($zipFile), 2);
  1390. self::assertTrue(isset($zipFile[$entryName]));
  1391. self::assertTrue(isset($zipFile[$entryNameStream]));
  1392. self::assertEquals($zipFile[$entryName], file_get_contents(__FILE__));
  1393. self::assertEquals($zipFile[$entryNameStream], file_get_contents(__FILE__));
  1394. $zipFile->close();
  1395. }
  1396. public function testUnknownCompressionMethod()
  1397. {
  1398. $zipFile = new ZipFile();
  1399. $zipFile->addFromString('file', 'content', ZipEntry::UNKNOWN);
  1400. $zipFile->addFromString('file2', base64_encode(CryptoUtil::randomBytes(512)), ZipEntry::UNKNOWN);
  1401. self::assertEquals($zipFile->getEntryInfo('file')->getMethodName(), 'Unknown');
  1402. self::assertEquals($zipFile->getEntryInfo('file2')->getMethodName(), 'Unknown');
  1403. $zipFile->saveAsFile($this->outputFilename);
  1404. $zipFile->close();
  1405. $zipFile->openFile($this->outputFilename);
  1406. self::assertEquals($zipFile->getEntryInfo('file')->getMethodName(), 'No compression');
  1407. self::assertEquals($zipFile->getEntryInfo('file2')->getMethodName(), 'Deflate');
  1408. $zipFile->close();
  1409. }
  1410. /**
  1411. * @expectedException \PhpZip\Exception\InvalidArgumentException
  1412. * @expectedExceptionMessage DirName empty
  1413. */
  1414. public function testAddEmptyDirNullName()
  1415. {
  1416. $zipFile = new ZipFile();
  1417. $zipFile->addEmptyDir(null);
  1418. }
  1419. /**
  1420. * @expectedException \PhpZip\Exception\InvalidArgumentException
  1421. * @expectedExceptionMessage DirName empty
  1422. */
  1423. public function testAddEmptyDirEmptyName()
  1424. {
  1425. $zipFile = new ZipFile();
  1426. $zipFile->addEmptyDir("");
  1427. }
  1428. /**
  1429. * @expectedException \PhpZip\Exception\InvalidArgumentException
  1430. * @expectedExceptionMessage Output filename is empty.
  1431. */
  1432. public function testOutputAsAttachmentNullName()
  1433. {
  1434. $zipFile = new ZipFile();
  1435. $zipFile->outputAsAttachment(null);
  1436. }
  1437. /**
  1438. * @expectedException \PhpZip\Exception\InvalidArgumentException
  1439. * @expectedExceptionMessage Output filename is empty.
  1440. */
  1441. public function testOutputAsAttachmentEmptyName()
  1442. {
  1443. $zipFile = new ZipFile();
  1444. $zipFile->outputAsAttachment('');
  1445. }
  1446. /**
  1447. * @expectedException \PhpZip\Exception\ZipNotFoundEntry
  1448. * @expectedExceptionMessage Zip entry bad entry name not found
  1449. */
  1450. public function testNotFoundEntry()
  1451. {
  1452. $zipFile = new ZipFile();
  1453. $zipFile['bad entry name'];
  1454. }
  1455. /**
  1456. * Test rewrite input file.
  1457. */
  1458. public function testRewriteFile()
  1459. {
  1460. $zipFile = new ZipFile();
  1461. $zipFile['file'] = 'content';
  1462. $zipFile['file2'] = 'content2';
  1463. self::assertEquals(count($zipFile), 2);
  1464. $zipFile
  1465. ->saveAsFile($this->outputFilename)
  1466. ->close();
  1467. $md5file = md5_file($this->outputFilename);
  1468. $zipFile->openFile($this->outputFilename);
  1469. self::assertEquals(count($zipFile), 2);
  1470. self::assertTrue(isset($zipFile['file']));
  1471. self::assertTrue(isset($zipFile['file2']));
  1472. $zipFile['file3'] = 'content3';
  1473. self::assertEquals(count($zipFile), 3);
  1474. $zipFile = $zipFile->rewrite();
  1475. self::assertEquals(count($zipFile), 3);
  1476. self::assertTrue(isset($zipFile['file']));
  1477. self::assertTrue(isset($zipFile['file2']));
  1478. self::assertTrue(isset($zipFile['file3']));
  1479. $zipFile->close();
  1480. self::assertNotEquals(md5_file($this->outputFilename), $md5file);
  1481. }
  1482. /**
  1483. * Test rewrite for string.
  1484. */
  1485. public function testRewriteString()
  1486. {
  1487. $zipFile = new ZipFile();
  1488. $zipFile['file'] = 'content';
  1489. $zipFile['file2'] = 'content2';
  1490. $zipFile->saveAsFile($this->outputFilename);
  1491. $zipFile->close();
  1492. $zipFile->openFromString(file_get_contents($this->outputFilename));
  1493. self::assertEquals(count($zipFile), 2);
  1494. self::assertTrue(isset($zipFile['file']));
  1495. self::assertTrue(isset($zipFile['file2']));
  1496. $zipFile['file3'] = 'content3';
  1497. $zipFile = $zipFile->rewrite();
  1498. self::assertEquals(count($zipFile), 3);
  1499. self::assertTrue(isset($zipFile['file']));
  1500. self::assertTrue(isset($zipFile['file2']));
  1501. self::assertTrue(isset($zipFile['file3']));
  1502. $zipFile->close();
  1503. }
  1504. /**
  1505. * @expectedException \PhpZip\Exception\ZipException
  1506. * @expectedExceptionMessage input stream is null
  1507. */
  1508. public function testRewriteNullStream()
  1509. {
  1510. $zipFile = new ZipFile();
  1511. $zipFile->rewrite();
  1512. }
  1513. /**
  1514. * Test zip alignment.
  1515. */
  1516. public function testZipAlignSourceZip()
  1517. {
  1518. $zipFile = new ZipFile();
  1519. for ($i = 0; $i < 100; $i++) {
  1520. $zipFile->addFromString(
  1521. 'entry' . $i . '.txt',
  1522. CryptoUtil::randomBytes(mt_rand(100, 4096)),
  1523. ZipFileInterface::METHOD_STORED
  1524. );
  1525. }
  1526. $zipFile->saveAsFile($this->outputFilename);
  1527. $zipFile->close();
  1528. self::assertCorrectZipArchive($this->outputFilename);
  1529. $result = self::doZipAlignVerify($this->outputFilename);
  1530. if ($result === null) {
  1531. return;
  1532. } // zip align not installed
  1533. // check not zip align
  1534. self::assertFalse($result);
  1535. $zipFile->openFile($this->outputFilename);
  1536. $zipFile->setZipAlign(4);
  1537. $zipFile->saveAsFile($this->outputFilename);
  1538. $zipFile->close();
  1539. self::assertCorrectZipArchive($this->outputFilename);
  1540. $result = self::doZipAlignVerify($this->outputFilename, true);
  1541. self::assertNotNull($result);
  1542. // check zip align
  1543. self::assertTrue($result);
  1544. }
  1545. public function testZipAlignNewFiles()
  1546. {
  1547. $zipFile = new ZipFile();
  1548. for ($i = 0; $i < 100; $i++) {
  1549. $zipFile->addFromString(
  1550. 'entry' . $i . '.txt',
  1551. CryptoUtil::randomBytes(mt_rand(100, 4096)),
  1552. ZipFileInterface::METHOD_STORED
  1553. );
  1554. }
  1555. $zipFile->setZipAlign(4);
  1556. $zipFile->saveAsFile($this->outputFilename);
  1557. $zipFile->close();
  1558. self::assertCorrectZipArchive($this->outputFilename);
  1559. $result = self::doZipAlignVerify($this->outputFilename);
  1560. if ($result === null) {
  1561. return;
  1562. } // zip align not installed
  1563. // check not zip align
  1564. self::assertTrue($result);
  1565. }
  1566. public function testZipAlignFromModifiedZipArchive()
  1567. {
  1568. $zipFile = new ZipFile();
  1569. for ($i = 0; $i < 100; $i++) {
  1570. $zipFile->addFromString(
  1571. 'entry' . $i . '.txt',
  1572. CryptoUtil::randomBytes(mt_rand(100, 4096)),
  1573. ZipFileInterface::METHOD_STORED
  1574. );
  1575. }
  1576. $zipFile->saveAsFile($this->outputFilename);
  1577. $zipFile->close();
  1578. self::assertCorrectZipArchive($this->outputFilename);
  1579. $result = self::doZipAlignVerify($this->outputFilename);
  1580. if ($result === null) {
  1581. return;
  1582. } // zip align not installed
  1583. // check not zip align
  1584. self::assertFalse($result);
  1585. $zipFile->openFile($this->outputFilename);
  1586. $zipFile->deleteFromRegex("~entry2[\d]+\.txt$~s");
  1587. for ($i = 0; $i < 100; $i++) {
  1588. $isStored = (bool)mt_rand(0, 1);
  1589. $zipFile->addFromString(
  1590. 'entry_new_' . ($isStored ? 'stored' : 'deflated') . '_' . $i . '.txt',
  1591. CryptoUtil::randomBytes(mt_rand(100, 4096)),
  1592. $isStored ?
  1593. ZipFileInterface::METHOD_STORED :
  1594. ZipFileInterface::METHOD_DEFLATED
  1595. );
  1596. }
  1597. $zipFile->setZipAlign(4);
  1598. $zipFile->saveAsFile($this->outputFilename);
  1599. $zipFile->close();
  1600. self::assertCorrectZipArchive($this->outputFilename);
  1601. $result = self::doZipAlignVerify($this->outputFilename, true);
  1602. self::assertNotNull($result);
  1603. // check zip align
  1604. self::assertTrue($result);
  1605. }
  1606. public function testFilename0()
  1607. {
  1608. $zipFile = new ZipFile();
  1609. $zipFile[0] = 0;
  1610. self::assertTrue(isset($zipFile[0]));
  1611. self::assertTrue(isset($zipFile['0']));
  1612. self::assertCount(1, $zipFile);
  1613. $zipFile
  1614. ->saveAsFile($this->outputFilename)
  1615. ->close();
  1616. self::assertCorrectZipArchive($this->outputFilename);
  1617. $zipFile->openFile($this->outputFilename);
  1618. self::assertTrue(isset($zipFile[0]));
  1619. self::assertTrue(isset($zipFile['0']));
  1620. self::assertEquals($zipFile['0'], '0');
  1621. self::assertCount(1, $zipFile);
  1622. $zipFile->close();
  1623. self::assertTrue(unlink($this->outputFilename));
  1624. $zipFile = new ZipFile();
  1625. $zipFile->addFromString(0, 0);
  1626. self::assertTrue(isset($zipFile[0]));
  1627. self::assertTrue(isset($zipFile['0']));
  1628. self::assertCount(1, $zipFile);
  1629. $zipFile
  1630. ->saveAsFile($this->outputFilename)
  1631. ->close();
  1632. self::assertCorrectZipArchive($this->outputFilename);
  1633. }
  1634. public function testPsrResponse()
  1635. {
  1636. $zipFile = new ZipFile();
  1637. for ($i = 0; $i < 10; $i++) {
  1638. $zipFile[$i] = $i;
  1639. }
  1640. $filename = 'file.jar';
  1641. $response = $this->getMock(ResponseInterface::class);
  1642. $response = $zipFile->outputAsResponse($response, $filename);
  1643. $this->assertInstanceOf(ResponseInterface::class, $response);
  1644. }
  1645. /**
  1646. * @expectedException \PhpZip\Exception\InvalidArgumentException
  1647. * @expectedExceptionMessage Output filename is empty.
  1648. */
  1649. public function testInvalidPsrResponse()
  1650. {
  1651. $zipFile = new ZipFile();
  1652. $zipFile['file'] = 'content';
  1653. $response = $this->getMock(ResponseInterface::class);
  1654. $zipFile->outputAsResponse($response, '');
  1655. }
  1656. public function testCompressionLevel()
  1657. {
  1658. $zipFile = new ZipFile();
  1659. $zipFile
  1660. ->addFromString('file', 'content', ZipFileInterface::METHOD_DEFLATED)
  1661. ->setCompressionLevelEntry('file', ZipFileInterface::LEVEL_BEST_COMPRESSION)
  1662. ->addFromString('file2', 'content', ZipFileInterface::METHOD_DEFLATED)
  1663. ->setCompressionLevelEntry('file2', ZipFileInterface::LEVEL_FAST)
  1664. ->addFromString('file3', 'content', ZipFileInterface::METHOD_DEFLATED)
  1665. ->setCompressionLevelEntry('file3', ZipFileInterface::LEVEL_SUPER_FAST)
  1666. ->addFromString('file4', 'content', ZipFileInterface::METHOD_DEFLATED)
  1667. ->setCompressionLevelEntry('file4', ZipFileInterface::LEVEL_DEFAULT_COMPRESSION)
  1668. ->saveAsFile($this->outputFilename)
  1669. ->close();
  1670. self::assertCorrectZipArchive($this->outputFilename);
  1671. $zipFile->openFile($this->outputFilename);
  1672. self::assertEquals($zipFile->getEntryInfo('file')
  1673. ->getCompressionLevel(), ZipFileInterface::LEVEL_BEST_COMPRESSION);
  1674. self::assertEquals($zipFile->getEntryInfo('file2')
  1675. ->getCompressionLevel(), ZipFileInterface::LEVEL_FAST);
  1676. self::assertEquals($zipFile->getEntryInfo('file3')
  1677. ->getCompressionLevel(), ZipFileInterface::LEVEL_SUPER_FAST);
  1678. self::assertEquals($zipFile->getEntryInfo('file4')
  1679. ->getCompressionLevel(), ZipFileInterface::LEVEL_DEFAULT_COMPRESSION);
  1680. $zipFile->close();
  1681. }
  1682. /**
  1683. * @expectedException \PhpZip\Exception\InvalidArgumentException
  1684. * @expectedExceptionMessage Invalid compression level
  1685. */
  1686. public function testInvalidCompressionLevel()
  1687. {
  1688. $zipFile = new ZipFile();
  1689. $zipFile->addFromString('file', 'content');
  1690. $zipFile->setCompressionLevel(15);
  1691. }
  1692. /**
  1693. * @expectedException \PhpZip\Exception\InvalidArgumentException
  1694. * @expectedExceptionMessage Invalid compression level
  1695. */
  1696. public function testInvalidCompressionLevelEntry()
  1697. {
  1698. $zipFile = new ZipFile();
  1699. $zipFile->addFromString('file', 'content');
  1700. $zipFile->setCompressionLevelEntry('file', 15);
  1701. }
  1702. public function testCompressionGlobal()
  1703. {
  1704. $zipFile = new ZipFile();
  1705. for ($i = 0; $i < 10; $i++) {
  1706. $zipFile->addFromString('file' . $i, 'content', ZipFileInterface::METHOD_DEFLATED);
  1707. }
  1708. $zipFile
  1709. ->setCompressionLevel(ZipFileInterface::LEVEL_BEST_SPEED)
  1710. ->saveAsFile($this->outputFilename)
  1711. ->close();
  1712. self::assertCorrectZipArchive($this->outputFilename);
  1713. $zipFile->openFile($this->outputFilename);
  1714. $infoList = $zipFile->getAllInfo();
  1715. array_walk($infoList, function (ZipInfo $zipInfo) {
  1716. self::assertEquals($zipInfo->getCompressionLevel(), ZipFileInterface::LEVEL_BEST_SPEED);
  1717. });
  1718. $zipFile->close();
  1719. }
  1720. public function testCompressionMethodEntry()
  1721. {
  1722. $zipFile = new ZipFile();
  1723. $zipFile->addFromString('file', 'content', ZipFileInterface::METHOD_STORED);
  1724. $zipFile->saveAsFile($this->outputFilename);
  1725. $zipFile->close();
  1726. $zipFile->openFile($this->outputFilename);
  1727. self::assertEquals($zipFile->getEntryInfo('file')->getMethodName(), 'No compression');
  1728. $zipFile->setCompressionMethodEntry('file', ZipFileInterface::METHOD_DEFLATED);
  1729. self::assertEquals($zipFile->getEntryInfo('file')->getMethodName(), 'Deflate');
  1730. $zipFile->rewrite();
  1731. self::assertEquals($zipFile->getEntryInfo('file')->getMethodName(), 'Deflate');
  1732. }
  1733. /**
  1734. * @expectedException \PhpZip\Exception\ZipUnsupportMethod
  1735. * @expectedExceptionMessage Unsupported method
  1736. */
  1737. public function testInvalidCompressionMethodEntry()
  1738. {
  1739. $zipFile = new ZipFile();
  1740. $zipFile->addFromString('file', 'content', ZipFileInterface::METHOD_STORED);
  1741. $zipFile->setCompressionMethodEntry('file', 99);
  1742. }
  1743. public function testUnchangeAll()
  1744. {
  1745. $zipFile = new ZipFile();
  1746. for ($i = 0; $i < 10; $i++) {
  1747. $zipFile[$i] = $i;
  1748. }
  1749. $zipFile->setArchiveComment('comment');
  1750. self::assertCount(10, $zipFile);
  1751. self::assertEquals($zipFile->getArchiveComment(), 'comment');
  1752. $zipFile->saveAsFile($this->outputFilename);
  1753. $zipFile->unchangeAll();
  1754. self::assertCount(0, $zipFile);
  1755. self::assertEquals($zipFile->getArchiveComment(), null);
  1756. $zipFile->close();
  1757. $zipFile->openFile($this->outputFilename);
  1758. self::assertCount(10, $zipFile);
  1759. self::assertEquals($zipFile->getArchiveComment(), 'comment');
  1760. for ($i = 10; $i < 100; $i++) {
  1761. $zipFile[$i] = $i;
  1762. }
  1763. $zipFile->setArchiveComment('comment 2');
  1764. self::assertCount(100, $zipFile);
  1765. self::assertEquals($zipFile->getArchiveComment(), 'comment 2');
  1766. $zipFile->unchangeAll();
  1767. self::assertCount(10, $zipFile);
  1768. self::assertEquals($zipFile->getArchiveComment(), 'comment');
  1769. $zipFile->close();
  1770. }
  1771. public function testUnchangeArchiveComment()
  1772. {
  1773. $zipFile = new ZipFile();
  1774. for ($i = 0; $i < 10; $i++) {
  1775. $zipFile[$i] = $i;
  1776. }
  1777. $zipFile->setArchiveComment('comment');
  1778. self::assertEquals($zipFile->getArchiveComment(), 'comment');
  1779. $zipFile->saveAsFile($this->outputFilename);
  1780. $zipFile->unchangeArchiveComment();
  1781. self::assertEquals($zipFile->getArchiveComment(), null);
  1782. $zipFile->close();
  1783. $zipFile->openFile($this->outputFilename);
  1784. self::assertEquals($zipFile->getArchiveComment(), 'comment');
  1785. $zipFile->setArchiveComment('comment 2');
  1786. self::assertEquals($zipFile->getArchiveComment(), 'comment 2');
  1787. $zipFile->unchangeArchiveComment();
  1788. self::assertEquals($zipFile->getArchiveComment(), 'comment');
  1789. $zipFile->close();
  1790. }
  1791. public function testUnchangeEntry()
  1792. {
  1793. $zipFile = new ZipFile();
  1794. $zipFile['file 1'] = 'content 1';
  1795. $zipFile['file 2'] = 'content 2';
  1796. $zipFile
  1797. ->saveAsFile($this->outputFilename)
  1798. ->close();
  1799. $zipFile->openFile($this->outputFilename);
  1800. $zipFile['file 1'] = 'modify content 1';
  1801. $zipFile->setPasswordEntry('file 1', 'password');
  1802. self::assertEquals($zipFile['file 1'], 'modify content 1');
  1803. self::assertTrue($zipFile->getEntryInfo('file 1')->isEncrypted());
  1804. self::assertEquals($zipFile['file 2'], 'content 2');
  1805. self::assertFalse($zipFile->getEntryInfo('file 2')->isEncrypted());
  1806. $zipFile->unchangeEntry('file 1');
  1807. self::assertEquals($zipFile['file 1'], 'content 1');
  1808. self::assertFalse($zipFile->getEntryInfo('file 1')->isEncrypted());
  1809. self::assertEquals($zipFile['file 2'], 'content 2');
  1810. self::assertFalse($zipFile->getEntryInfo('file 2')->isEncrypted());
  1811. $zipFile->close();
  1812. }
  1813. /**
  1814. * Test support ZIP64 ext (slow test - normal).
  1815. * Create > 65535 files in archive and open and extract to /dev/null.
  1816. */
  1817. public function testCreateAndOpenZip64Ext()
  1818. {
  1819. $countFiles = 0xffff + 1;
  1820. $zipFile = new ZipFile();
  1821. for ($i = 0; $i < $countFiles; $i++) {
  1822. $zipFile[$i . '.txt'] = $i;
  1823. }
  1824. $zipFile->saveAsFile($this->outputFilename);
  1825. $zipFile->close();
  1826. self::assertCorrectZipArchive($this->outputFilename);
  1827. $zipFile->openFile($this->outputFilename);
  1828. self::assertEquals($zipFile->count(), $countFiles);
  1829. $i = 0;
  1830. foreach ($zipFile as $entry => $content) {
  1831. self::assertEquals($entry, $i . '.txt');
  1832. self::assertEquals($content, $i);
  1833. $i++;
  1834. }
  1835. $zipFile->close();
  1836. }
  1837. }