Skip to content

Commit 0788892

Browse files
committed
Merge branch 'release/3.1.0'
2 parents 42c0fc5 + ab41e70 commit 0788892

File tree

74 files changed

+7196
-3476
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

74 files changed

+7196
-3476
lines changed

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
/vendor
22
*.iml
33
/.idea
4-
/composer.lock
4+
/composer.lock
5+
/.php_cs.cache

.travis.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,4 +21,4 @@ before_script:
2121

2222
script:
2323
- composer validate --no-check-lock
24-
- vendor/bin/phpunit -v -c bootstrap.xml
24+
- vendor/bin/phpunit -v -c phpunit.xml

CHANGELOG.md

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,22 @@
1+
# Changelog
2+
3+
## 3.1.0 (2017-11-14)
4+
- Added class `ZipModel` for all changes.
5+
- All manipulations with incoming and outgoing streams are in separate files: `ZipInputStream` and `ZipOutputStream`.
6+
- Removed class `CentralDirectory`.
7+
- Optimized extra fields classes.
8+
- Fixed issue #4 (`count()` returns 0 when files are added in directories).
9+
- Implemented issue #8 - support inline Content-Disposition and empty output filename.
10+
- Optimized and tested on a php 32-bit platform (issue #5).
11+
- Added output as PSR-7 Response.
12+
- Added methods for canceling changes.
13+
- Added [russian documentation](README.RU.md).
14+
- Updated [documentation](README.md).
15+
- Declared deprecated methods:
16+
+ rename `ZipFile::withReadPassword` to `ZipFile::setReadPassword`
17+
+ rename `ZipFile::withNewPassword` to `ZipFile::setPassword`
18+
+ rename `ZipFile::withoutPassword` to `ZipFile::disableEncryption`
19+
120
## 3.0.3 (2017-11-11)
221
Fix bug issue #8 - Error if the file is empty.
322

README.RU.md

Lines changed: 821 additions & 0 deletions
Large diffs are not rendered by default.

README.md

Lines changed: 501 additions & 226 deletions
Large diffs are not rendered by default.

bootstrap.xml

Lines changed: 0 additions & 10 deletions
This file was deleted.

composer.json

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,18 @@
11
{
22
"name": "nelexa/zip",
3-
"description": "Zip files CRUD. Open, create, update, extract and get info tool. Supports appending to existing ZIP files, WinZip AES encryption, Traditional PKWARE Encryption, ZipAlign tool, BZIP2 compression, external file attributes and ZIP64 extensions. Alternative ZipArchive. It does not require php-zip extension.",
3+
"description": "PhpZip is a php-library for extended work with ZIP-archives. Open, create, update, delete, extract and get info tool. Supports appending to existing ZIP files, WinZip AES encryption, Traditional PKWARE Encryption, ZipAlign tool, BZIP2 compression, external file attributes and ZIP64 extensions. Alternative ZipArchive. It does not require php-zip extension.",
44
"type": "library",
55
"keywords": [
66
"zip",
77
"unzip",
88
"archive",
99
"extract",
1010
"winzip",
11-
"zipalign"
11+
"zipalign",
12+
"ziparchive"
1213
],
1314
"require-dev": {
14-
"phpunit/phpunit": "4.8",
15-
"codeclimate/php-test-reporter": "^0.4.4"
15+
"phpunit/phpunit": "4.8"
1616
},
1717
"license": "MIT",
1818
"authors": [
@@ -24,7 +24,8 @@
2424
],
2525
"minimum-stability": "stable",
2626
"require": {
27-
"php": "^5.5 || ^7.0"
27+
"php": "^5.5 || ^7.0",
28+
"psr/http-message": "^1.0"
2829
},
2930
"autoload": {
3031
"psr-4": {

phpunit.xml

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<?xml version="1.0" encoding="utf-8" ?>
2+
3+
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4+
xsi:noNamespaceSchemaLocation="http://schema.phpunit.de/4.8/phpunit.xsd"
5+
backupGlobals="false"
6+
colors="true"
7+
bootstrap="vendor/autoload.php">
8+
<php>
9+
<ini name="error_reporting" value="-1"/>
10+
</php>
11+
12+
<testsuites>
13+
<testsuite name="PhpZip test suite">
14+
<directory>tests</directory>
15+
</testsuite>
16+
</testsuites>
17+
18+
<filter>
19+
<whitelist>
20+
<directory>src</directory>
21+
</whitelist>
22+
</filter>
23+
</phpunit>

src/PhpZip/Crypto/TraditionalPkwareEncryptionEngine.php

Lines changed: 13 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
<?php
2+
23
namespace PhpZip\Crypto;
34

45
use PhpZip\Exception\ZipAuthenticationException;
56
use PhpZip\Exception\ZipCryptoException;
67
use PhpZip\Model\ZipEntry;
78
use PhpZip\Util\CryptoUtil;
9+
use PhpZip\Util\PackUtil;
810

911
/**
1012
* Traditional PKWARE Encryption Engine.
@@ -13,7 +15,7 @@
1315
* @author Ne-Lexa [email protected]
1416
* @license MIT
1517
*/
16-
class TraditionalPkwareEncryptionEngine implements CryptoEngine
18+
class TraditionalPkwareEncryptionEngine implements ZipEncryptionEngine
1719
{
1820
/**
1921
* Encryption header size
@@ -66,7 +68,6 @@ class TraditionalPkwareEncryptionEngine implements CryptoEngine
6668
* @var array
6769
*/
6870
private $keys = [];
69-
7071
/**
7172
* @var ZipEntry
7273
*/
@@ -80,7 +81,6 @@ class TraditionalPkwareEncryptionEngine implements CryptoEngine
8081
public function __construct(ZipEntry $entry)
8182
{
8283
$this->entry = $entry;
83-
$this->initKeys($entry->getPassword());
8484
}
8585

8686
/**
@@ -107,25 +107,8 @@ private function updateKeys($charAt)
107107
{
108108
$this->keys[0] = self::crc32($this->keys[0], $charAt);
109109
$this->keys[1] = $this->keys[1] + ($this->keys[0] & 0xff);
110-
$this->keys[1] = self::toInt($this->keys[1] * 134775813 + 1);
111-
$this->keys[2] = self::toInt(self::crc32($this->keys[2], ($this->keys[1] >> 24) & 0xff));
112-
}
113-
114-
/**
115-
* Cast to int
116-
*
117-
* @param $i
118-
* @return int
119-
*/
120-
private static function toInt($i)
121-
{
122-
$i = (int)($i & 0xffffffff);
123-
if ($i > 2147483647) {
124-
return -(-$i & 0xffffffff);
125-
} elseif ($i < -2147483648) {
126-
return $i & -2147483648;
127-
}
128-
return $i;
110+
$this->keys[1] = PackUtil::toSignedInt32($this->keys[1] * 134775813 + 1);
111+
$this->keys[2] = PackUtil::toSignedInt32(self::crc32($this->keys[2], ($this->keys[1] >> 24) & 0xff));
129112
}
130113

131114
/**
@@ -147,7 +130,11 @@ private function crc32($oldCrc, $charAt)
147130
*/
148131
public function decrypt($content)
149132
{
133+
$password = $this->entry->getPassword();
134+
$this->initKeys($password);
135+
150136
$headerBytes = array_values(unpack('C*', substr($content, 0, self::STD_DEC_HDR_SIZE)));
137+
$byte = 0;
151138
foreach ($headerBytes as &$byte) {
152139
$byte = ($byte ^ $this->decryptByte()) & 0xff;
153140
$this->updateKeys($byte);
@@ -198,7 +185,9 @@ public function encrypt($data)
198185
$headerBytes = CryptoUtil::randomBytes(self::STD_DEC_HDR_SIZE);
199186

200187
// Initialize again since the generated bytes were encrypted.
201-
$this->initKeys($this->entry->getPassword());
188+
$password = $this->entry->getPassword();
189+
$this->initKeys($password);
190+
202191
$headerBytes[self::STD_DEC_HDR_SIZE - 1] = pack('c', ($crc >> 24) & 0xff);
203192
$headerBytes[self::STD_DEC_HDR_SIZE - 2] = pack('c', ($crc >> 16) & 0xff);
204193

@@ -233,4 +222,4 @@ private function encryptByte($byte)
233222
$this->updateKeys($byte);
234223
return $tempVal;
235224
}
236-
}
225+
}

src/PhpZip/Crypto/WinZipAesEngine.php

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,22 @@
11
<?php
2+
23
namespace PhpZip\Crypto;
34

45
use PhpZip\Exception\RuntimeException;
56
use PhpZip\Exception\ZipAuthenticationException;
67
use PhpZip\Exception\ZipCryptoException;
7-
use PhpZip\Extra\WinZipAesEntryExtraField;
8+
use PhpZip\Extra\Fields\WinZipAesEntryExtraField;
89
use PhpZip\Model\ZipEntry;
910
use PhpZip\Util\CryptoUtil;
1011

1112
/**
1213
* WinZip Aes Encryption Engine.
1314
*
15+
* @see https://pkware.cachefly.net/webdocs/casestudies/APPNOTE.TXT .ZIP File Format Specification
1416
* @author Ne-Lexa [email protected]
1517
* @license MIT
1618
*/
17-
class WinZipAesEngine implements CryptoEngine
19+
class WinZipAesEngine implements ZipEncryptionEngine
1820
{
1921
/**
2022
* The block size of the Advanced Encryption Specification (AES) Algorithm
@@ -50,13 +52,16 @@ public function __construct(ZipEntry $entry)
5052
*/
5153
public function decrypt($content)
5254
{
55+
$extraFieldsCollection = $this->entry->getExtraFieldsCollection();
56+
57+
if (!isset($extraFieldsCollection[WinZipAesEntryExtraField::getHeaderId()])) {
58+
throw new ZipCryptoException($this->entry->getName() . " (missing extra field for WinZip AES entry)");
59+
}
60+
5361
/**
5462
* @var WinZipAesEntryExtraField $field
5563
*/
56-
$field = $this->entry->getExtraField(WinZipAesEntryExtraField::getHeaderId());
57-
if (null === $field) {
58-
throw new ZipCryptoException($this->entry->getName() . " (missing extra field for WinZip AES entry)");
59-
}
64+
$field = $extraFieldsCollection[WinZipAesEntryExtraField::getHeaderId()];
6065

6166
// Get key strength.
6267
$keyStrengthBits = $field->getKeyStrength();
@@ -218,8 +223,8 @@ public function encrypt($content)
218223
// @see https://sourceforge.net/p/p7zip/discussion/383044/thread/c859a2f0/
219224
$password = substr($password, 0, 99);
220225

221-
$keyStrengthBytes = 32;
222-
$keyStrengthBits = $keyStrengthBytes * 8;
226+
$keyStrengthBits = WinZipAesEntryExtraField::getKeyStrangeFromEncryptionMethod($this->entry->getEncryptionMethod());
227+
$keyStrengthBytes = $keyStrengthBits / 8;
223228

224229
assert(self::AES_BLOCK_SIZE_BITS <= $keyStrengthBits);
225230

@@ -244,4 +249,4 @@ public function encrypt($content)
244249
substr($mac, 0, 10)
245250
);
246251
}
247-
}
252+
}

0 commit comments

Comments
 (0)