Skip to content

Commit

Permalink
Merge branch 'release/3.1.0'
Browse files Browse the repository at this point in the history
  • Loading branch information
Ne-Lexa committed Nov 14, 2017
2 parents 42c0fc5 + ab41e70 commit 0788892
Show file tree
Hide file tree
Showing 74 changed files with 7,196 additions and 3,476 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
/vendor
*.iml
/.idea
/composer.lock
/composer.lock
/.php_cs.cache
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,4 @@ before_script:

script:
- composer validate --no-check-lock
- vendor/bin/phpunit -v -c bootstrap.xml
- vendor/bin/phpunit -v -c phpunit.xml
19 changes: 19 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,22 @@
# Changelog

## 3.1.0 (2017-11-14)
- Added class `ZipModel` for all changes.
- All manipulations with incoming and outgoing streams are in separate files: `ZipInputStream` and `ZipOutputStream`.
- Removed class `CentralDirectory`.
- Optimized extra fields classes.
- Fixed issue #4 (`count()` returns 0 when files are added in directories).
- Implemented issue #8 - support inline Content-Disposition and empty output filename.
- Optimized and tested on a php 32-bit platform (issue #5).
- Added output as PSR-7 Response.
- Added methods for canceling changes.
- Added [russian documentation](README.RU.md).
- Updated [documentation](README.md).
- Declared deprecated methods:
+ rename `ZipFile::withReadPassword` to `ZipFile::setReadPassword`
+ rename `ZipFile::withNewPassword` to `ZipFile::setPassword`
+ rename `ZipFile::withoutPassword` to `ZipFile::disableEncryption`

## 3.0.3 (2017-11-11)
Fix bug issue #8 - Error if the file is empty.

Expand Down
821 changes: 821 additions & 0 deletions README.RU.md

Large diffs are not rendered by default.

727 changes: 501 additions & 226 deletions README.md

Large diffs are not rendered by default.

10 changes: 0 additions & 10 deletions bootstrap.xml

This file was deleted.

11 changes: 6 additions & 5 deletions composer.json
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
{
"name": "nelexa/zip",
"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.",
"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.",
"type": "library",
"keywords": [
"zip",
"unzip",
"archive",
"extract",
"winzip",
"zipalign"
"zipalign",
"ziparchive"
],
"require-dev": {
"phpunit/phpunit": "4.8",
"codeclimate/php-test-reporter": "^0.4.4"
"phpunit/phpunit": "4.8"
},
"license": "MIT",
"authors": [
Expand All @@ -24,7 +24,8 @@
],
"minimum-stability": "stable",
"require": {
"php": "^5.5 || ^7.0"
"php": "^5.5 || ^7.0",
"psr/http-message": "^1.0"
},
"autoload": {
"psr-4": {
Expand Down
23 changes: 23 additions & 0 deletions phpunit.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="utf-8" ?>

<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="http://schema.phpunit.de/4.8/phpunit.xsd"
backupGlobals="false"
colors="true"
bootstrap="vendor/autoload.php">
<php>
<ini name="error_reporting" value="-1"/>
</php>

<testsuites>
<testsuite name="PhpZip test suite">
<directory>tests</directory>
</testsuite>
</testsuites>

<filter>
<whitelist>
<directory>src</directory>
</whitelist>
</filter>
</phpunit>
37 changes: 13 additions & 24 deletions src/PhpZip/Crypto/TraditionalPkwareEncryptionEngine.php
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
<?php

namespace PhpZip\Crypto;

use PhpZip\Exception\ZipAuthenticationException;
use PhpZip\Exception\ZipCryptoException;
use PhpZip\Model\ZipEntry;
use PhpZip\Util\CryptoUtil;
use PhpZip\Util\PackUtil;

/**
* Traditional PKWARE Encryption Engine.
Expand All @@ -13,7 +15,7 @@
* @author Ne-Lexa alexey@nelexa.ru
* @license MIT
*/
class TraditionalPkwareEncryptionEngine implements CryptoEngine
class TraditionalPkwareEncryptionEngine implements ZipEncryptionEngine
{
/**
* Encryption header size
Expand Down Expand Up @@ -66,7 +68,6 @@ class TraditionalPkwareEncryptionEngine implements CryptoEngine
* @var array
*/
private $keys = [];

/**
* @var ZipEntry
*/
Expand All @@ -80,7 +81,6 @@ class TraditionalPkwareEncryptionEngine implements CryptoEngine
public function __construct(ZipEntry $entry)
{
$this->entry = $entry;
$this->initKeys($entry->getPassword());
}

/**
Expand All @@ -107,25 +107,8 @@ private function updateKeys($charAt)
{
$this->keys[0] = self::crc32($this->keys[0], $charAt);
$this->keys[1] = $this->keys[1] + ($this->keys[0] & 0xff);
$this->keys[1] = self::toInt($this->keys[1] * 134775813 + 1);
$this->keys[2] = self::toInt(self::crc32($this->keys[2], ($this->keys[1] >> 24) & 0xff));
}

/**
* Cast to int
*
* @param $i
* @return int
*/
private static function toInt($i)
{
$i = (int)($i & 0xffffffff);
if ($i > 2147483647) {
return -(-$i & 0xffffffff);
} elseif ($i < -2147483648) {
return $i & -2147483648;
}
return $i;
$this->keys[1] = PackUtil::toSignedInt32($this->keys[1] * 134775813 + 1);
$this->keys[2] = PackUtil::toSignedInt32(self::crc32($this->keys[2], ($this->keys[1] >> 24) & 0xff));
}

/**
Expand All @@ -147,7 +130,11 @@ private function crc32($oldCrc, $charAt)
*/
public function decrypt($content)
{
$password = $this->entry->getPassword();
$this->initKeys($password);

$headerBytes = array_values(unpack('C*', substr($content, 0, self::STD_DEC_HDR_SIZE)));
$byte = 0;
foreach ($headerBytes as &$byte) {
$byte = ($byte ^ $this->decryptByte()) & 0xff;
$this->updateKeys($byte);
Expand Down Expand Up @@ -198,7 +185,9 @@ public function encrypt($data)
$headerBytes = CryptoUtil::randomBytes(self::STD_DEC_HDR_SIZE);

// Initialize again since the generated bytes were encrypted.
$this->initKeys($this->entry->getPassword());
$password = $this->entry->getPassword();
$this->initKeys($password);

$headerBytes[self::STD_DEC_HDR_SIZE - 1] = pack('c', ($crc >> 24) & 0xff);
$headerBytes[self::STD_DEC_HDR_SIZE - 2] = pack('c', ($crc >> 16) & 0xff);

Expand Down Expand Up @@ -233,4 +222,4 @@ private function encryptByte($byte)
$this->updateKeys($byte);
return $tempVal;
}
}
}
23 changes: 14 additions & 9 deletions src/PhpZip/Crypto/WinZipAesEngine.php
Original file line number Diff line number Diff line change
@@ -1,20 +1,22 @@
<?php

namespace PhpZip\Crypto;

use PhpZip\Exception\RuntimeException;
use PhpZip\Exception\ZipAuthenticationException;
use PhpZip\Exception\ZipCryptoException;
use PhpZip\Extra\WinZipAesEntryExtraField;
use PhpZip\Extra\Fields\WinZipAesEntryExtraField;
use PhpZip\Model\ZipEntry;
use PhpZip\Util\CryptoUtil;

/**
* WinZip Aes Encryption Engine.
*
* @see https://pkware.cachefly.net/webdocs/casestudies/APPNOTE.TXT .ZIP File Format Specification
* @author Ne-Lexa alexey@nelexa.ru
* @license MIT
*/
class WinZipAesEngine implements CryptoEngine
class WinZipAesEngine implements ZipEncryptionEngine
{
/**
* The block size of the Advanced Encryption Specification (AES) Algorithm
Expand Down Expand Up @@ -50,13 +52,16 @@ public function __construct(ZipEntry $entry)
*/
public function decrypt($content)
{
$extraFieldsCollection = $this->entry->getExtraFieldsCollection();

if (!isset($extraFieldsCollection[WinZipAesEntryExtraField::getHeaderId()])) {
throw new ZipCryptoException($this->entry->getName() . " (missing extra field for WinZip AES entry)");
}

/**
* @var WinZipAesEntryExtraField $field
*/
$field = $this->entry->getExtraField(WinZipAesEntryExtraField::getHeaderId());
if (null === $field) {
throw new ZipCryptoException($this->entry->getName() . " (missing extra field for WinZip AES entry)");
}
$field = $extraFieldsCollection[WinZipAesEntryExtraField::getHeaderId()];

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

$keyStrengthBytes = 32;
$keyStrengthBits = $keyStrengthBytes * 8;
$keyStrengthBits = WinZipAesEntryExtraField::getKeyStrangeFromEncryptionMethod($this->entry->getEncryptionMethod());
$keyStrengthBytes = $keyStrengthBits / 8;

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

Expand All @@ -244,4 +249,4 @@ public function encrypt($content)
substr($mac, 0, 10)
);
}
}
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,17 @@
<?php

namespace PhpZip\Crypto;

use PhpZip\Exception\ZipAuthenticationException;

interface CryptoEngine
/**
* Encryption Engine
*
* @see https://pkware.cachefly.net/webdocs/casestudies/APPNOTE.TXT .ZIP File Format Specification
* @author Ne-Lexa alexey@nelexa.ru
* @license MIT
*/
interface ZipEncryptionEngine
{
/**
* Decryption string.
Expand All @@ -21,4 +29,4 @@ public function decrypt($encryptionContent);
* @return string
*/
public function encrypt($content);
}
}
14 changes: 5 additions & 9 deletions src/PhpZip/Exception/Crc32Exception.php
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
<?php

namespace PhpZip\Exception;

/**
* Thrown to indicate a CRC32 mismatch between the declared value in the
* Central File Header and the Data Descriptor or between the declared value
* and the computed value from the decompressed data.
*
* The exception's detail message is the name of the ZIP entry.
* The exception detail message is the name of the ZIP entry.
*
* @author Ne-Lexa alexey@nelexa.ru
* @license MIT
Expand Down Expand Up @@ -36,12 +37,8 @@ class Crc32Exception extends ZipException
*/
public function __construct($name, $expected, $actual)
{
parent::__construct($name
. " (expected CRC32 value 0x"
. dechex($expected)
. ", but is actually 0x"
. dechex($actual)
. ")");
parent::__construct($name . " (expected CRC32 value 0x" .
dechex($expected) . ", but is actually 0x" . dechex($actual) . ")");
assert($expected != $actual);
$this->expectedCrc = $expected;
$this->actualCrc = $actual;
Expand All @@ -66,5 +63,4 @@ public function getActualCrc()
{
return $this->actualCrc;
}

}
}
6 changes: 3 additions & 3 deletions src/PhpZip/Exception/InvalidArgumentException.php
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
<?php

namespace PhpZip\Exception;

/**
Expand All @@ -8,7 +9,6 @@
* @author Ne-Lexa alexey@nelexa.ru
* @license MIT
*/
class InvalidArgumentException extends ZipException
class InvalidArgumentException extends RuntimeException
{

}
}
4 changes: 2 additions & 2 deletions src/PhpZip/Exception/RuntimeException.php
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
<?php

namespace PhpZip\Exception;

/**
Expand All @@ -9,5 +10,4 @@
*/
class RuntimeException extends ZipException
{

}
}
4 changes: 2 additions & 2 deletions src/PhpZip/Exception/ZipAuthenticationException.php
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
<?php

namespace PhpZip\Exception;

/**
Expand All @@ -9,5 +10,4 @@
*/
class ZipAuthenticationException extends ZipCryptoException
{

}
}
4 changes: 2 additions & 2 deletions src/PhpZip/Exception/ZipCryptoException.php
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
<?php

namespace PhpZip\Exception;

/**
Expand All @@ -10,5 +11,4 @@
*/
class ZipCryptoException extends ZipException
{

}
}
Loading

0 comments on commit 0788892

Please sign in to comment.