From 3bafe01ff0c7f0207abe1685250d1188290c93d5 Mon Sep 17 00:00:00 2001
From: Ne-Lexa
Date: Thu, 5 Dec 2019 19:36:11 +0300
Subject: [PATCH 1/8] php cs fix
---
.php_cs | 1500 +++++++++++++++++
.travis.yml | 1 +
composer.json | 14 +-
.../TraditionalPkwareEncryptionEngine.php | 350 +++-
src/PhpZip/Crypto/WinZipAesEngine.php | 155 +-
src/PhpZip/Crypto/ZipEncryptionEngine.php | 8 +-
src/PhpZip/Exception/Crc32Exception.php | 7 +-
.../Exception/ZipEntryNotFoundException.php | 15 +-
src/PhpZip/Exception/ZipException.php | 1 +
src/PhpZip/Exception/ZipNotFoundEntry.php | 14 -
src/PhpZip/Exception/ZipUnsupportMethod.php | 14 -
src/PhpZip/Extra/ExtraField.php | 2 +
src/PhpZip/Extra/ExtraFieldsCollection.php | 162 +-
src/PhpZip/Extra/ExtraFieldsFactory.php | 80 +-
.../Extra/Fields/ApkAlignmentExtraField.php | 24 +-
src/PhpZip/Extra/Fields/DefaultExtraField.php | 15 +-
.../Extra/Fields/JarMarkerExtraField.php | 5 +-
src/PhpZip/Extra/Fields/NtfsExtraField.php | 21 +-
.../Extra/Fields/WinZipAesEntryExtraField.php | 68 +-
src/PhpZip/Extra/Fields/Zip64ExtraField.php | 44 +-
src/PhpZip/Mapper/OffsetPositionMapper.php | 8 +-
src/PhpZip/Mapper/PositionMapper.php | 2 +
src/PhpZip/Model/EndOfCentralDirectory.php | 33 +-
src/PhpZip/Model/Entry/OutputOffsetEntry.php | 11 +-
src/PhpZip/Model/Entry/ZipAbstractEntry.php | 271 +--
src/PhpZip/Model/Entry/ZipChangesEntry.php | 14 +-
src/PhpZip/Model/Entry/ZipNewEntry.php | 32 +-
src/PhpZip/Model/Entry/ZipNewFileEntry.php | 20 +-
src/PhpZip/Model/Entry/ZipSourceEntry.php | 38 +-
src/PhpZip/Model/ZipEntry.php | 134 +-
src/PhpZip/Model/ZipEntryMatcher.php | 142 +-
src/PhpZip/Model/ZipInfo.php | 286 ++--
src/PhpZip/Model/ZipModel.php | 126 +-
src/PhpZip/Stream/ResponseStream.php | 166 +-
src/PhpZip/Stream/ZipInputStream.php | 256 +--
src/PhpZip/Stream/ZipInputStreamInterface.php | 10 +-
src/PhpZip/Stream/ZipOutputStream.php | 126 +-
.../Stream/ZipOutputStreamInterface.php | 2 +-
src/PhpZip/Util/CryptoUtil.php | 16 +-
src/PhpZip/Util/DateTimeConverter.php | 28 +-
src/PhpZip/Util/FilesUtil.php | 95 +-
.../Iterator/IgnoreFilesFilterIterator.php | 15 +-
.../IgnoreFilesRecursiveFilterIterator.php | 18 +-
src/PhpZip/Util/PackUtil.php | 25 +-
src/PhpZip/Util/StringUtil.php | 38 +-
src/PhpZip/Util/encodings/cp866-utf8.php | Bin 3831 -> 0 bytes
src/PhpZip/ZipFile.php | 860 ++++++----
src/PhpZip/ZipFileInterface.php | 340 ++--
.../PhpZip/Internal/DummyFileSystemStream.php | 57 +
tests/PhpZip/Internal/ZipFileExtended.php | 18 +
tests/PhpZip/Issue24Test.php | 76 +-
tests/PhpZip/PhpZipExtResourceTest.php | 74 +-
tests/PhpZip/Zip64Test.php | 45 +
tests/PhpZip/ZipAlignTest.php | 67 +-
tests/PhpZip/ZipEventTest.php | 45 +-
tests/PhpZip/ZipFileAddDirTest.php | 253 +--
tests/PhpZip/ZipFileTest.php | 1096 ++++++------
tests/PhpZip/ZipMatcherTest.php | 73 +-
tests/PhpZip/ZipPasswordTest.php | 217 ++-
tests/PhpZip/ZipRemoteFileTest.php | 50 +-
tests/PhpZip/ZipSlipVulnerabilityTest.php | 14 +-
tests/PhpZip/ZipTestCase.php | 77 +-
62 files changed, 5315 insertions(+), 2459 deletions(-)
create mode 100644 .php_cs
delete mode 100644 src/PhpZip/Exception/ZipNotFoundEntry.php
delete mode 100644 src/PhpZip/Exception/ZipUnsupportMethod.php
delete mode 100644 src/PhpZip/Util/encodings/cp866-utf8.php
create mode 100644 tests/PhpZip/Internal/DummyFileSystemStream.php
create mode 100644 tests/PhpZip/Internal/ZipFileExtended.php
create mode 100644 tests/PhpZip/Zip64Test.php
diff --git a/.php_cs b/.php_cs
new file mode 100644
index 0000000..976ecbf
--- /dev/null
+++ b/.php_cs
@@ -0,0 +1,1500 @@
+ true,
+
+ // Each element of an array must be indented exactly once.
+ 'array_indentation' => true,
+
+ // PHP arrays should be declared using the configured syntax.
+ 'array_syntax' => [
+ 'syntax' => 'short',
+ ],
+
+ /*
+ * Converts backtick operators to `shell_exec` calls.
+ *
+ * Conversion is done only when it is non risky, so when special
+ * chars like single-quotes, double-quotes and backticks are not
+ * used inside the command.
+ */
+ 'backtick_to_shell_exec' => true,
+
+ // Binary operators should be surrounded by space as configured.
+ 'binary_operator_spaces' => true,
+
+ // There MUST be one blank line after the namespace declaration.
+ 'blank_line_after_namespace' => true,
+
+ /*
+ * Ensure there is no code on the same line as the PHP open tag and
+ * it is followed by a blank line.
+ */
+ 'blank_line_after_opening_tag' => true,
+
+ // An empty line feed must precede any configured statement.
+ 'blank_line_before_statement' => [
+ 'statements' => [
+ 'continue',
+ 'declare',
+ 'return',
+ 'throw',
+ 'try',
+ 'case',
+ 'die',
+ 'exit',
+ 'do',
+ 'foreach',
+ 'goto',
+ 'if',
+ 'while',
+ ],
+ ],
+
+ /*
+ * The body of each structure MUST be enclosed by braces. Braces
+ * should be properly placed. Body of braces should be properly
+ * indented.
+ */
+ 'braces' => [
+ 'allow_single_line_closure' => true,
+ ],
+
+ // A single space or none should be between cast and variable.
+ 'cast_spaces' => true,
+
+ /*
+ * Class, trait and interface elements must be separated with one
+ * blank line.
+ */
+ 'class_attributes_separation' => true,
+
+ /*
+ * Whitespace around the keywords of a class, trait or interfaces
+ * definition should be one space.
+ */
+ 'class_definition' => [
+ 'single_item_single_line' => true,
+ ],
+
+ // Converts `::class` keywords to FQCN strings.
+ 'class_keyword_remove' => false,
+
+ // Using `isset($var) &&` multiple times should be done in one call.
+ 'combine_consecutive_issets' => true,
+
+ // Calling `unset` on multiple items should be done in one call.
+ 'combine_consecutive_unsets' => true,
+
+ /*
+ * Replace multiple nested calls of `dirname` by only one call with
+ * second `$level` parameter. Requires PHP >= 7.0.
+ *
+ * Risky!
+ * Risky when the function `dirname` is overridden.
+ */
+ 'combine_nested_dirname' => false,
+
+ /*
+ * Comments with annotation should be docblock when used on
+ * structural elements.
+ *
+ * Risky!
+ * Risky as new docblocks might mean more, e.g. a Doctrine entity
+ * might have a new column in database
+ */
+ 'comment_to_phpdoc' => [
+ 'ignored_tags' => [
+ 'noinspection',
+ ],
+ ],
+
+ /*
+ * Remove extra spaces in a nullable typehint.
+ *
+ * Rule is applied only in a PHP 7.1+ environment.
+ */
+ 'compact_nullable_typehint' => false,
+
+ // Concatenation should be spaced according configuration.
+ 'concat_space' => [
+ 'spacing' => 'one',
+ ],
+
+ /*
+ * The PHP constants `true`, `false`, and `null` MUST be written
+ * using the correct casing.
+ */
+ 'constant_case' => true,
+
+ /*
+ * Class `DateTimeImmutable` should be used instead of `DateTime`.
+ *
+ * Risky!
+ * Risky when the code relies on modifying `DateTime` objects or if
+ * any of the `date_create*` functions are overridden.
+ */
+ 'date_time_immutable' => true,
+
+ /*
+ * Equal sign in declare statement should be surrounded by spaces or
+ * not following configuration.
+ */
+ 'declare_equal_normalize' => true,
+
+ /*
+ * Force strict types declaration in all files. Requires PHP >= 7.0.
+ *
+ * Risky!
+ * Forcing strict types will stop non strict code from working.
+ */
+ 'declare_strict_types' => false,
+
+ /*
+ * Replaces `dirname(__FILE__)` expression with equivalent `__DIR__`
+ * constant.
+ *
+ * Risky!
+ * Risky when the function `dirname` is overridden.
+ */
+ 'dir_constant' => true,
+
+ /*
+ * Doctrine annotations must use configured operator for assignment
+ * in arrays.
+ */
+ 'doctrine_annotation_array_assignment' => true,
+
+ /*
+ * Doctrine annotations without arguments must use the configured
+ * syntax.
+ */
+ 'doctrine_annotation_braces' => true,
+
+ // Doctrine annotations must be indented with four spaces.
+ 'doctrine_annotation_indentation' => true,
+
+ /*
+ * Fixes spaces in Doctrine annotations.
+ *
+ * There must not be any space around parentheses; commas must be
+ * preceded by no space and followed by one space; there must be no
+ * space around named arguments assignment operator; there must be
+ * one space around array assignment operator.
+ */
+ 'doctrine_annotation_spaces' => true,
+
+ /*
+ * The keyword `elseif` should be used instead of `else if` so that
+ * all control keywords look like single words.
+ */
+ 'elseif' => true,
+
+ // PHP code MUST use only UTF-8 without BOM (remove BOM).
+ 'encoding' => true,
+
+ /*
+ * Replace deprecated `ereg` regular expression functions with
+ * `preg`.
+ *
+ * Risky!
+ * Risky if the `ereg` function is overridden.
+ */
+ 'ereg_to_preg' => true,
+
+ /*
+ * Error control operator should be added to deprecation notices
+ * and/or removed from other cases.
+ *
+ * Risky!
+ * Risky because adding/removing `@` might cause changes to code
+ * behaviour or if `trigger_error` function is overridden.
+ */
+ 'error_suppression' => [
+ 'mute_deprecation_error' => true,
+ 'noise_remaining_usages' => true,
+ 'noise_remaining_usages_exclude' => [
+ 'gzinflate',
+ 'fclose',
+ 'fopen',
+ 'mime_content_type',
+ 'rename',
+ 'unlink',
+ ],
+ ],
+
+ /*
+ * Escape implicit backslashes in strings and heredocs to ease the
+ * understanding of which are special chars interpreted by PHP and
+ * which not.
+ *
+ * In PHP double-quoted strings and heredocs some chars like `n`,
+ * `$` or `u` have special meanings if preceded by a backslash (and
+ * some are special only if followed by other special chars), while
+ * a backslash preceding other chars are interpreted like a plain
+ * backslash. The precise list of those special chars is hard to
+ * remember and to identify quickly: this fixer escapes backslashes
+ * that do not start a special interpretation with the char after
+ * them.
+ * It is possible to fix also single-quoted strings: in this case
+ * there is no special chars apart from single-quote and backslash
+ * itself, so the fixer simply ensure that all backslashes are
+ * escaped. Both single and double backslashes are allowed in
+ * single-quoted strings, so the purpose in this context is mainly
+ * to have a uniformed way to have them written all over the
+ * codebase.
+ */
+ 'escape_implicit_backslashes' => true,
+
+ /*
+ * Add curly braces to indirect variables to make them clear to
+ * understand. Requires PHP >= 7.0.
+ */
+ 'explicit_indirect_variable' => false,
+
+ /*
+ * Converts implicit variables into explicit ones in double-quoted
+ * strings or heredoc syntax.
+ *
+ * The reasoning behind this rule is the following:
+ * - When there are two valid ways of doing the same thing, using
+ * both is confusing, there should be a coding standard to follow
+ * - PHP manual marks `"$var"` syntax as implicit and `"${var}"`
+ * syntax as explicit: explicit code should always be preferred
+ * - Explicit syntax allows word concatenation inside strings, e.g.
+ * `"${var}IsAVar"`, implicit doesn't
+ * - Explicit syntax is easier to detect for IDE/editors and
+ * therefore has colors/hightlight with higher contrast, which is
+ * easier to read
+ * Backtick operator is skipped because it is harder to handle; you
+ * can use `backtick_to_shell_exec` fixer to normalize backticks to
+ * strings
+ */
+ 'explicit_string_variable' => true,
+
+ /*
+ * All classes must be final, except abstract ones and Doctrine
+ * entities.
+ *
+ * No exception and no configuration are intentional. Beside
+ * Doctrine entities and of course abstract classes, there is no
+ * single reason not to declare all classes final. If you want to
+ * subclass a class, mark the parent class as abstract and create
+ * two child classes, one empty if necessary: you'll gain much more
+ * fine grained type-hinting. If you need to mock a standalone
+ * class, create an interface, or maybe it's a value-object that
+ * shouldn't be mocked at all. If you need to extend a standalone
+ * class, create an interface and use the Composite pattern. If you
+ * aren't ready yet for serious OOP, go with
+ * FinalInternalClassFixer, it's fine.
+ *
+ * Risky!
+ * Risky when subclassing non-abstract classes.
+ */
+ 'final_class' => false,
+
+ /*
+ * Internal classes should be `final`.
+ *
+ * Risky!
+ * Changing classes to `final` might cause code execution to break.
+ */
+ 'final_internal_class' => false,
+
+ /*
+ * All `public` methods of `abstract` classes should be `final`.
+ *
+ * Enforce API encapsulation in an inheritance architecture. If you
+ * want to override a method, use the Template method pattern.
+ *
+ * Risky!
+ * Risky when overriding `public` methods of `abstract` classes
+ */
+ 'final_public_method_for_abstract_class' => false,
+
+ // Converts `static` access to `self` access in `final` classes.
+ 'final_static_access' => true,
+
+ /*
+ * Order the flags in `fopen` calls, `b` and `t` must be last.
+ *
+ * Risky!
+ * Risky when the function `fopen` is overridden.
+ */
+ 'fopen_flag_order' => true,
+
+ /*
+ * The flags in `fopen` calls must omit `t`, and `b` must be omitted
+ * or included consistently.
+ *
+ * Risky!
+ * Risky when the function `fopen` is overridden.
+ */
+ 'fopen_flags' => [
+ 'b_mode' => true,
+ ],
+
+ /*
+ * PHP code must use the long ` true,
+
+ /*
+ * Transforms imported FQCN parameters and return types in function
+ * arguments to short version.
+ */
+ 'fully_qualified_strict_types' => true,
+
+ // Spaces should be properly placed in a function declaration.
+ 'function_declaration' => true,
+
+ /*
+ * Replace core functions calls returning constants with the
+ * constants.
+ *
+ * Risky!
+ * Risky when any of the configured functions to replace are
+ * overridden.
+ */
+ 'function_to_constant' => [
+ 'functions' => [
+ 'get_class',
+ 'php_sapi_name',
+ 'phpversion',
+ 'pi',
+ 'get_called_class',
+ ],
+ ],
+
+ // Ensure single space between function's argument and its typehint.
+ 'function_typehint_space' => true,
+
+ // Configured annotations should be omitted from PHPDoc.
+ 'general_phpdoc_annotation_remove' => true,
+
+ // Imports or fully qualifies global classes/functions/constants.
+ 'global_namespace_import' => [
+ 'import_constants' => false,
+ 'import_functions' => false,
+ 'import_classes' => false,
+ ],
+
+ // Add, replace or remove header comment.
+ 'header_comment' => false,
+
+ /*
+ * Heredoc/nowdoc content must be properly indented. Requires PHP >=
+ * 7.3.
+ */
+ 'heredoc_indentation' => false,
+
+ // Convert `heredoc` to `nowdoc` where possible.
+ 'heredoc_to_nowdoc' => true,
+
+ /*
+ * Function `implode` must be called with 2 arguments in the
+ * documented order.
+ *
+ * Risky!
+ * Risky when the function `implode` is overridden.
+ */
+ 'implode_call' => true,
+
+ /*
+ * Include/Require and file path should be divided with a single
+ * space. File path should not be placed under brackets.
+ */
+ 'include' => true,
+
+ /*
+ * Pre- or post-increment and decrement operators should be used if
+ * possible.
+ */
+ 'increment_style' => false,
+
+ // Code MUST use configured indentation type.
+ 'indentation_type' => true,
+
+ /*
+ * Replaces `is_null($var)` expression with `null === $var`.
+ *
+ * Risky!
+ * Risky when the function `is_null` is overridden.
+ */
+ 'is_null' => true,
+
+ // All PHP files must use same line ending.
+ 'line_ending' => true,
+
+ // Ensure there is no code on the same line as the PHP open tag.
+ 'linebreak_after_opening_tag' => true,
+
+ /*
+ * List (`array` destructuring) assignment should be declared using
+ * the configured syntax. Requires PHP >= 7.1.
+ */
+ 'list_syntax' => false,
+
+ /*
+ * Use `&&` and `||` logical operators instead of `and` and `or`.
+ *
+ * Risky!
+ * Risky, because you must double-check if using and/or with lower
+ * precedence was intentional.
+ */
+ 'logical_operators' => true,
+
+ // Cast should be written in lower case.
+ 'lowercase_cast' => true,
+
+ // PHP keywords MUST be in lower case.
+ 'lowercase_keywords' => true,
+
+ /*
+ * Class static references `self`, `static` and `parent` MUST be in
+ * lower case.
+ */
+ 'lowercase_static_reference' => true,
+
+ // Magic constants should be referred to using the correct casing.
+ 'magic_constant_casing' => true,
+
+ /*
+ * Magic method definitions and calls must be using the correct
+ * casing.
+ */
+ 'magic_method_casing' => true,
+
+ /*
+ * Replace non multibyte-safe functions with corresponding mb
+ * function.
+ *
+ * Risky!
+ * Risky when any of the functions are overridden.
+ */
+ 'mb_str_functions' => false,
+
+ /*
+ * In method arguments and method call, there MUST NOT be a space
+ * before each comma and there MUST be one space after each comma.
+ * Argument lists MAY be split across multiple lines, where each
+ * subsequent line is indented once. When doing so, the first item
+ * in the list MUST be on the next line, and there MUST be only one
+ * argument per line.
+ */
+ 'method_argument_space' => [
+ 'on_multiline' => 'ensure_fully_multiline',
+ ],
+
+ /*
+ * Method chaining MUST be properly indented. Method chaining with
+ * different levels of indentation is not supported.
+ */
+ 'method_chaining_indentation' => true,
+
+ /*
+ * Replaces `intval`, `floatval`, `doubleval`, `strval` and
+ * `boolval` function calls with according type casting operator.
+ *
+ * Risky!
+ * Risky if any of the functions `intval`, `floatval`, `doubleval`,
+ * `strval` or `boolval` are overridden.
+ */
+ 'modernize_types_casting' => true,
+
+ /*
+ * DocBlocks must start with two asterisks, multiline comments must
+ * start with a single asterisk, after the opening slash. Both must
+ * end with a single asterisk before the closing slash.
+ */
+ 'multiline_comment_opening_closing' => true,
+
+ /*
+ * Forbid multi-line whitespace before the closing semicolon or move
+ * the semicolon to the new line for chained calls.
+ */
+ 'multiline_whitespace_before_semicolons' => [
+ 'strategy' => 'new_line_for_chained_calls',
+ ],
+
+ /*
+ * Add leading `\` before constant invocation of internal constant
+ * to speed up resolving. Constant name match is case-sensitive,
+ * except for `null`, `false` and `true`.
+ *
+ * Risky!
+ * Risky when any of the constants are namespaced or overridden.
+ */
+ 'native_constant_invocation' => true,
+
+ /*
+ * Function defined by PHP should be called using the correct
+ * casing.
+ */
+ 'native_function_casing' => true,
+
+ /*
+ * Add leading `\` before function invocation to speed up resolving.
+ *
+ * Risky!
+ * Risky when any of the functions are overridden.
+ */
+ 'native_function_invocation' => [
+ 'include' => [
+ '@compiler_optimized',
+ ],
+ 'scope' => 'namespaced',
+ 'strict' => true,
+ ],
+
+ // Native type hints for functions should use the correct case.
+ 'native_function_type_declaration_casing' => true,
+
+ /*
+ * All instances created with new keyword must be followed by
+ * braces.
+ */
+ 'new_with_braces' => true,
+
+ /*
+ * Master functions shall be used instead of aliases.
+ *
+ * Risky!
+ * Risky when any of the alias functions are overridden.
+ */
+ 'no_alias_functions' => [
+ 'sets' => [
+ '@all',
+ ],
+ ],
+
+ // Replace control structure alternative syntax to use braces.
+ 'no_alternative_syntax' => true,
+
+ // There should not be a binary flag before strings.
+ 'no_binary_string' => true,
+
+ // There should be no empty lines after class opening brace.
+ 'no_blank_lines_after_class_opening' => true,
+
+ /*
+ * There should not be blank lines between docblock and the
+ * documented element.
+ */
+ 'no_blank_lines_after_phpdoc' => true,
+
+ // There should be no blank lines before a namespace declaration.
+ 'no_blank_lines_before_namespace' => false,
+
+ /*
+ * There must be a comment when fall-through is intentional in a
+ * non-empty case body.
+ *
+ * Adds a "no break" comment before fall-through cases, and removes
+ * it if there is no fall-through.
+ */
+ 'no_break_comment' => [
+ 'comment_text' => 'no break',
+ ],
+
+ /*
+ * The closing `?>` tag MUST be omitted from files containing only
+ * PHP.
+ */
+ 'no_closing_tag' => true,
+
+ // There should not be any empty comments.
+ 'no_empty_comment' => true,
+
+ // There should not be empty PHPDoc blocks.
+ 'no_empty_phpdoc' => true,
+
+ // Remove useless semicolon statements.
+ 'no_empty_statement' => true,
+
+ /*
+ * Removes extra blank lines and/or blank lines following
+ * configuration.
+ */
+ 'no_extra_blank_lines' => [
+ 'tokens' => [
+ 'extra',
+ 'case',
+ 'continue',
+ 'default',
+ 'curly_brace_block',
+ 'parenthesis_brace_block',
+ 'return',
+ 'square_brace_block',
+ 'use',
+ 'throw',
+ 'use_trait',
+ 'useTrait',
+ 'switch',
+ ],
+ ],
+
+ /*
+ * Replace accidental usage of homoglyphs (non ascii characters) in
+ * names.
+ *
+ * Risky!
+ * Renames classes and cannot rename the files. You might have
+ * string references to renamed code (`$$name`).
+ */
+ 'no_homoglyph_names' => true,
+
+ // Remove leading slashes in `use` clauses.
+ 'no_leading_import_slash' => true,
+
+ /*
+ * The namespace declaration line shouldn't contain leading
+ * whitespace.
+ */
+ 'no_leading_namespace_whitespace' => true,
+
+ // Either language construct `print` or `echo` should be used.
+ 'no_mixed_echo_print' => true,
+
+ // Operator `=>` should not be surrounded by multi-line whitespaces.
+ 'no_multiline_whitespace_around_double_arrow' => true,
+
+ /*
+ * Properties MUST not be explicitly initialized with `null` except
+ * when they have a type declaration (PHP 7.4).
+ */
+ 'no_null_property_initialization' => true,
+
+ /*
+ * Convert PHP4-style constructors to `__construct`.
+ *
+ * Risky!
+ * Risky when old style constructor being fixed is overridden or
+ * overrides parent one.
+ */
+ 'no_php4_constructor' => true,
+
+ /*
+ * Short cast `bool` using double exclamation mark should not be
+ * used.
+ */
+ 'no_short_bool_cast' => true,
+
+ // Replace short-echo `=` with long format ` false,
+
+ // Single-line whitespace before closing semicolon are prohibited.
+ 'no_singleline_whitespace_before_semicolons' => true,
+
+ /*
+ * When making a method or function call, there MUST NOT be a space
+ * between the method or function name and the opening parenthesis.
+ */
+ 'no_spaces_after_function_name' => true,
+
+ // There MUST NOT be spaces around offset braces.
+ 'no_spaces_around_offset' => true,
+
+ /*
+ * There MUST NOT be a space after the opening parenthesis. There
+ * MUST NOT be a space before the closing parenthesis.
+ */
+ 'no_spaces_inside_parenthesis' => true,
+
+ // Replaces superfluous `elseif` with `if`.
+ 'no_superfluous_elseif' => true,
+
+ /*
+ * Removes `@param` and `@return` tags that don't provide any useful
+ * information.
+ */
+ 'no_superfluous_phpdoc_tags' => false,
+
+ // Remove trailing commas in list function calls.
+ 'no_trailing_comma_in_list_call' => true,
+
+ // PHP single-line arrays should not have trailing comma.
+ 'no_trailing_comma_in_singleline_array' => true,
+
+ // Remove trailing whitespace at the end of non-blank lines.
+ 'no_trailing_whitespace' => true,
+
+ // There MUST be no trailing spaces inside comment or PHPDoc.
+ 'no_trailing_whitespace_in_comment' => true,
+
+ // Removes unneeded parentheses around control statements.
+ 'no_unneeded_control_parentheses' => true,
+
+ /*
+ * Removes unneeded curly braces that are superfluous and aren't
+ * part of a control structure's body.
+ */
+ 'no_unneeded_curly_braces' => true,
+
+ // A final class must not have final methods.
+ 'no_unneeded_final_method' => true,
+
+ /*
+ * In function arguments there must not be arguments with default
+ * values before non-default ones.
+ *
+ * Risky!
+ * Modifies the signature of functions; therefore risky when using
+ * systems (such as some Symfony components) that rely on those (for
+ * example through reflection).
+ */
+ 'no_unreachable_default_argument_value' => false,
+
+ // Variables must be set `null` instead of using `(unset)` casting.
+ 'no_unset_cast' => true,
+
+ /*
+ * Properties should be set to `null` instead of using `unset`.
+ *
+ * Risky!
+ * Changing variables to `null` instead of unsetting them will mean
+ * they still show up when looping over class variables. With PHP
+ * 7.4, this rule might introduce `null` assignments to property
+ * whose type declaration does not allow it.
+ */
+ 'no_unset_on_property' => false,
+
+ // Unused `use` statements must be removed.
+ 'no_unused_imports' => true,
+
+ // There should not be useless `else` cases.
+ 'no_useless_else' => true,
+
+ /*
+ * There should not be an empty `return` statement at the end of a
+ * function.
+ */
+ 'no_useless_return' => true,
+
+ /*
+ * In array declaration, there MUST NOT be a whitespace before each
+ * comma.
+ */
+ 'no_whitespace_before_comma_in_array' => true,
+
+ // Remove trailing whitespace at the end of blank lines.
+ 'no_whitespace_in_blank_line' => true,
+
+ /*
+ * Remove Zero-width space (ZWSP), Non-breaking space (NBSP) and
+ * other invisible unicode symbols.
+ *
+ * Risky!
+ * Risky when strings contain intended invisible characters.
+ */
+ 'non_printable_character' => true,
+
+ // Array index should always be written by using square braces.
+ 'normalize_index_brace' => true,
+
+ /*
+ * Logical NOT operators (`!`) should have leading and trailing
+ * whitespaces.
+ */
+ 'not_operator_with_space' => false,
+
+ // Logical NOT operators (`!`) should have one trailing whitespace.
+ 'not_operator_with_successor_space' => false,
+
+ /*
+ * Adds or removes `?` before type declarations for parameters with
+ * a default `null` value.
+ *
+ * Rule is applied only in a PHP 7.1+ environment.
+ */
+ 'nullable_type_declaration_for_default_null_value' => false,
+
+ /*
+ * There should not be space before or after object
+ * `T_OBJECT_OPERATOR` `->`.
+ */
+ 'object_operator_without_whitespace' => true,
+
+ // Orders the elements of classes/interfaces/traits.
+ 'ordered_class_elements' => false,
+
+ // Ordering `use` statements.
+ 'ordered_imports' => [
+ 'sort_algorithm' => 'alpha',
+ 'imports_order' => [
+ 'class',
+ 'const',
+ 'function',
+ ],
+ ],
+
+ /*
+ * Orders the interfaces in an `implements` or `interface extends`
+ * clause.
+ *
+ * Risky!
+ * Risky for `implements` when specifying both an interface and its
+ * parent interface, because PHP doesn't break on `parent, child`
+ * but does on `child, parent`.
+ */
+ 'ordered_interfaces' => false,
+
+ /*
+ * PHPUnit assertion method calls like `->assertSame(true, $foo)`
+ * should be written with dedicated method like
+ * `->assertTrue($foo)`.
+ *
+ * Risky!
+ * Fixer could be risky if one is overriding PHPUnit's native
+ * methods.
+ */
+ 'php_unit_construct' => true,
+
+ /*
+ * PHPUnit assertions like `assertInternalType`, `assertFileExists`,
+ * should be used over `assertTrue`.
+ *
+ * Risky!
+ * Fixer could be risky if one is overriding PHPUnit's native
+ * methods.
+ */
+ 'php_unit_dedicate_assert' => [
+ 'target' => '3.5',
+ ],
+
+ /*
+ * PHPUnit assertions like `assertIsArray` should be used over
+ * `assertInternalType`.
+ *
+ * Risky!
+ * Risky when PHPUnit methods are overridden or when project has
+ * PHPUnit incompatibilities.
+ */
+ 'php_unit_dedicate_assert_internal_type' => false,
+
+ /*
+ * Usages of `->setExpectedException*` methods MUST be replaced by
+ * `->expectException*` methods.
+ *
+ * Risky!
+ * Risky when PHPUnit classes are overridden or not accessible, or
+ * when project has PHPUnit incompatibilities.
+ */
+ 'php_unit_expectation' => true,
+
+ // PHPUnit annotations should be a FQCNs including a root namespace.
+ 'php_unit_fqcn_annotation' => true,
+
+ // All PHPUnit test classes should be marked as internal.
+ 'php_unit_internal_class' => true,
+
+ /*
+ * Enforce camel (or snake) case for PHPUnit test methods, following
+ * configuration.
+ */
+ 'php_unit_method_casing' => true,
+
+ /*
+ * Usages of `->getMock` and
+ * `->getMockWithoutInvokingTheOriginalConstructor` methods MUST be
+ * replaced by `->createMock` or `->createPartialMock` methods.
+ *
+ * Risky!
+ * Risky when PHPUnit classes are overridden or not accessible, or
+ * when project has PHPUnit incompatibilities.
+ */
+ 'php_unit_mock' => false,
+
+ /*
+ * Usage of PHPUnit's mock e.g. `->will($this->returnValue(..))`
+ * must be replaced by its shorter equivalent such as
+ * `->willReturn(...)`.
+ *
+ * Risky!
+ * Risky when PHPUnit classes are overridden or not accessible, or
+ * when project has PHPUnit incompatibilities.
+ */
+ 'php_unit_mock_short_will_return' => false,
+
+ /*
+ * PHPUnit classes MUST be used in namespaced version, e.g.
+ * `\PHPUnit\Framework\TestCase` instead of
+ * `\PHPUnit_Framework_TestCase`.
+ *
+ * PHPUnit v6 has finally fully switched to namespaces.
+ * You could start preparing the upgrade by switching from
+ * non-namespaced TestCase to namespaced one.
+ * Forward compatibility layer (`\PHPUnit\Framework\TestCase` class)
+ * was backported to PHPUnit v4.8.35 and PHPUnit v5.4.0.
+ * Extended forward compatibility layer (`PHPUnit\Framework\Assert`,
+ * `PHPUnit\Framework\BaseTestListener`,
+ * `PHPUnit\Framework\TestListener` classes) was introduced in
+ * v5.7.0.
+ *
+ * Risky!
+ * Risky when PHPUnit classes are overridden or not accessible, or
+ * when project has PHPUnit incompatibilities.
+ */
+ 'php_unit_namespaced' => [
+ 'target' => '4.8',
+ ],
+
+ /*
+ * Usages of `@expectedException*` annotations MUST be replaced by
+ * `->setExpectedException*` methods.
+ *
+ * Risky!
+ * Risky when PHPUnit classes are overridden or not accessible, or
+ * when project has PHPUnit incompatibilities.
+ */
+ 'php_unit_no_expectation_annotation' => [
+ 'target' => 'newest',
+ ],
+
+ // Order `@covers` annotation of PHPUnit tests.
+ 'php_unit_ordered_covers' => true,
+
+ /*
+ * Changes the visibility of the `setUp()` and `tearDown()`
+ * functions of PHPUnit to `protected`, to match the PHPUnit
+ * TestCase.
+ *
+ * Risky!
+ * This fixer may change functions named `setUp()` or `tearDown()`
+ * outside of PHPUnit tests, when a class is wrongly seen as a
+ * PHPUnit test.
+ */
+ 'php_unit_set_up_tear_down_visibility' => true,
+
+ /*
+ * All PHPUnit test cases should have `@small`, `@medium` or
+ * `@large` annotation to enable run time limits.
+ *
+ * The special groups [small, medium, large] provides a way to
+ * identify tests that are taking long to be executed.
+ */
+ 'php_unit_size_class' => true,
+
+ /*
+ * PHPUnit methods like `assertSame` should be used instead of
+ * `assertEquals`.
+ *
+ * Risky!
+ * Risky when any of the functions are overridden or when testing
+ * object equality.
+ */
+ 'php_unit_strict' => false,
+
+ /*
+ * Adds or removes @test annotations from tests, following
+ * configuration.
+ *
+ * Risky!
+ * This fixer may change the name of your tests, and could cause
+ * incompatibility with abstract classes or interfaces.
+ */
+ 'php_unit_test_annotation' => true,
+
+ /*
+ * Calls to `PHPUnit\Framework\TestCase` static methods must all be
+ * of the same type, either `$this->`, `self::` or `static::`.
+ *
+ * Risky!
+ * Risky when PHPUnit methods are overridden or not accessible, or
+ * when project has PHPUnit incompatibilities.
+ */
+ 'php_unit_test_case_static_method_calls' => true,
+
+ /*
+ * Adds a default `@coversNothing` annotation to PHPUnit test
+ * classes that have no `@covers*` annotation.
+ */
+ 'php_unit_test_class_requires_covers' => true,
+
+ // PHPDoc should contain `@param` for all params.
+ 'phpdoc_add_missing_param_annotation' => [
+ 'only_untyped' => false,
+ ],
+
+ /*
+ * All items of the given phpdoc tags must be either left-aligned or
+ * (by default) aligned vertically.
+ */
+ 'phpdoc_align' => [
+ 'tags' => [
+ 'return',
+ 'throws',
+ 'type',
+ 'var',
+ 'property',
+ 'method',
+ 'param',
+ ],
+ 'align' => 'vertical',
+ ],
+
+ // PHPDoc annotation descriptions should not be a sentence.
+ 'phpdoc_annotation_without_dot' => true,
+
+ /*
+ * Docblocks should have the same indentation as the documented
+ * subject.
+ */
+ 'phpdoc_indent' => true,
+
+ // Fix PHPDoc inline tags, make `@inheritdoc` always inline.
+ 'phpdoc_inline_tag' => true,
+
+ /*
+ * Changes doc blocks from single to multi line, or reversed. Works
+ * for class constants, properties and methods only.
+ */
+ 'phpdoc_line_span' => [
+ 'const' => 'single',
+ 'property' => 'single',
+ 'method' => 'multi',
+ ],
+
+ // `@access` annotations should be omitted from PHPDoc.
+ 'phpdoc_no_access' => true,
+
+ // No alias PHPDoc tags should be used.
+ 'phpdoc_no_alias_tag' => true,
+
+ /*
+ * `@return void` and `@return null` annotations should be omitted
+ * from PHPDoc.
+ */
+ 'phpdoc_no_empty_return' => true,
+
+ /*
+ * `@package` and `@subpackage` annotations should be omitted from
+ * PHPDoc.
+ */
+ 'phpdoc_no_package' => true,
+
+ // Classy that does not inherit must not have `@inheritdoc` tags.
+ 'phpdoc_no_useless_inheritdoc' => true,
+
+ /*
+ * Annotations in PHPDoc should be ordered so that `@param`
+ * annotations come first, then `@throws` annotations, then
+ * `@return` annotations.
+ */
+ 'phpdoc_order' => true,
+
+ /*
+ * The type of `@return` annotations of methods returning a
+ * reference to itself must the configured one.
+ */
+ 'phpdoc_return_self_reference' => true,
+
+ /*
+ * Scalar types should always be written in the same form. `int` not
+ * `integer`, `bool` not `boolean`, `float` not `real` or `double`.
+ */
+ 'phpdoc_scalar' => true,
+
+ /*
+ * Annotations in PHPDoc should be grouped together so that
+ * annotations of the same type immediately follow each other, and
+ * annotations of a different type are separated by a single blank
+ * line.
+ */
+ 'phpdoc_separation' => true,
+
+ // Single line `@var` PHPDoc should have proper spacing.
+ 'phpdoc_single_line_var_spacing' => true,
+
+ /*
+ * PHPDoc summary should end in either a full stop, exclamation
+ * mark, or question mark.
+ */
+ 'phpdoc_summary' => true,
+
+ // Docblocks should only be used on structural elements.
+ 'phpdoc_to_comment' => false,
+
+ /*
+ * EXPERIMENTAL: Takes `@param` annotations of non-mixed types and
+ * adjusts accordingly the function signature. Requires PHP >= 7.0.
+ *
+ * Risky!
+ * [1] This rule is EXPERIMENTAL and is not covered with backward
+ * compatibility promise. [2] `@param` annotation is mandatory for
+ * the fixer to make changes, signatures of methods without it (no
+ * docblock, inheritdocs) will not be fixed. [3] Manual actions are
+ * required if inherited signatures are not properly documented.
+ */
+ 'phpdoc_to_param_type' => false,
+
+ /*
+ * EXPERIMENTAL: Takes `@return` annotation of non-mixed types and
+ * adjusts accordingly the function signature. Requires PHP >= 7.0.
+ *
+ * Risky!
+ * [1] This rule is EXPERIMENTAL and is not covered with backward
+ * compatibility promise. [2] `@return` annotation is mandatory for
+ * the fixer to make changes, signatures of methods without it (no
+ * docblock, inheritdocs) will not be fixed. [3] Manual actions are
+ * required if inherited signatures are not properly documented. [4]
+ * `@inheritdocs` support is under construction.
+ */
+ 'phpdoc_to_return_type' => false,
+
+ /*
+ * PHPDoc should start and end with content, excluding the very
+ * first and last line of the docblocks.
+ */
+ 'phpdoc_trim' => true,
+
+ /*
+ * Removes extra blank lines after summary and after description in
+ * PHPDoc.
+ */
+ 'phpdoc_trim_consecutive_blank_line_separation' => true,
+
+ // The correct case must be used for standard PHP types in PHPDoc.
+ 'phpdoc_types' => true,
+
+ // Sorts PHPDoc types.
+ 'phpdoc_types_order' => [
+ 'sort_algorithm' => 'none',
+ 'null_adjustment' => 'always_last',
+ ],
+
+ /*
+ * `@var` and `@type` annotations must have type and name in the
+ * correct order.
+ */
+ 'phpdoc_var_annotation_correct_order' => true,
+
+ /*
+ * `@var` and `@type` annotations should not contain the variable
+ * name.
+ */
+ 'phpdoc_var_without_name' => false,
+
+ /*
+ * Converts `pow` to the `**` operator.
+ *
+ * Risky!
+ * Risky when the function `pow` is overridden.
+ */
+ 'pow_to_exponentiation' => false,
+
+ /*
+ * Converts `protected` variables and methods to `private` where
+ * possible.
+ */
+ 'protected_to_private' => true,
+
+ /*
+ * Classes must be in a path that matches their namespace, be at
+ * least one namespace deep and the class name should match the file
+ * name.
+ *
+ * Risky!
+ * This fixer may change your class name, which will break the code
+ * that depends on the old name.
+ */
+ 'psr0' => false,
+
+ /*
+ * Class names should match the file name.
+ *
+ * Risky!
+ * This fixer may change your class name, which will break the code
+ * that depends on the old name.
+ */
+ 'psr4' => true,
+
+ /*
+ * Replaces `rand`, `srand`, `getrandmax` functions calls with their
+ * `mt_*` analogs.
+ *
+ * Risky!
+ * Risky when the configured functions are overridden.
+ */
+ 'random_api_migration' => [
+ 'replacements' => [
+ 'getrandmax' => 'mt_getrandmax',
+ 'rand' => 'mt_rand',
+ 'srand' => 'mt_srand',
+ ],
+ ],
+
+ /*
+ * Local, dynamic and directly referenced variables should not be
+ * assigned and directly returned by a function or method.
+ */
+ 'return_assignment' => true,
+
+ /*
+ * There should be one or no space before colon, and one space after
+ * it in return type declarations, according to configuration.
+ *
+ * Rule is applied only in a PHP 7+ environment.
+ */
+ 'return_type_declaration' => false,
+
+ /*
+ * Inside class or interface element `self` should be preferred to
+ * the class name itself.
+ *
+ * Risky!
+ * Risky when using dynamic calls like get_called_class() or late
+ * static binding.
+ */
+ 'self_accessor' => true,
+
+ /*
+ * Inside a `final` class or anonymous class `self` should be
+ * preferred to `static`.
+ */
+ 'self_static_accessor' => true,
+
+ // Instructions must be terminated with a semicolon.
+ 'semicolon_after_instruction' => true,
+
+ /*
+ * Cast shall be used, not `settype`.
+ *
+ * Risky!
+ * Risky when the `settype` function is overridden or when used as
+ * the 2nd or 3rd expression in a `for` loop .
+ */
+ 'set_type_to_cast' => true,
+
+ /*
+ * Cast `(boolean)` and `(integer)` should be written as `(bool)`
+ * and `(int)`, `(double)` and `(real)` as `(float)`, `(binary)` as
+ * `(string)`.
+ */
+ 'short_scalar_cast' => true,
+
+ /*
+ * Converts explicit variables in double-quoted strings and heredoc
+ * syntax from simple to complex format (`${` to `{$`).
+ *
+ * Doesn't touch implicit variables. Works together nicely with
+ * `explicit_string_variable`.
+ */
+ 'simple_to_complex_string_variable' => true,
+
+ /*
+ * A return statement wishing to return `void` should not return
+ * `null`.
+ */
+ 'simplified_null_return' => false,
+
+ /*
+ * A PHP file without end tag must always end with a single empty
+ * line feed.
+ */
+ 'single_blank_line_at_eof' => true,
+
+ /*
+ * There should be exactly one blank line before a namespace
+ * declaration.
+ */
+ 'single_blank_line_before_namespace' => true,
+
+ /*
+ * There MUST NOT be more than one property or constant declared per
+ * statement.
+ */
+ 'single_class_element_per_statement' => true,
+
+ // There MUST be one use keyword per declaration.
+ 'single_import_per_statement' => true,
+
+ /*
+ * Each namespace use MUST go on its own line and there MUST be one
+ * blank line after the use statements block.
+ */
+ 'single_line_after_imports' => true,
+
+ /*
+ * Single-line comments and multi-line comments with only one line
+ * of actual content should use the `//` syntax.
+ */
+ 'single_line_comment_style' => true,
+
+ // Throwing exception must be done in single line.
+ 'single_line_throw' => false,
+
+ // Convert double quotes to single quotes for simple strings.
+ 'single_quote' => [
+ 'strings_containing_single_quote_chars' => false,
+ ],
+
+ // Each trait `use` must be done as single statement.
+ 'single_trait_insert_per_statement' => true,
+
+ // Fix whitespace after a semicolon.
+ 'space_after_semicolon' => true,
+
+ // Increment and decrement operators should be used if possible.
+ 'standardize_increment' => true,
+
+ // Replace all `<>` with `!=`.
+ 'standardize_not_equals' => true,
+
+ /*
+ * Lambdas not (indirect) referencing `$this` must be declared
+ * `static`.
+ *
+ * Risky!
+ * Risky when using "->bindTo" on lambdas without referencing to
+ * `$this`.
+ */
+ 'static_lambda' => true,
+
+ /*
+ * Comparisons should be strict.
+ *
+ * Risky!
+ * Changing comparisons to strict might change code behavior.
+ */
+ 'strict_comparison' => false,
+
+ /*
+ * Functions should be used with `$strict` param set to `true`.
+ *
+ * The functions "array_keys", "array_search", "base64_decode",
+ * "in_array" and "mb_detect_encoding" should be used with $strict
+ * param.
+ *
+ * Risky!
+ * Risky when the fixed function is overridden or if the code relies
+ * on non-strict usage.
+ */
+ 'strict_param' => false,
+
+ /*
+ * All multi-line strings must use correct line ending.
+ *
+ * Risky!
+ * Changing the line endings of multi-line strings might affect
+ * string comparisons and outputs.
+ */
+ 'string_line_ending' => true,
+
+ // A case should be followed by a colon and not a semicolon.
+ 'switch_case_semicolon_to_colon' => true,
+
+ // Removes extra spaces between colon and case value.
+ 'switch_case_space' => true,
+
+ // Standardize spaces around ternary operator.
+ 'ternary_operator_spaces' => true,
+
+ /*
+ * Use `null` coalescing operator `??` where possible. Requires PHP
+ * >= 7.0.
+ */
+ 'ternary_to_null_coalescing' => false,
+
+ // PHP multi-line arrays should have a trailing comma.
+ 'trailing_comma_in_multiline_array' => true,
+
+ /*
+ * Arrays should be formatted like function/method arguments,
+ * without leading or trailing single line space.
+ */
+ 'trim_array_spaces' => true,
+
+ // Unary operators should be placed adjacent to their operands.
+ 'unary_operator_spaces' => true,
+
+ /*
+ * Visibility MUST be declared on all properties and methods;
+ * `abstract` and `final` MUST be declared before the visibility;
+ * `static` MUST be declared after the visibility.
+ */
+ 'visibility_required' => true,
+
+ /*
+ * Add `void` return type to functions with missing or empty return
+ * statements, but priority is given to `@return` annotations.
+ * Requires PHP >= 7.1.
+ *
+ * Risky!
+ * Modifies the signature of functions.
+ */
+ 'void_return' => false,
+
+ /*
+ * In array declaration, there MUST be a whitespace after each
+ * comma.
+ */
+ 'whitespace_after_comma_in_array' => true,
+
+ /*
+ * Write conditions in Yoda style (`true`), non-Yoda style (`false`)
+ * or ignore those conditions (`null`) based on configuration.
+ */
+ 'yoda_style' => [
+ 'equal' => false,
+ 'identical' => false,
+ 'less_and_greater' => false,
+ ],
+];
+
+if (\PHP_SAPI === 'cli' && !class_exists(\PhpCsFixer\Config::class)) {
+ $binFixer = __DIR__ . '/vendor/bin/php-cs-fixer';
+ if (!is_file($binFixer)) {
+ $binFixer = 'php-cs-fixer';
+ }
+ $dryRun = !\in_array('--force', $_SERVER['argv'], true);
+
+ $command = escapeshellarg($binFixer) . ' fix --config ' . escapeshellarg(__FILE__) . ' --diff-format udiff --ansi';
+ if ($dryRun) {
+ $command .= ' --dry-run';
+ }
+
+ system($command, $returnCode);
+
+ if ($dryRun || $returnCode === 8) {
+ fwrite(\STDOUT, "\n\e[1;40;93m\e[K\n");
+ fwrite(\STDOUT, " [DEBUG] Dry run php-cs-fixer config.\e[K\n");
+ fwrite(\STDOUT, " Only shows which files would have been modified.\e[K\n");
+ fwrite(\STDOUT, " To apply the rules, use the --force option:\e[K\n\e[K\n");
+ fwrite(\STDOUT, " \e[1;40;92mphp {$_SERVER['argv'][0]} --force\e[K\n\e[0m\n");
+ } elseif ($returnCode !== 0) {
+ fwrite(\STDERR, "\n\e[1;41;97m\e[K\n ERROR CODE: {$returnCode}\e[K\n\e[0m\n");
+ }
+
+ exit($returnCode);
+}
+
+return \PhpCsFixer\Config::create()
+ ->setUsingCache(true)
+ ->setCacheFile(__DIR__ . '/.php_cs.cache')
+ ->setRules($rules)
+ ->setRiskyAllowed(true)
+ ->setFinder(
+ \PhpCsFixer\Finder::create()
+ ->in(__DIR__)
+ )
+;
diff --git a/.travis.yml b/.travis.yml
index b2525a0..d8693db 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -6,6 +6,7 @@ php:
- '7.1'
- '7.2'
- '7.3'
+ - '7.4'
# cache vendor dirs
cache:
diff --git a/composer.json b/composer.json
index 8f3ca0a..b3658ab 100644
--- a/composer.json
+++ b/composer.json
@@ -21,8 +21,8 @@
}
],
"require": {
- "ext-zlib": "*",
"php": "^5.5 || ^7.0",
+ "ext-zlib": "*",
"psr/http-message": "^1.0"
},
"require-dev": {
@@ -45,5 +45,15 @@
"ext-bz2": "Needed to support BZIP2 compression",
"ext-fileinfo": "Needed to get mime-type file"
},
- "minimum-stability": "stable"
+ "minimum-stability": "stable",
+ "scripts": {
+ "php:fix": "php .php_cs --force",
+ "php:fix:debug": "php .php_cs"
+ },
+ "extra": {
+ "branch-alias": {
+ "dev-master": "3.1.x-dev",
+ "dev-develop": "3.2.x-dev"
+ }
+ }
}
diff --git a/src/PhpZip/Crypto/TraditionalPkwareEncryptionEngine.php b/src/PhpZip/Crypto/TraditionalPkwareEncryptionEngine.php
index 8a5978b..ff6d357 100644
--- a/src/PhpZip/Crypto/TraditionalPkwareEncryptionEngine.php
+++ b/src/PhpZip/Crypto/TraditionalPkwareEncryptionEngine.php
@@ -12,65 +12,287 @@ use PhpZip\Util\PackUtil;
* Traditional PKWARE Encryption Engine.
*
* @see https://pkware.cachefly.net/webdocs/casestudies/APPNOTE.TXT .ZIP File Format Specification
+ *
* @author Ne-Lexa alexey@nelexa.ru
* @license MIT
*/
class TraditionalPkwareEncryptionEngine implements ZipEncryptionEngine
{
- /**
- * Encryption header size
- */
+ /** Encryption header size */
const STD_DEC_HDR_SIZE = 12;
/**
- * Crc table
+ * Crc table.
*
* @var array
*/
private static $CRC_TABLE = [
- 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
- 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
- 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
- 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
- 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
- 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
- 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
- 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
- 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
- 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
- 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
- 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
- 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
- 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
- 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
- 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
- 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
- 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
- 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
- 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
- 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
- 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
- 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
- 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
- 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
- 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
- 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
- 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
- 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
- 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
- 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
- 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d,
+ 0x00000000,
+ 0x77073096,
+ 0xee0e612c,
+ 0x990951ba,
+ 0x076dc419,
+ 0x706af48f,
+ 0xe963a535,
+ 0x9e6495a3,
+ 0x0edb8832,
+ 0x79dcb8a4,
+ 0xe0d5e91e,
+ 0x97d2d988,
+ 0x09b64c2b,
+ 0x7eb17cbd,
+ 0xe7b82d07,
+ 0x90bf1d91,
+ 0x1db71064,
+ 0x6ab020f2,
+ 0xf3b97148,
+ 0x84be41de,
+ 0x1adad47d,
+ 0x6ddde4eb,
+ 0xf4d4b551,
+ 0x83d385c7,
+ 0x136c9856,
+ 0x646ba8c0,
+ 0xfd62f97a,
+ 0x8a65c9ec,
+ 0x14015c4f,
+ 0x63066cd9,
+ 0xfa0f3d63,
+ 0x8d080df5,
+ 0x3b6e20c8,
+ 0x4c69105e,
+ 0xd56041e4,
+ 0xa2677172,
+ 0x3c03e4d1,
+ 0x4b04d447,
+ 0xd20d85fd,
+ 0xa50ab56b,
+ 0x35b5a8fa,
+ 0x42b2986c,
+ 0xdbbbc9d6,
+ 0xacbcf940,
+ 0x32d86ce3,
+ 0x45df5c75,
+ 0xdcd60dcf,
+ 0xabd13d59,
+ 0x26d930ac,
+ 0x51de003a,
+ 0xc8d75180,
+ 0xbfd06116,
+ 0x21b4f4b5,
+ 0x56b3c423,
+ 0xcfba9599,
+ 0xb8bda50f,
+ 0x2802b89e,
+ 0x5f058808,
+ 0xc60cd9b2,
+ 0xb10be924,
+ 0x2f6f7c87,
+ 0x58684c11,
+ 0xc1611dab,
+ 0xb6662d3d,
+ 0x76dc4190,
+ 0x01db7106,
+ 0x98d220bc,
+ 0xefd5102a,
+ 0x71b18589,
+ 0x06b6b51f,
+ 0x9fbfe4a5,
+ 0xe8b8d433,
+ 0x7807c9a2,
+ 0x0f00f934,
+ 0x9609a88e,
+ 0xe10e9818,
+ 0x7f6a0dbb,
+ 0x086d3d2d,
+ 0x91646c97,
+ 0xe6635c01,
+ 0x6b6b51f4,
+ 0x1c6c6162,
+ 0x856530d8,
+ 0xf262004e,
+ 0x6c0695ed,
+ 0x1b01a57b,
+ 0x8208f4c1,
+ 0xf50fc457,
+ 0x65b0d9c6,
+ 0x12b7e950,
+ 0x8bbeb8ea,
+ 0xfcb9887c,
+ 0x62dd1ddf,
+ 0x15da2d49,
+ 0x8cd37cf3,
+ 0xfbd44c65,
+ 0x4db26158,
+ 0x3ab551ce,
+ 0xa3bc0074,
+ 0xd4bb30e2,
+ 0x4adfa541,
+ 0x3dd895d7,
+ 0xa4d1c46d,
+ 0xd3d6f4fb,
+ 0x4369e96a,
+ 0x346ed9fc,
+ 0xad678846,
+ 0xda60b8d0,
+ 0x44042d73,
+ 0x33031de5,
+ 0xaa0a4c5f,
+ 0xdd0d7cc9,
+ 0x5005713c,
+ 0x270241aa,
+ 0xbe0b1010,
+ 0xc90c2086,
+ 0x5768b525,
+ 0x206f85b3,
+ 0xb966d409,
+ 0xce61e49f,
+ 0x5edef90e,
+ 0x29d9c998,
+ 0xb0d09822,
+ 0xc7d7a8b4,
+ 0x59b33d17,
+ 0x2eb40d81,
+ 0xb7bd5c3b,
+ 0xc0ba6cad,
+ 0xedb88320,
+ 0x9abfb3b6,
+ 0x03b6e20c,
+ 0x74b1d29a,
+ 0xead54739,
+ 0x9dd277af,
+ 0x04db2615,
+ 0x73dc1683,
+ 0xe3630b12,
+ 0x94643b84,
+ 0x0d6d6a3e,
+ 0x7a6a5aa8,
+ 0xe40ecf0b,
+ 0x9309ff9d,
+ 0x0a00ae27,
+ 0x7d079eb1,
+ 0xf00f9344,
+ 0x8708a3d2,
+ 0x1e01f268,
+ 0x6906c2fe,
+ 0xf762575d,
+ 0x806567cb,
+ 0x196c3671,
+ 0x6e6b06e7,
+ 0xfed41b76,
+ 0x89d32be0,
+ 0x10da7a5a,
+ 0x67dd4acc,
+ 0xf9b9df6f,
+ 0x8ebeeff9,
+ 0x17b7be43,
+ 0x60b08ed5,
+ 0xd6d6a3e8,
+ 0xa1d1937e,
+ 0x38d8c2c4,
+ 0x4fdff252,
+ 0xd1bb67f1,
+ 0xa6bc5767,
+ 0x3fb506dd,
+ 0x48b2364b,
+ 0xd80d2bda,
+ 0xaf0a1b4c,
+ 0x36034af6,
+ 0x41047a60,
+ 0xdf60efc3,
+ 0xa867df55,
+ 0x316e8eef,
+ 0x4669be79,
+ 0xcb61b38c,
+ 0xbc66831a,
+ 0x256fd2a0,
+ 0x5268e236,
+ 0xcc0c7795,
+ 0xbb0b4703,
+ 0x220216b9,
+ 0x5505262f,
+ 0xc5ba3bbe,
+ 0xb2bd0b28,
+ 0x2bb45a92,
+ 0x5cb36a04,
+ 0xc2d7ffa7,
+ 0xb5d0cf31,
+ 0x2cd99e8b,
+ 0x5bdeae1d,
+ 0x9b64c2b0,
+ 0xec63f226,
+ 0x756aa39c,
+ 0x026d930a,
+ 0x9c0906a9,
+ 0xeb0e363f,
+ 0x72076785,
+ 0x05005713,
+ 0x95bf4a82,
+ 0xe2b87a14,
+ 0x7bb12bae,
+ 0x0cb61b38,
+ 0x92d28e9b,
+ 0xe5d5be0d,
+ 0x7cdcefb7,
+ 0x0bdbdf21,
+ 0x86d3d2d4,
+ 0xf1d4e242,
+ 0x68ddb3f8,
+ 0x1fda836e,
+ 0x81be16cd,
+ 0xf6b9265b,
+ 0x6fb077e1,
+ 0x18b74777,
+ 0x88085ae6,
+ 0xff0f6a70,
+ 0x66063bca,
+ 0x11010b5c,
+ 0x8f659eff,
+ 0xf862ae69,
+ 0x616bffd3,
+ 0x166ccf45,
+ 0xa00ae278,
+ 0xd70dd2ee,
+ 0x4e048354,
+ 0x3903b3c2,
+ 0xa7672661,
+ 0xd06016f7,
+ 0x4969474d,
+ 0x3e6e77db,
+ 0xaed16a4a,
+ 0xd9d65adc,
+ 0x40df0b66,
+ 0x37d83bf0,
+ 0xa9bcae53,
+ 0xdebb9ec5,
+ 0x47b2cf7f,
+ 0x30b5ffe9,
+ 0xbdbdf21c,
+ 0xcabac28a,
+ 0x53b39330,
+ 0x24b4a3a6,
+ 0xbad03605,
+ 0xcdd70693,
+ 0x54de5729,
+ 0x23d967bf,
+ 0xb3667a2e,
+ 0xc4614ab8,
+ 0x5d681b02,
+ 0x2a6f2b94,
+ 0xb40bbe37,
+ 0xc30c8ea1,
+ 0x5a05df1b,
+ 0x2d02ef8d,
];
/**
- * Encryption keys
+ * Encryption keys.
*
* @var array
*/
private $keys = [];
- /**
- * @var ZipEntry
- */
+
+ /** @var ZipEntry */
private $entry;
/**
@@ -84,7 +306,7 @@ class TraditionalPkwareEncryptionEngine implements ZipEncryptionEngine
}
/**
- * Initial keys
+ * Initial keys.
*
* @param string $password
*/
@@ -93,6 +315,7 @@ class TraditionalPkwareEncryptionEngine implements ZipEncryptionEngine
$this->keys[0] = 305419896;
$this->keys[1] = 591751049;
$this->keys[2] = 878082192;
+
foreach (unpack('C*', $password) as $b) {
$this->updateKeys($b);
}
@@ -105,17 +328,18 @@ class TraditionalPkwareEncryptionEngine implements ZipEncryptionEngine
*/
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[0] = $this->crc32($this->keys[0], $charAt);
+ $this->keys[1] += ($this->keys[0] & 0xff);
$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));
+ $this->keys[2] = PackUtil::toSignedInt32($this->crc32($this->keys[2], ($this->keys[1] >> 24) & 0xff));
}
/**
* Update crc.
*
* @param int $oldCrc
- * @param string $charAt
+ * @param int $charAt
+ *
* @return int
*/
private function crc32($oldCrc, $charAt)
@@ -125,8 +349,10 @@ class TraditionalPkwareEncryptionEngine implements ZipEncryptionEngine
/**
* @param string $content
- * @return string
+ *
* @throws ZipAuthenticationException
+ *
+ * @return string
*/
public function decrypt($content)
{
@@ -135,6 +361,7 @@ class TraditionalPkwareEncryptionEngine implements ZipEncryptionEngine
$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);
@@ -147,19 +374,24 @@ class TraditionalPkwareEncryptionEngine implements ZipEncryptionEngine
// compare against the CRC otherwise
$checkByte = ($this->entry->getCrc() >> 24) & 0xff;
}
+
if ($byte !== $checkByte) {
- throw new ZipAuthenticationException(sprintf(
- 'Invalid password for zip entry "%s"',
- $this->entry->getName()
- ));
+ throw new ZipAuthenticationException(
+ sprintf(
+ 'Invalid password for zip entry "%s"',
+ $this->entry->getName()
+ )
+ );
}
- $outputContent = "";
+ $outputContent = '';
+
foreach (unpack('C*', substr($content, self::STD_DEC_HDR_SIZE)) as $val) {
$val = ($val ^ $this->decryptByte()) & 0xff;
$this->updateKeys($val);
$outputContent .= pack('c', $val);
}
+
return $outputContent;
}
@@ -171,15 +403,18 @@ class TraditionalPkwareEncryptionEngine implements ZipEncryptionEngine
private function decryptByte()
{
$temp = $this->keys[2] | 2;
+
return (($temp * ($temp ^ 1)) >> 8) & 0xffffff;
}
/**
- * Encryption data
+ * Encryption data.
*
* @param string $data
- * @return string
+ *
* @throws ZipCryptoException
+ *
+ * @return string
*/
public function encrypt($data)
{
@@ -196,13 +431,16 @@ class TraditionalPkwareEncryptionEngine implements ZipEncryptionEngine
$headerBytes[self::STD_DEC_HDR_SIZE - 2] = pack('c', ($crc >> 16) & 0xff);
$headerBytes = $this->encryptData($headerBytes);
+
return $headerBytes . $this->encryptData($data);
}
/**
* @param string $content
- * @return string
+ *
* @throws ZipCryptoException
+ *
+ * @return string
*/
private function encryptData($content)
{
@@ -210,20 +448,24 @@ class TraditionalPkwareEncryptionEngine implements ZipEncryptionEngine
throw new ZipCryptoException('content is null');
}
$buff = '';
+
foreach (unpack('C*', $content) as $val) {
$buff .= pack('c', $this->encryptByte($val));
}
+
return $buff;
}
/**
* @param int $byte
+ *
* @return int
*/
private function encryptByte($byte)
{
$tempVal = $byte ^ $this->decryptByte() & 0xff;
$this->updateKeys($byte);
+
return $tempVal;
}
}
diff --git a/src/PhpZip/Crypto/WinZipAesEngine.php b/src/PhpZip/Crypto/WinZipAesEngine.php
index 5bdd7a7..6c4b4de 100644
--- a/src/PhpZip/Crypto/WinZipAesEngine.php
+++ b/src/PhpZip/Crypto/WinZipAesEngine.php
@@ -14,6 +14,7 @@ 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
*/
@@ -24,18 +25,18 @@ class WinZipAesEngine implements ZipEncryptionEngine
* in bits (AES_BLOCK_SIZE_BITS).
*/
const AES_BLOCK_SIZE_BITS = 128;
+
const PWD_VERIFIER_BITS = 16;
- /**
- * The iteration count for the derived keys of the cipher, KLAC and MAC.
- */
+
+ /** The iteration count for the derived keys of the cipher, KLAC and MAC. */
const ITERATION_COUNT = 1000;
- /**
- * @var ZipEntry
- */
+
+ /** @var ZipEntry */
private $entry;
/**
* WinZipAesEngine constructor.
+ *
* @param ZipEntry $entry
*/
public function __construct(ZipEntry $entry)
@@ -47,17 +48,19 @@ class WinZipAesEngine implements ZipEncryptionEngine
* Decrypt from stream resource.
*
* @param string $content Input stream buffer
- * @return string
+ *
* @throws ZipAuthenticationException
* @throws ZipCryptoException
- * @throws \PhpZip\Exception\ZipException
+ * @throws ZipException
+ *
+ * @return string
*/
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)");
+ throw new ZipCryptoException($this->entry->getName() . ' (missing extra field for WinZip AES entry)');
}
/**
@@ -78,32 +81,37 @@ class WinZipAesEngine implements ZipEncryptionEngine
// Init start, end and size of encrypted data.
$start = $pos;
- $endPos = strlen($content);
+ $endPos = \strlen($content);
$footerSize = $sha1Size / 2;
$end = $endPos - $footerSize;
$size = $end - $start;
- if (0 > $size) {
- throw new ZipCryptoException($this->entry->getName() . " (false positive WinZip AES entry is too short)");
+ if ($size < 0) {
+ throw new ZipCryptoException($this->entry->getName() . ' (false positive WinZip AES entry is too short)');
}
// Load authentication code.
$authenticationCode = substr($content, $end, $footerSize);
+
if ($end + $footerSize !== $endPos) {
// This should never happen unless someone is writing to the
// end of the file concurrently!
- throw new ZipCryptoException("Expected end of file after WinZip AES authentication code!");
+ throw new ZipCryptoException('Expected end of file after WinZip AES authentication code!');
}
$password = $this->entry->getPassword();
- assert($password !== null);
- assert(self::AES_BLOCK_SIZE_BITS <= $keyStrengthBits);
+ \assert($password !== null);
+ \assert($keyStrengthBits >= self::AES_BLOCK_SIZE_BITS);
- // WinZip 99-character limit
- // @see https://sourceforge.net/p/p7zip/discussion/383044/thread/c859a2f0/
+ /**
+ * WinZip 99-character limit.
+ *
+ * @see https://sourceforge.net/p/p7zip/discussion/383044/thread/c859a2f0/
+ */
$password = substr($password, 0, 99);
$ctrIvSize = self::AES_BLOCK_SIZE_BITS / 8;
- $iv = str_repeat(chr(0), $ctrIvSize);
+ $iv = str_repeat(\chr(0), $ctrIvSize);
+
do {
// Here comes the strange part about WinZip AES encryption:
// Its unorthodox use of the Password-Based Key Derivation
@@ -111,7 +119,7 @@ class WinZipAesEngine implements ZipEncryptionEngine
// Yes, the password verifier is only a 16 bit value.
// So we must use the MAC for password verification, too.
$keyParam = hash_pbkdf2(
- "sha1",
+ 'sha1',
$password,
$salt,
self::ITERATION_COUNT,
@@ -126,9 +134,11 @@ class WinZipAesEngine implements ZipEncryptionEngine
$content = substr($content, $start, $size);
$mac = hash_hmac('sha1', $content, $sha1MacParam, true);
- if (substr($mac, 0, 10) !== $authenticationCode) {
- throw new ZipAuthenticationException($this->entry->getName() .
- " (authenticated WinZip AES entry content has been tampered with)");
+ if (strpos($mac, $authenticationCode) !== 0) {
+ throw new ZipAuthenticationException(
+ $this->entry->getName() .
+ ' (authenticated WinZip AES entry content has been tampered with)'
+ );
}
return self::aesCtrSegmentIntegerCounter($content, $key, $iv, false);
@@ -137,25 +147,27 @@ class WinZipAesEngine implements ZipEncryptionEngine
/**
* Decryption or encryption AES-CTR with Segment Integer Count (SIC).
*
- * @param string $str Data
- * @param string $key Key
- * @param string $iv IV
- * @param bool $encrypted If true encryption else decryption
+ * @param string $str Data
+ * @param string $key Key
+ * @param string $iv IV
+ * @param bool $encrypted If true encryption else decryption
+ *
* @return string
*/
private static function aesCtrSegmentIntegerCounter($str, $key, $iv, $encrypted = true)
{
- $numOfBlocks = ceil(strlen($str) / 16);
+ $numOfBlocks = ceil(\strlen($str) / 16);
$ctrStr = '';
for ($i = 0; $i < $numOfBlocks; ++$i) {
for ($j = 0; $j < 16; ++$j) {
- $n = ord($iv[$j]);
+ $n = \ord($iv[$j]);
+
if (++$n === 0x100) {
// overflow, set this one to 0, increment next
- $iv[$j] = chr(0);
+ $iv[$j] = \chr(0);
} else {
// no overflow, just write incremented number back and abort
- $iv[$j] = chr($n);
+ $iv[$j] = \chr($n);
break;
}
}
@@ -164,6 +176,7 @@ class WinZipAesEngine implements ZipEncryptionEngine
self::encryptCtr($data, $key, $iv) :
self::decryptCtr($data, $key, $iv);
}
+
return $ctrStr;
}
@@ -171,78 +184,97 @@ class WinZipAesEngine implements ZipEncryptionEngine
* Encrypt AES-CTR.
*
* @param string $data Raw data
- * @param string $key Aes key
- * @param string $iv Aes IV
+ * @param string $key Aes key
+ * @param string $iv Aes IV
+ *
* @return string Encrypted data
*/
private static function encryptCtr($data, $key, $iv)
{
- if (extension_loaded("openssl")) {
- $numBits = strlen($key) * 8;
+ if (\extension_loaded('openssl')) {
+ $numBits = \strlen($key) * 8;
/** @noinspection PhpComposerExtensionStubsInspection */
- return openssl_encrypt($data, 'AES-' . $numBits . '-CTR', $key, OPENSSL_RAW_DATA, $iv);
- } elseif (extension_loaded("mcrypt")) {
- /** @noinspection PhpDeprecationInspection */
- /** @noinspection PhpComposerExtensionStubsInspection */
- return mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $data, "ctr", $iv);
- } else {
- throw new RuntimeException('Extension openssl or mcrypt not loaded');
+ return openssl_encrypt($data, 'AES-' . $numBits . '-CTR', $key, \OPENSSL_RAW_DATA, $iv);
}
+
+ if (\extension_loaded('mcrypt')) {
+ /** @noinspection PhpComposerExtensionStubsInspection */
+ return mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $data, 'ctr', $iv);
+ }
+
+ throw new RuntimeException('Extension openssl or mcrypt not loaded');
}
/**
* Decrypt AES-CTR.
*
* @param string $data Encrypted data
- * @param string $key Aes key
- * @param string $iv Aes IV
+ * @param string $key Aes key
+ * @param string $iv Aes IV
+ *
* @return string Raw data
*/
private static function decryptCtr($data, $key, $iv)
{
- if (extension_loaded("openssl")) {
- $numBits = strlen($key) * 8;
+ if (\extension_loaded('openssl')) {
+ $numBits = \strlen($key) * 8;
/** @noinspection PhpComposerExtensionStubsInspection */
- return openssl_decrypt($data, 'AES-' . $numBits . '-CTR', $key, OPENSSL_RAW_DATA, $iv);
- } elseif (extension_loaded("mcrypt")) {
- /** @noinspection PhpDeprecationInspection */
- /** @noinspection PhpComposerExtensionStubsInspection */
- return mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $key, $data, "ctr", $iv);
- } else {
- throw new RuntimeException('Extension openssl or mcrypt not loaded');
+ return openssl_decrypt($data, 'AES-' . $numBits . '-CTR', $key, \OPENSSL_RAW_DATA, $iv);
}
+
+ if (\extension_loaded('mcrypt')) {
+ /** @noinspection PhpComposerExtensionStubsInspection */
+ return mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $key, $data, 'ctr', $iv);
+ }
+
+ throw new RuntimeException('Extension openssl or mcrypt not loaded');
}
/**
* Encryption string.
*
* @param string $content
+ *
+ * @throws ZipException
+ *
* @return string
- * @throws \PhpZip\Exception\ZipException
*/
public function encrypt($content)
{
// Init key strength.
$password = $this->entry->getPassword();
+
if ($password === null) {
- throw new ZipException('No password was set for the entry "'.$this->entry->getName().'"');
+ throw new ZipException('No password was set for the entry "' . $this->entry->getName() . '"');
}
- // WinZip 99-character limit
- // @see https://sourceforge.net/p/p7zip/discussion/383044/thread/c859a2f0/
+ /**
+ * WinZip 99-character limit.
+ *
+ * @see https://sourceforge.net/p/p7zip/discussion/383044/thread/c859a2f0/
+ */
$password = substr($password, 0, 99);
- $keyStrengthBits = WinZipAesEntryExtraField::getKeyStrangeFromEncryptionMethod($this->entry->getEncryptionMethod());
+ $keyStrengthBits = WinZipAesEntryExtraField::getKeyStrangeFromEncryptionMethod(
+ $this->entry->getEncryptionMethod()
+ );
$keyStrengthBytes = $keyStrengthBits / 8;
$salt = CryptoUtil::randomBytes($keyStrengthBytes / 2);
- $keyParam = hash_pbkdf2("sha1", $password, $salt, self::ITERATION_COUNT, (2 * $keyStrengthBits + self::PWD_VERIFIER_BITS) / 8, true);
+ $keyParam = hash_pbkdf2(
+ 'sha1',
+ $password,
+ $salt,
+ self::ITERATION_COUNT,
+ (2 * $keyStrengthBits + self::PWD_VERIFIER_BITS) / 8,
+ true
+ );
$sha1HMacParam = substr($keyParam, $keyStrengthBytes, $keyStrengthBytes);
// Can you believe they "forgot" the nonce in the CTR mode IV?! :-(
$ctrIvSize = self::AES_BLOCK_SIZE_BITS / 8;
- $iv = str_repeat(chr(0), $ctrIvSize);
+ $iv = str_repeat(\chr(0), $ctrIvSize);
$key = substr($keyParam, 0, $keyStrengthBytes);
@@ -250,10 +282,9 @@ class WinZipAesEngine implements ZipEncryptionEngine
$mac = hash_hmac('sha1', $content, $sha1HMacParam, true);
- return ($salt .
+ return $salt .
substr($keyParam, 2 * $keyStrengthBytes, self::PWD_VERIFIER_BITS / 8) .
$content .
- substr($mac, 0, 10)
- );
+ substr($mac, 0, 10);
}
}
diff --git a/src/PhpZip/Crypto/ZipEncryptionEngine.php b/src/PhpZip/Crypto/ZipEncryptionEngine.php
index 3187969..55dbe10 100644
--- a/src/PhpZip/Crypto/ZipEncryptionEngine.php
+++ b/src/PhpZip/Crypto/ZipEncryptionEngine.php
@@ -5,9 +5,10 @@ namespace PhpZip\Crypto;
use PhpZip\Exception\ZipAuthenticationException;
/**
- * Encryption Engine
+ * Encryption Engine.
*
* @see https://pkware.cachefly.net/webdocs/casestudies/APPNOTE.TXT .ZIP File Format Specification
+ *
* @author Ne-Lexa alexey@nelexa.ru
* @license MIT
*/
@@ -17,8 +18,10 @@ interface ZipEncryptionEngine
* Decryption string.
*
* @param string $encryptionContent
- * @return string
+ *
* @throws ZipAuthenticationException
+ *
+ * @return string
*/
public function decrypt($encryptionContent);
@@ -26,6 +29,7 @@ interface ZipEncryptionEngine
* Encryption string.
*
* @param string $content
+ *
* @return string
*/
public function encrypt($content);
diff --git a/src/PhpZip/Exception/Crc32Exception.php b/src/PhpZip/Exception/Crc32Exception.php
index b0ec2d0..04feb19 100644
--- a/src/PhpZip/Exception/Crc32Exception.php
+++ b/src/PhpZip/Exception/Crc32Exception.php
@@ -32,20 +32,19 @@ class Crc32Exception extends ZipException
* Crc32Exception constructor.
*
* @param string $name
- * @param int $expected
- * @param int $actual
+ * @param int $expected
+ * @param int $actual
*/
public function __construct($name, $expected, $actual)
{
parent::__construct(
sprintf(
- "%s (expected CRC32 value 0x%x, but is actually 0x%x)",
+ '%s (expected CRC32 value 0x%x, but is actually 0x%x)',
$name,
$expected,
$actual
)
);
- assert($expected != $actual);
$this->expectedCrc = $expected;
$this->actualCrc = $actual;
}
diff --git a/src/PhpZip/Exception/ZipEntryNotFoundException.php b/src/PhpZip/Exception/ZipEntryNotFoundException.php
index e8cdbae..7524cf7 100644
--- a/src/PhpZip/Exception/ZipEntryNotFoundException.php
+++ b/src/PhpZip/Exception/ZipEntryNotFoundException.php
@@ -10,21 +10,22 @@ namespace PhpZip\Exception;
*/
class ZipEntryNotFoundException extends ZipException
{
- /**
- * @var string
- */
+ /** @var string */
private $entryName;
/**
* ZipEntryNotFoundException constructor.
+ *
* @param string $entryName
*/
public function __construct($entryName)
{
- parent::__construct(sprintf(
- "Zip Entry \"%s\" was not found in the archive.",
- $entryName
- ));
+ parent::__construct(
+ sprintf(
+ 'Zip Entry "%s" was not found in the archive.',
+ $entryName
+ )
+ );
$this->entryName = $entryName;
}
diff --git a/src/PhpZip/Exception/ZipException.php b/src/PhpZip/Exception/ZipException.php
index bd123f8..e59ec60 100644
--- a/src/PhpZip/Exception/ZipException.php
+++ b/src/PhpZip/Exception/ZipException.php
@@ -7,6 +7,7 @@ namespace PhpZip\Exception;
*
* @author Ne-Lexa alexey@nelexa.ru
* @license MIT
+ *
* @see \Exception
*/
class ZipException extends \Exception
diff --git a/src/PhpZip/Exception/ZipNotFoundEntry.php b/src/PhpZip/Exception/ZipNotFoundEntry.php
deleted file mode 100644
index ffc3064..0000000
--- a/src/PhpZip/Exception/ZipNotFoundEntry.php
+++ /dev/null
@@ -1,14 +0,0 @@
-collection);
+ return \count($this->collection);
}
/**
* Returns the Extra Field with the given Header ID or null
* if no such Extra Field exists.
*
- * @param int $headerId The requested Header ID.
- * @return ExtraField The Extra Field with the given Header ID or
- * if no such Extra Field exists.
- * @throws ZipException If headerId is out of range.
+ * @param int $headerId the requested Header ID
+ *
+ * @throws ZipException if headerId is out of range
+ *
+ * @return ExtraField|null the Extra Field with the given Header ID or
+ * if no such Extra Field exists
*/
public function get($headerId)
{
- if (0x0000 > $headerId || $headerId > 0xffff) {
+ if ($headerId < 0x0000 || $headerId > 0xffff) {
throw new ZipException('headerId out of range');
}
+
if (isset($this->collection[$headerId])) {
return $this->collection[$headerId];
}
+
return null;
}
/**
* Stores the given Extra Field in this collection.
*
- * @param ExtraField $extraField The Extra Field to store in this collection.
- * @return ExtraField The Extra Field previously associated with the Header ID of
- * of the given Extra Field or null if no such Extra Field existed.
- * @throws ZipException If headerId is out of range.
+ * @param ExtraField $extraField the Extra Field to store in this collection
+ *
+ * @throws ZipException if headerId is out of range
+ *
+ * @return ExtraField the Extra Field previously associated with the Header ID of
+ * of the given Extra Field or null if no such Extra Field existed
*/
public function add(ExtraField $extraField)
{
$headerId = $extraField::getHeaderId();
- if (0x0000 > $headerId || $headerId > 0xffff) {
+
+ if ($headerId < 0x0000 || $headerId > 0xffff) {
throw new ZipException('headerId out of range');
}
$this->collection[$headerId] = $extraField;
+
return $extraField;
}
/**
- * Returns Extra Field exists
+ * Returns Extra Field exists.
+ *
+ * @param int $headerId the requested Header ID
*
- * @param int $headerId The requested Header ID.
* @return bool
*/
public function has($headerId)
@@ -86,34 +95,43 @@ class ExtraFieldsCollection implements \Countable, \ArrayAccess, \Iterator
/**
* Removes the Extra Field with the given Header ID.
*
- * @param int $headerId The requested Header ID.
- * @return ExtraField The Extra Field with the given Header ID or null
- * if no such Extra Field exists.
- * @throws ZipException If headerId is out of range or extra field not found.
+ * @param int $headerId the requested Header ID
+ *
+ * @throws ZipException if headerId is out of range or extra field not found
+ *
+ * @return ExtraField the Extra Field with the given Header ID or null
+ * if no such Extra Field exists
*/
public function remove($headerId)
{
- if (0x0000 > $headerId || $headerId > 0xffff) {
+ if ($headerId < 0x0000 || $headerId > 0xffff) {
throw new ZipException('headerId out of range');
}
+
if (isset($this->collection[$headerId])) {
$ef = $this->collection[$headerId];
unset($this->collection[$headerId]);
+
return $ef;
}
+
throw new ZipException('ExtraField not found');
}
/**
- * Whether a offset exists
- * @link http://php.net/manual/en/arrayaccess.offsetexists.php
+ * Whether a offset exists.
+ *
+ * @see http://php.net/manual/en/arrayaccess.offsetexists.php
+ *
* @param mixed $offset
- * An offset to check for.
- *
- * @return boolean true on success or false on failure.
- *
- *
- * The return value will be casted to boolean if non-boolean was returned.
+ * An offset to check for.
+ *
+ *
+ * @return bool true on success or false on failure.
+ *
+ *
+ * The return value will be casted to boolean if non-boolean was returned.
+ *
* @since 5.0.0
*/
public function offsetExists($offset)
@@ -122,14 +140,19 @@ class ExtraFieldsCollection implements \Countable, \ArrayAccess, \Iterator
}
/**
- * Offset to retrieve
- * @link http://php.net/manual/en/arrayaccess.offsetget.php
+ * Offset to retrieve.
+ *
+ * @see http://php.net/manual/en/arrayaccess.offsetget.php
+ *
* @param mixed $offset
- * The offset to retrieve.
- *
- * @return mixed Can return all value types.
- * @since 5.0.0
+ * The offset to retrieve.
+ *
+ *
* @throws ZipException
+ *
+ * @return mixed can return all value types
+ *
+ * @since 5.0.0
*/
public function offsetGet($offset)
{
@@ -137,23 +160,26 @@ class ExtraFieldsCollection implements \Countable, \ArrayAccess, \Iterator
}
/**
- * Offset to set
- * @link http://php.net/manual/en/arrayaccess.offsetset.php
+ * Offset to set.
+ *
+ * @see http://php.net/manual/en/arrayaccess.offsetset.php
+ *
* @param mixed $offset
- * The offset to assign the value to.
- *
- * @param mixed $value
- * The value to set.
- *
- * @return void
+ * The offset to assign the value to.
+ *
+ * @param mixed $value
+ * The value to set.
+ *
+ *
* @throws ZipException
+ *
* @since 5.0.0
*/
public function offsetSet($offset, $value)
{
if ($value instanceof ExtraField) {
if ($offset !== $value::getHeaderId()) {
- throw new InvalidArgumentException("Value header id !== array access key");
+ throw new InvalidArgumentException('Value header id !== array access key');
}
$this->add($value);
} else {
@@ -162,13 +188,16 @@ class ExtraFieldsCollection implements \Countable, \ArrayAccess, \Iterator
}
/**
- * Offset to unset
- * @link http://php.net/manual/en/arrayaccess.offsetunset.php
+ * Offset to unset.
+ *
+ * @see http://php.net/manual/en/arrayaccess.offsetunset.php
+ *
* @param mixed $offset
- * The offset to unset.
- *
- * @return void
+ * The offset to unset.
+ *
+ *
* @since 5.0.0
+ *
* @throws ZipException
*/
public function offsetUnset($offset)
@@ -177,9 +206,12 @@ class ExtraFieldsCollection implements \Countable, \ArrayAccess, \Iterator
}
/**
- * Return the current element
- * @link http://php.net/manual/en/iterator.current.php
- * @return mixed Can return any type.
+ * Return the current element.
+ *
+ * @see http://php.net/manual/en/iterator.current.php
+ *
+ * @return mixed can return any type
+ *
* @since 5.0.0
*/
public function current()
@@ -188,9 +220,9 @@ class ExtraFieldsCollection implements \Countable, \ArrayAccess, \Iterator
}
/**
- * Move forward to next element
- * @link http://php.net/manual/en/iterator.next.php
- * @return void Any returned value is ignored.
+ * Move forward to next element.
+ *
+ * @see http://php.net/manual/en/iterator.next.php
* @since 5.0.0
*/
public function next()
@@ -199,9 +231,12 @@ class ExtraFieldsCollection implements \Countable, \ArrayAccess, \Iterator
}
/**
- * Return the key of the current element
- * @link http://php.net/manual/en/iterator.key.php
- * @return mixed scalar on success, or null on failure.
+ * Return the key of the current element.
+ *
+ * @see http://php.net/manual/en/iterator.key.php
+ *
+ * @return mixed scalar on success, or null on failure
+ *
* @since 5.0.0
*/
public function key()
@@ -210,10 +245,13 @@ class ExtraFieldsCollection implements \Countable, \ArrayAccess, \Iterator
}
/**
- * Checks if current position is valid
- * @link http://php.net/manual/en/iterator.valid.php
- * @return boolean The return value will be casted to boolean and then evaluated.
- * Returns true on success or false on failure.
+ * Checks if current position is valid.
+ *
+ * @see http://php.net/manual/en/iterator.valid.php
+ *
+ * @return bool The return value will be casted to boolean and then evaluated.
+ * Returns true on success or false on failure.
+ *
* @since 5.0.0
*/
public function valid()
@@ -222,9 +260,9 @@ class ExtraFieldsCollection implements \Countable, \ArrayAccess, \Iterator
}
/**
- * Rewind the Iterator to the first element
- * @link http://php.net/manual/en/iterator.rewind.php
- * @return void Any returned value is ignored.
+ * Rewind the Iterator to the first element.
+ *
+ * @see http://php.net/manual/en/iterator.rewind.php
* @since 5.0.0
*/
public function rewind()
diff --git a/src/PhpZip/Extra/ExtraFieldsFactory.php b/src/PhpZip/Extra/ExtraFieldsFactory.php
index 4d6e3c9..08c0648 100644
--- a/src/PhpZip/Extra/ExtraFieldsFactory.php
+++ b/src/PhpZip/Extra/ExtraFieldsFactory.php
@@ -13,16 +13,14 @@ use PhpZip\Model\ZipEntry;
use PhpZip\Util\StringUtil;
/**
- * Extra Fields Factory
+ * Extra Fields Factory.
*
* @author Ne-Lexa alexey@nelexa.ru
* @license MIT
*/
class ExtraFieldsFactory
{
- /**
- * @var array|null
- */
+ /** @var array|null */
protected static $registry;
private function __construct()
@@ -30,18 +28,22 @@ class ExtraFieldsFactory
}
/**
- * @param string $extra
+ * @param string $extra
* @param ZipEntry|null $entry
- * @return ExtraFieldsCollection
+ *
* @throws ZipException
+ *
+ * @return ExtraFieldsCollection
*/
public static function createExtraFieldCollections($extra, ZipEntry $entry = null)
{
$extraFieldsCollection = new ExtraFieldsCollection();
+
if ($extra !== null) {
- $extraLength = strlen($extra);
+ $extraLength = \strlen($extra);
+
if ($extraLength > 0xffff) {
- throw new ZipException("Extra Fields too large: " . $extraLength);
+ throw new ZipException('Extra Fields too large: ' . $extraLength);
}
$pos = 0;
$endPos = $extraLength;
@@ -49,38 +51,53 @@ class ExtraFieldsFactory
while ($endPos - $pos >= 4) {
$unpack = unpack('vheaderId/vdataSize', substr($extra, $pos, 4));
$pos += 4;
- $headerId = (int)$unpack['headerId'];
- $dataSize = (int)$unpack['dataSize'];
- $extraField = ExtraFieldsFactory::create($headerId);
+ $headerId = (int) $unpack['headerId'];
+ $dataSize = (int) $unpack['dataSize'];
+ $extraField = self::create($headerId);
+
if ($extraField instanceof Zip64ExtraField && $entry !== null) {
$extraField->setEntry($entry);
}
- $extraField->deserialize(substr($extra, $pos, $dataSize));
+
+ if ($dataSize > 0) {
+ $content = substr($extra, $pos, $dataSize);
+
+ if ($content !== false) {
+ $extraField->deserialize($content);
+ $extraFieldsCollection[$headerId] = $extraField;
+ }
+ }
+
$pos += $dataSize;
- $extraFieldsCollection[$headerId] = $extraField;
}
}
+
return $extraFieldsCollection;
}
/**
* @param ExtraFieldsCollection $extraFieldsCollection
- * @return string
+ *
* @throws ZipException
+ *
+ * @return string
*/
public static function createSerializedData(ExtraFieldsCollection $extraFieldsCollection)
{
$extraData = '';
+
foreach ($extraFieldsCollection as $extraField) {
$data = $extraField->serialize();
- $extraData .= pack('vv', $extraField::getHeaderId(), strlen($data));
+ $extraData .= pack('vv', $extraField::getHeaderId(), \strlen($data));
$extraData .= $data;
}
- $size = strlen($extraData);
- if (0x0000 > $size || $size > 0xffff) {
+ $size = \strlen($extraData);
+
+ if ($size < 0x0000 || $size > 0xffff) {
throw new ZipException('Size extra out of range: ' . $size . '. Extra data: ' . $extraData);
}
+
return $extraData;
}
@@ -90,29 +107,31 @@ class ExtraFieldsFactory
* The returned Extra Field still requires proper initialization, for
* example by calling ExtraField::readFrom.
*
- * @param int $headerId An unsigned short integer (two bytes) which indicates
- * the type of the returned Extra Field.
- * @return ExtraField A new Extra Field or null if not support header id.
- * @throws ZipException If headerId is out of range.
+ * @param int $headerId an unsigned short integer (two bytes) which indicates
+ * the type of the returned Extra Field
+ *
+ * @throws ZipException if headerId is out of range
+ *
+ * @return ExtraField a new Extra Field or null if not support header id
*/
public static function create($headerId)
{
- if (0x0000 > $headerId || $headerId > 0xffff) {
+ if ($headerId < 0x0000 || $headerId > 0xffff) {
throw new ZipException('headerId out of range');
}
- /**
- * @var ExtraField $extraField
- */
if (isset(self::getRegistry()[$headerId])) {
$extraClassName = self::getRegistry()[$headerId];
- $extraField = new $extraClassName;
+ /** @var ExtraField $extraField */
+ $extraField = new $extraClassName();
+
if ($headerId !== $extraField::getHeaderId()) {
throw new ZipException('Runtime error support headerId ' . $headerId);
}
} else {
$extraField = new DefaultExtraField($headerId);
}
+
return $extraField;
}
@@ -130,6 +149,7 @@ class ExtraFieldsFactory
self::$registry[ApkAlignmentExtraField::getHeaderId()] = ApkAlignmentExtraField::class;
self::$registry[JarMarkerExtraField::getHeaderId()] = JarMarkerExtraField::class;
}
+
return self::$registry;
}
@@ -151,6 +171,7 @@ class ExtraFieldsFactory
/**
* @param ZipEntry $entry
+ *
* @return Zip64ExtraField
*/
public static function createZip64Extra(ZipEntry $entry)
@@ -160,19 +181,22 @@ class ExtraFieldsFactory
/**
* @param ZipEntry $entry
- * @param int $padding
+ * @param int $padding
+ *
* @return ApkAlignmentExtraField
*/
public static function createApkAlignExtra(ZipEntry $entry, $padding)
{
- $padding = (int)$padding;
+ $padding = (int) $padding;
$multiple = 4;
+
if (StringUtil::endsWith($entry->getName(), '.so')) {
$multiple = ApkAlignmentExtraField::ANDROID_COMMON_PAGE_ALIGNMENT_BYTES;
}
$extraField = new ApkAlignmentExtraField();
$extraField->setMultiple($multiple);
$extraField->setPadding($padding);
+
return $extraField;
}
}
diff --git a/src/PhpZip/Extra/Fields/ApkAlignmentExtraField.php b/src/PhpZip/Extra/Fields/ApkAlignmentExtraField.php
index a9b9031..9548f63 100644
--- a/src/PhpZip/Extra/Fields/ApkAlignmentExtraField.php
+++ b/src/PhpZip/Extra/Fields/ApkAlignmentExtraField.php
@@ -6,7 +6,7 @@ use PhpZip\Exception\InvalidArgumentException;
use PhpZip\Extra\ExtraField;
/**
- * Apk Alignment Extra Field
+ * Apk Alignment Extra Field.
*
* @author Ne-Lexa alexey@nelexa.ru
* @license MIT
@@ -21,13 +21,10 @@ class ApkAlignmentExtraField implements ExtraField
const ANDROID_COMMON_PAGE_ALIGNMENT_BYTES = 4096;
- /**
- * @var int
- */
+ /** @var int */
private $multiple;
- /**
- * @var int
- */
+
+ /** @var int */
private $padding;
/**
@@ -44,6 +41,7 @@ class ApkAlignmentExtraField implements ExtraField
/**
* Serializes a Data Block.
+ *
* @return string
*/
public function serialize()
@@ -53,25 +51,31 @@ class ApkAlignmentExtraField implements ExtraField
['vc*', $this->multiple],
array_fill(2, $this->padding, 0)
);
- return call_user_func_array('pack', $args);
+
+ return \call_user_func_array('pack', $args);
}
+
return pack('v', $this->multiple);
}
/**
* Initializes this Extra Field by deserializing a Data Block.
+ *
* @param string $data
*/
public function deserialize($data)
{
- $length = strlen($data);
+ $length = \strlen($data);
+
if ($length < 2) {
// This is APK alignment field.
// FORMAT:
// * uint16 alignment multiple (in bytes)
// * remaining bytes -- padding to achieve alignment of data which starts after
// the extra field
- throw new InvalidArgumentException("Minimum 6 bytes of the extensible data block/field used for alignment of uncompressed entries.");
+ throw new InvalidArgumentException(
+ 'Minimum 6 bytes of the extensible data block/field used for alignment of uncompressed entries.'
+ );
}
$this->multiple = unpack('v', $data)[1];
$this->padding = $length - 2;
diff --git a/src/PhpZip/Extra/Fields/DefaultExtraField.php b/src/PhpZip/Extra/Fields/DefaultExtraField.php
index 77af380..231fa32 100644
--- a/src/PhpZip/Extra/Fields/DefaultExtraField.php
+++ b/src/PhpZip/Extra/Fields/DefaultExtraField.php
@@ -14,26 +14,23 @@ use PhpZip\Extra\ExtraField;
*/
class DefaultExtraField implements ExtraField
{
- /**
- * @var int
- */
+ /** @var int */
private static $headerId;
- /**
- * @var string
- */
+ /** @var string */
protected $data;
/**
* Constructs a new Extra Field.
*
* @param int $headerId an unsigned short integer (two bytes) indicating the
- * type of the Extra Field.
+ * type of the Extra Field
+ *
* @throws ZipException
*/
public function __construct($headerId)
{
- if (0x0000 > $headerId || $headerId > 0xffff) {
+ if ($headerId < 0x0000 || $headerId > 0xffff) {
throw new ZipException('headerId out of range');
}
self::$headerId = $headerId;
@@ -53,6 +50,7 @@ class DefaultExtraField implements ExtraField
/**
* Serializes a Data Block.
+ *
* @return string
*/
public function serialize()
@@ -62,6 +60,7 @@ class DefaultExtraField implements ExtraField
/**
* Initializes this Extra Field by deserializing a Data Block.
+ *
* @param string $data
*/
public function deserialize($data)
diff --git a/src/PhpZip/Extra/Fields/JarMarkerExtraField.php b/src/PhpZip/Extra/Fields/JarMarkerExtraField.php
index 01c66b4..8914204 100644
--- a/src/PhpZip/Extra/Fields/JarMarkerExtraField.php
+++ b/src/PhpZip/Extra/Fields/JarMarkerExtraField.php
@@ -30,6 +30,7 @@ class JarMarkerExtraField implements ExtraField
/**
* Serializes a Data Block.
+ *
* @return string
*/
public function serialize()
@@ -39,12 +40,14 @@ class JarMarkerExtraField implements ExtraField
/**
* Initializes this Extra Field by deserializing a Data Block.
+ *
* @param string $data
+ *
* @throws ZipException
*/
public function deserialize($data)
{
- if (strlen($data) !== 0) {
+ if ($data !== '') {
throw new ZipException("JarMarker doesn't expect any data");
}
}
diff --git a/src/PhpZip/Extra/Fields/NtfsExtraField.php b/src/PhpZip/Extra/Fields/NtfsExtraField.php
index 02f761c..626a88b 100644
--- a/src/PhpZip/Extra/Fields/NtfsExtraField.php
+++ b/src/PhpZip/Extra/Fields/NtfsExtraField.php
@@ -6,31 +6,31 @@ use PhpZip\Extra\ExtraField;
use PhpZip\Util\PackUtil;
/**
- * NTFS Extra Field
+ * NTFS Extra Field.
*
* @see https://pkware.cachefly.net/webdocs/casestudies/APPNOTE.TXT .ZIP File Format Specification
+ *
* @author Ne-Lexa alexey@nelexa.ru
* @license MIT
*/
class NtfsExtraField implements ExtraField
{
-
/**
- * Modify time
+ * Modify time.
*
* @var int Unix Timestamp
*/
private $mtime;
/**
- * Access Time
+ * Access Time.
*
* @var int Unix Timestamp
*/
private $atime;
/**
- * Create Time
+ * Create Time.
*
* @var int Unix Time
*/
@@ -50,11 +50,13 @@ class NtfsExtraField implements ExtraField
/**
* Initializes this Extra Field by deserializing a Data Block.
+ *
* @param string $data
*/
public function deserialize($data)
{
$unpack = unpack('vtag/vsizeAttr', substr($data, 0, 4));
+
if ($unpack['sizeAttr'] === 24) {
$tagData = substr($data, 4, $unpack['sizeAttr']);
$this->mtime = PackUtil::unpackLongLE(substr($tagData, 0, 8)) / 10000000 - 11644473600;
@@ -65,11 +67,13 @@ class NtfsExtraField implements ExtraField
/**
* Serializes a Data Block.
+ *
* @return string
*/
public function serialize()
{
$serialize = '';
+
if ($this->mtime !== null && $this->atime !== null && $this->ctime !== null) {
$mtimeLong = ($this->mtime + 11644473600) * 10000000;
$atimeLong = ($this->atime + 11644473600) * 10000000;
@@ -80,6 +84,7 @@ class NtfsExtraField implements ExtraField
. PackUtil::packLongLE($atimeLong)
. PackUtil::packLongLE($ctimeLong);
}
+
return $serialize;
}
@@ -96,7 +101,7 @@ class NtfsExtraField implements ExtraField
*/
public function setMtime($mtime)
{
- $this->mtime = (int)$mtime;
+ $this->mtime = (int) $mtime;
}
/**
@@ -112,7 +117,7 @@ class NtfsExtraField implements ExtraField
*/
public function setAtime($atime)
{
- $this->atime = (int)$atime;
+ $this->atime = (int) $atime;
}
/**
@@ -128,6 +133,6 @@ class NtfsExtraField implements ExtraField
*/
public function setCtime($ctime)
{
- $this->ctime = (int)$ctime;
+ $this->ctime = (int) $ctime;
}
}
diff --git a/src/PhpZip/Extra/Fields/WinZipAesEntryExtraField.php b/src/PhpZip/Extra/Fields/WinZipAesEntryExtraField.php
index 7f640bf..948452a 100644
--- a/src/PhpZip/Extra/Fields/WinZipAesEntryExtraField.php
+++ b/src/PhpZip/Extra/Fields/WinZipAesEntryExtraField.php
@@ -9,42 +9,49 @@ use PhpZip\ZipFileInterface;
/**
* WinZip AES Extra Field.
*
- * @see http://www.winzip.com/win/en/aes_info.htm AES Encryption Information: Encryption Specification AE-1 and AE-2 (WinZip Computing, S.L.)
+ * @see http://www.winzip.com/win/en/aes_info.htm AES Encryption Information: Encryption Specification AE-1 and AE-2
+ * (WinZip Computing, S.L.)
* @see http://www.winzip.com/win/en/aes_tips.htm AES Coding Tips for Developers (WinZip Computing, S.L.)
+ *
* @author Ne-Lexa alexey@nelexa.ru
* @license MIT
*/
class WinZipAesEntryExtraField implements ExtraField
{
const DATA_SIZE = 7;
+
const VENDOR_ID = 17729; // 'A' | ('E' << 8);
/**
* Entries of this type do include the standard ZIP CRC-32 value.
- * For use with @see WinZipAesEntryExtraField::setVendorVersion()}/@see WinZipAesEntryExtraField::getVendorVersion().
+ * For use with @see WinZipAesEntryExtraField::setVendorVersion()}/@see
+ * WinZipAesEntryExtraField::getVendorVersion().
*/
const VV_AE_1 = 1;
/**
* Entries of this type do not include the standard ZIP CRC-32 value.
- * For use with @see WinZipAesEntryExtraField::setVendorVersion()}/@see WinZipAesEntryExtraField::getVendorVersion().
+ * For use with @see WinZipAesEntryExtraField::setVendorVersion()}/@see
+ * WinZipAesEntryExtraField::getVendorVersion().
*/
const VV_AE_2 = 2;
const KEY_STRENGTH_128BIT = 128;
+
const KEY_STRENGTH_192BIT = 192;
+
const KEY_STRENGTH_256BIT = 256;
protected static $keyStrengths = [
self::KEY_STRENGTH_128BIT => 0x01,
self::KEY_STRENGTH_192BIT => 0x02,
- self::KEY_STRENGTH_256BIT => 0x03
+ self::KEY_STRENGTH_256BIT => 0x03,
];
protected static $encryptionMethods = [
self::KEY_STRENGTH_128BIT => ZipFileInterface::ENCRYPTION_METHOD_WINZIP_AES_128,
self::KEY_STRENGTH_192BIT => ZipFileInterface::ENCRYPTION_METHOD_WINZIP_AES_192,
- self::KEY_STRENGTH_256BIT => ZipFileInterface::ENCRYPTION_METHOD_WINZIP_AES_256
+ self::KEY_STRENGTH_256BIT => ZipFileInterface::ENCRYPTION_METHOD_WINZIP_AES_256,
];
/**
@@ -94,14 +101,16 @@ class WinZipAesEntryExtraField implements ExtraField
/**
* Sets the vendor version.
*
+ * @param int $vendorVersion the vendor version
+ *
+ * @throws ZipException unsupport vendor version
+ *
* @see WinZipAesEntryExtraField::VV_AE_1
* @see WinZipAesEntryExtraField::VV_AE_2
- * @param int $vendorVersion the vendor version.
- * @throws ZipException Unsupport vendor version.
*/
public function setVendorVersion($vendorVersion)
{
- if ($vendorVersion < self::VV_AE_1 || self::VV_AE_2 < $vendorVersion) {
+ if ($vendorVersion < self::VV_AE_1 || $vendorVersion > self::VV_AE_2) {
throw new ZipException($vendorVersion);
}
$this->vendorVersion = $vendorVersion;
@@ -118,8 +127,9 @@ class WinZipAesEntryExtraField implements ExtraField
}
/**
- * @return bool|int
* @throws ZipException
+ *
+ * @return bool|int
*/
public function getKeyStrength()
{
@@ -127,16 +137,20 @@ class WinZipAesEntryExtraField implements ExtraField
}
/**
- * @param int $encryptionStrength Encryption strength as bits.
+ * @param int $encryptionStrength encryption strength as bits
+ *
+ * @throws ZipException if unsupport encryption strength
+ *
* @return int
- * @throws ZipException If unsupport encryption strength.
*/
public static function keyStrength($encryptionStrength)
{
$flipKeyStrength = array_flip(self::$keyStrengths);
+
if (!isset($flipKeyStrength[$encryptionStrength])) {
- throw new ZipException("Unsupport encryption strength " . $encryptionStrength);
+ throw new ZipException('Unsupport encryption strength ' . $encryptionStrength);
}
+
return $flipKeyStrength[$encryptionStrength];
}
@@ -153,8 +167,9 @@ class WinZipAesEntryExtraField implements ExtraField
/**
* Internal encryption method.
*
- * @return int
* @throws ZipException
+ *
+ * @return int
*/
public function getEncryptionMethod()
{
@@ -165,15 +180,19 @@ class WinZipAesEntryExtraField implements ExtraField
/**
* @param int $encryptionMethod
- * @return int
+ *
* @throws ZipException
+ *
+ * @return int
*/
public static function getKeyStrangeFromEncryptionMethod($encryptionMethod)
{
$flipKey = array_flip(self::$encryptionMethods);
+
if (!isset($flipKey[$encryptionMethod])) {
- throw new ZipException("Unsupport encryption method " . $encryptionMethod);
+ throw new ZipException('Unsupport encryption method ' . $encryptionMethod);
}
+
return $flipKey[$encryptionMethod];
}
@@ -181,11 +200,12 @@ class WinZipAesEntryExtraField implements ExtraField
* Sets compression method.
*
* @param int $compressionMethod Compression method
- * @throws ZipException Compression method out of range.
+ *
+ * @throws ZipException compression method out of range
*/
public function setMethod($compressionMethod)
{
- if (0x0000 > $compressionMethod || $compressionMethod > 0xffff) {
+ if ($compressionMethod < 0x0000 || $compressionMethod > 0xffff) {
throw new ZipException('Compression method out of range');
}
$this->method = $compressionMethod;
@@ -204,7 +224,8 @@ class WinZipAesEntryExtraField implements ExtraField
/**
* Returns encryption strength.
*
- * @param int $keyStrength Key strength in bits.
+ * @param int $keyStrength key strength in bits
+ *
* @return int
*/
public static function encryptionStrength($keyStrength)
@@ -216,6 +237,7 @@ class WinZipAesEntryExtraField implements ExtraField
/**
* Serializes a Data Block.
+ *
* @return string
*/
public function serialize()
@@ -231,13 +253,16 @@ class WinZipAesEntryExtraField implements ExtraField
/**
* Initializes this Extra Field by deserializing a Data Block.
+ *
* @param string $data
+ *
* @throws ZipException
*/
public function deserialize($data)
{
- $size = strlen($data);
- if (self::DATA_SIZE !== $size) {
+ $size = \strlen($data);
+
+ if ($size !== self::DATA_SIZE) {
throw new ZipException('WinZip AES Extra data invalid size: ' . $size . '. Must be ' . self::DATA_SIZE);
}
@@ -249,7 +274,8 @@ class WinZipAesEntryExtraField implements ExtraField
*/
$unpack = unpack('vvendorVersion/vvendorId/ckeyStrength/vmethod', $data);
$this->setVendorVersion($unpack['vendorVersion']);
- if (self::VENDOR_ID !== $unpack['vendorId']) {
+
+ if ($unpack['vendorId'] !== self::VENDOR_ID) {
throw new ZipException('Vendor id invalid: ' . $unpack['vendorId'] . '. Must be ' . self::VENDOR_ID);
}
$this->setKeyStrength(self::keyStrength($unpack['keyStrength'])); // checked
diff --git a/src/PhpZip/Extra/Fields/Zip64ExtraField.php b/src/PhpZip/Extra/Fields/Zip64ExtraField.php
index c39dff0..982010d 100644
--- a/src/PhpZip/Extra/Fields/Zip64ExtraField.php
+++ b/src/PhpZip/Extra/Fields/Zip64ExtraField.php
@@ -3,14 +3,16 @@
namespace PhpZip\Extra\Fields;
use PhpZip\Exception\RuntimeException;
+use PhpZip\Exception\ZipException;
use PhpZip\Extra\ExtraField;
use PhpZip\Model\ZipEntry;
use PhpZip\Util\PackUtil;
/**
- * ZIP64 Extra Field
+ * ZIP64 Extra Field.
*
* @see https://pkware.cachefly.net/webdocs/casestudies/APPNOTE.TXT .ZIP File Format Specification
+ *
* @author Ne-Lexa alexey@nelexa.ru
* @license MIT
*/
@@ -18,13 +20,13 @@ class Zip64ExtraField implements ExtraField
{
/** The Header ID for a ZIP64 Extended Information Extra Field. */
const ZIP64_HEADER_ID = 0x0001;
- /**
- * @var ZipEntry
- */
+
+ /** @var ZipEntry */
protected $entry;
/**
* Zip64ExtraField constructor.
+ *
* @param ZipEntry $entry
*/
public function __construct(ZipEntry $entry = null)
@@ -56,61 +58,71 @@ class Zip64ExtraField implements ExtraField
/**
* Serializes a Data Block.
+ *
* @return string
*/
public function serialize()
{
if ($this->entry === null) {
- throw new RuntimeException("entry is null");
+ throw new RuntimeException('entry is null');
}
$data = '';
// Write out Uncompressed Size.
$size = $this->entry->getSize();
- if (0xffffffff <= $size) {
+
+ if ($size >= 0xffffffff) {
$data .= PackUtil::packLongLE($size);
}
// Write out Compressed Size.
$compressedSize = $this->entry->getCompressedSize();
- if (0xffffffff <= $compressedSize) {
+
+ if ($compressedSize >= 0xffffffff) {
$data .= PackUtil::packLongLE($compressedSize);
}
// Write out Relative Header Offset.
$offset = $this->entry->getOffset();
- if (0xffffffff <= $offset) {
+
+ if ($offset >= 0xffffffff) {
$data .= PackUtil::packLongLE($offset);
}
+
return $data;
}
/**
* Initializes this Extra Field by deserializing a Data Block.
+ *
* @param string $data
- * @throws \PhpZip\Exception\ZipException
+ *
+ * @throws ZipException
*/
public function deserialize($data)
{
if ($this->entry === null) {
- throw new RuntimeException("entry is null");
+ throw new RuntimeException('entry is null');
}
$off = 0;
// Read in Uncompressed Size.
$size = $this->entry->getSize();
- if (0xffffffff <= $size) {
- assert(0xffffffff === $size);
+
+ if ($size >= 0xffffffff) {
+ \assert($size === 0xffffffff);
$this->entry->setSize(PackUtil::unpackLongLE(substr($data, $off, 8)));
$off += 8;
}
// Read in Compressed Size.
$compressedSize = $this->entry->getCompressedSize();
- if (0xffffffff <= $compressedSize) {
- assert(0xffffffff === $compressedSize);
+
+ if ($compressedSize >= 0xffffffff) {
+ \assert($compressedSize === 0xffffffff);
$this->entry->setCompressedSize(PackUtil::unpackLongLE(substr($data, $off, 8)));
$off += 8;
}
// Read in Relative Header Offset.
$offset = $this->entry->getOffset();
- if (0xffffffff <= $offset) {
- assert(0xffffffff, $offset);
+
+ if ($offset >= 0xffffffff) {
+ \assert(0xffffffff, $offset);
$this->entry->setOffset(PackUtil::unpackLongLE(substr($data, $off, 8)));
}
}
diff --git a/src/PhpZip/Mapper/OffsetPositionMapper.php b/src/PhpZip/Mapper/OffsetPositionMapper.php
index 7ea9116..747b8a1 100644
--- a/src/PhpZip/Mapper/OffsetPositionMapper.php
+++ b/src/PhpZip/Mapper/OffsetPositionMapper.php
@@ -10,9 +10,7 @@ namespace PhpZip\Mapper;
*/
class OffsetPositionMapper extends PositionMapper
{
- /**
- * @var int
- */
+ /** @var int */
private $offset;
/**
@@ -20,11 +18,12 @@ class OffsetPositionMapper extends PositionMapper
*/
public function __construct($offset)
{
- $this->offset = (int)$offset;
+ $this->offset = (int) $offset;
}
/**
* @param int $position
+ *
* @return int
*/
public function map($position)
@@ -34,6 +33,7 @@ class OffsetPositionMapper extends PositionMapper
/**
* @param int $position
+ *
* @return int
*/
public function unmap($position)
diff --git a/src/PhpZip/Mapper/PositionMapper.php b/src/PhpZip/Mapper/PositionMapper.php
index e5d67c8..42a9b29 100644
--- a/src/PhpZip/Mapper/PositionMapper.php
+++ b/src/PhpZip/Mapper/PositionMapper.php
@@ -12,6 +12,7 @@ class PositionMapper
{
/**
* @param int $position
+ *
* @return int
*/
public function map($position)
@@ -21,6 +22,7 @@ class PositionMapper
/**
* @param int $position
+ *
* @return int
*/
public function unmap($position)
diff --git a/src/PhpZip/Model/EndOfCentralDirectory.php b/src/PhpZip/Model/EndOfCentralDirectory.php
index 8016e5f..f27d57f 100644
--- a/src/PhpZip/Model/EndOfCentralDirectory.php
+++ b/src/PhpZip/Model/EndOfCentralDirectory.php
@@ -3,7 +3,7 @@
namespace PhpZip\Model;
/**
- * Read End of Central Directory
+ * Read End of Central Directory.
*
* @author Ne-Lexa alexey@nelexa.ru
* @license MIT
@@ -12,10 +12,13 @@ class EndOfCentralDirectory
{
/** Zip64 End Of Central Directory Record. */
const ZIP64_END_OF_CENTRAL_DIRECTORY_RECORD_SIG = 0x06064B50;
+
/** Zip64 End Of Central Directory Locator. */
const ZIP64_END_OF_CENTRAL_DIRECTORY_LOCATOR_SIG = 0x07064B50;
+
/** End Of Central Directory Record signature. */
const END_OF_CENTRAL_DIRECTORY_RECORD_SIG = 0x06054B50;
+
/**
* The minimum length of the End Of Central Directory Record.
*
@@ -34,6 +37,7 @@ class EndOfCentralDirectory
* zipfile comment length 2
*/
const END_OF_CENTRAL_DIRECTORY_RECORD_MIN_LEN = 22;
+
/**
* The length of the Zip64 End Of Central Directory Locator.
* zip64 end of central dir locator
@@ -43,9 +47,10 @@ class EndOfCentralDirectory
* central directory 4
* relative offset of the zip64
* end of central directory record 8
- * total number of disks 4
+ * total number of disks 4.
*/
const ZIP64_END_OF_CENTRAL_DIRECTORY_LOCATOR_LEN = 20;
+
/**
* The minimum length of the Zip64 End Of Central Directory Record.
*
@@ -68,24 +73,22 @@ class EndOfCentralDirectory
* the starting disk number 8
*/
const ZIP64_END_OF_CENTRAL_DIRECTORY_RECORD_MIN_LEN = 56;
- /**
- * @var string|null The archive comment.
- */
+
+ /** @var string|null the archive comment */
private $comment;
- /**
- * @var int
- */
+
+ /** @var int */
private $entryCount;
- /**
- * @var bool
- */
+
+ /** @var bool */
private $zip64 = false;
/**
* EndOfCentralDirectory constructor.
- * @param int $entryCount
- * @param null|string $comment
- * @param bool $zip64
+ *
+ * @param int $entryCount
+ * @param string|null $comment
+ * @param bool $zip64
*/
public function __construct($entryCount, $comment, $zip64 = false)
{
@@ -95,7 +98,7 @@ class EndOfCentralDirectory
}
/**
- * @return null|string
+ * @return string|null
*/
public function getComment()
{
diff --git a/src/PhpZip/Model/Entry/OutputOffsetEntry.php b/src/PhpZip/Model/Entry/OutputOffsetEntry.php
index 94bd15b..fea5383 100644
--- a/src/PhpZip/Model/Entry/OutputOffsetEntry.php
+++ b/src/PhpZip/Model/Entry/OutputOffsetEntry.php
@@ -12,17 +12,14 @@ use PhpZip\Model\ZipEntry;
*/
class OutputOffsetEntry
{
- /**
- * @var int
- */
+ /** @var int */
private $offset;
- /**
- * @var ZipEntry
- */
+
+ /** @var ZipEntry */
private $entry;
/**
- * @param int $pos
+ * @param int $pos
* @param ZipEntry $entry
*/
public function __construct($pos, ZipEntry $entry)
diff --git a/src/PhpZip/Model/Entry/ZipAbstractEntry.php b/src/PhpZip/Model/Entry/ZipAbstractEntry.php
index b8cdb5e..2b4c14d 100644
--- a/src/PhpZip/Model/Entry/ZipAbstractEntry.php
+++ b/src/PhpZip/Model/Entry/ZipAbstractEntry.php
@@ -16,59 +16,48 @@ use PhpZip\ZipFileInterface;
* Abstract ZIP entry.
*
* @see https://pkware.cachefly.net/webdocs/casestudies/APPNOTE.TXT .ZIP File Format Specification
+ *
* @author Ne-Lexa alexey@nelexa.ru
* @license MIT
*/
abstract class ZipAbstractEntry implements ZipEntry
{
- /**
- * @var int Bit flags for init state.
- */
+ /** @var int bit flags for init state */
private $init;
- /**
- * @var string Entry name (filename in archive)
- */
+
+ /** @var string Entry name (filename in archive) */
private $name;
- /**
- * @var int Made by platform
- */
+
+ /** @var int Made by platform */
private $platform;
- /**
- * @var int
- */
+
+ /** @var int */
private $versionNeededToExtract = 20;
- /**
- * @var int Compression method
- */
+
+ /** @var int Compression method */
private $method;
- /**
- * @var int
- */
+
+ /** @var int */
private $general;
- /**
- * @var int Dos time
- */
+
+ /** @var int Dos time */
private $dosTime;
- /**
- * @var int Crc32
- */
+
+ /** @var int Crc32 */
private $crc;
- /**
- * @var int Compressed size
- */
+
+ /** @var int Compressed size */
private $compressedSize = self::UNKNOWN;
- /**
- * @var int Uncompressed size
- */
+
+ /** @var int Uncompressed size */
private $size = self::UNKNOWN;
- /**
- * @var int External attributes
- */
+
+ /** @var int External attributes */
private $externalAttributes;
- /**
- * @var int Relative Offset Of Local File Header.
- */
+
+ /** @var int relative Offset Of Local File Header */
private $offset = self::UNKNOWN;
+
/**
* Collections of Extra Fields.
* Keys from Header ID [int] and value Extra Field [ExtraField].
@@ -77,26 +66,26 @@ abstract class ZipAbstractEntry implements ZipEntry
* @var ExtraFieldsCollection
*/
private $extraFieldsCollection;
- /**
- * @var string Comment field.
- */
+
+ /** @var string comment field */
private $comment;
- /**
- * @var string Entry password for read or write encryption data.
- */
+
+ /** @var string entry password for read or write encryption data */
private $password;
+
/**
* Encryption method.
+ *
* @see ZipFileInterface::ENCRYPTION_METHOD_TRADITIONAL
* @see ZipFileInterface::ENCRYPTION_METHOD_WINZIP_AES_128
* @see ZipFileInterface::ENCRYPTION_METHOD_WINZIP_AES_192
* @see ZipFileInterface::ENCRYPTION_METHOD_WINZIP_AES_256
+ *
* @var int
*/
private $encryptionMethod = ZipFileInterface::ENCRYPTION_METHOD_TRADITIONAL;
- /**
- * @var int
- */
+
+ /** @var int */
private $compressionLevel = ZipFileInterface::LEVEL_DEFAULT_COMPRESSION;
/**
@@ -109,6 +98,7 @@ abstract class ZipAbstractEntry implements ZipEntry
/**
* @param ZipEntry $entry
+ *
* @throws ZipException
*/
public function setEntry(ZipEntry $entry)
@@ -146,25 +136,30 @@ abstract class ZipAbstractEntry implements ZipEntry
* Set entry name.
*
* @param string $name New entry name
- * @return ZipEntry
+ *
* @throws ZipException
+ *
+ * @return ZipEntry
*/
public function setName($name)
{
- $length = strlen($name);
- if (0x0000 > $length || $length > 0xffff) {
+ $length = \strlen($name);
+
+ if ($length < 0x0000 || $length > 0xffff) {
throw new ZipException('Illegal zip entry name parameter');
}
$this->setGeneralPurposeBitFlag(self::GPBF_UTF8, true);
$this->name = $name;
+
return $this;
}
/**
* Sets the indexed General Purpose Bit Flag.
*
- * @param int $mask
+ * @param int $mask
* @param bool $bit
+ *
* @return ZipEntry
*/
public function setGeneralPurposeBitFlag($mask, $bit)
@@ -174,6 +169,7 @@ abstract class ZipAbstractEntry implements ZipEntry
} else {
$this->general &= ~$mask;
}
+
return $this;
}
@@ -186,29 +182,34 @@ abstract class ZipAbstractEntry implements ZipEntry
}
/**
- * Set platform
+ * Set platform.
*
* @param int $platform
- * @return ZipEntry
+ *
* @throws ZipException
+ *
+ * @return ZipEntry
*/
public function setPlatform($platform)
{
- $known = self::UNKNOWN !== $platform;
+ $known = $platform !== self::UNKNOWN;
+
if ($known) {
- if (0x00 > $platform || $platform > 0xff) {
- throw new ZipException("Platform out of range");
+ if ($platform < 0x00 || $platform > 0xff) {
+ throw new ZipException('Platform out of range');
}
$this->platform = $platform;
} else {
$this->platform = 0;
}
$this->setInit(self::BIT_PLATFORM, $known);
+
return $this;
}
/**
* @param int $mask
+ *
* @return bool
*/
protected function isInit($mask)
@@ -217,7 +218,7 @@ abstract class ZipAbstractEntry implements ZipEntry
}
/**
- * @param int $mask
+ * @param int $mask
* @param bool $init
*/
protected function setInit($mask, $init)
@@ -243,11 +244,13 @@ abstract class ZipAbstractEntry implements ZipEntry
* Set version needed to extract.
*
* @param int $version
+ *
* @return ZipEntry
*/
public function setVersionNeededToExtract($version)
{
$this->versionNeededToExtract = $version;
+
return $this;
}
@@ -256,8 +259,8 @@ abstract class ZipAbstractEntry implements ZipEntry
*/
public function isZip64ExtensionsRequired()
{
- return 0xffffffff <= $this->getCompressedSize()
- || 0xffffffff <= $this->getSize();
+ return $this->getCompressedSize() >= 0xffffffff
+ || $this->getSize() >= 0xffffffff;
}
/**
@@ -273,12 +276,14 @@ abstract class ZipAbstractEntry implements ZipEntry
/**
* Sets the compressed size of this entry.
*
- * @param int $compressedSize The Compressed Size.
+ * @param int $compressedSize the Compressed Size
+ *
* @return ZipEntry
*/
public function setCompressedSize($compressedSize)
{
$this->compressedSize = $compressedSize;
+
return $this;
}
@@ -295,12 +300,14 @@ abstract class ZipAbstractEntry implements ZipEntry
/**
* Sets the uncompressed size of this entry.
*
- * @param int $size The (Uncompressed) Size.
+ * @param int $size the (Uncompressed) Size
+ *
* @return ZipEntry
*/
public function setSize($size)
{
$this->size = $size;
+
return $this;
}
@@ -316,16 +323,19 @@ abstract class ZipAbstractEntry implements ZipEntry
/**
* @param int $offset
+ *
* @return ZipEntry
*/
public function setOffset($offset)
{
$this->offset = $offset;
+
return $this;
}
/**
* Returns the General Purpose Bit Flags.
+ *
* @return int
*/
public function getGeneralPurposeBitFlags()
@@ -336,19 +346,25 @@ abstract class ZipAbstractEntry implements ZipEntry
/**
* Sets the General Purpose Bit Flags.
*
- * @var int general
- * @return ZipEntry
+ * @param mixed $general
+ *
* @throws ZipException
+ *
+ * @return ZipEntry
+ *
+ * @var int general
*/
public function setGeneralPurposeBitFlags($general)
{
- if (0x0000 > $general || $general > 0xffff) {
+ if ($general < 0x0000 || $general > 0xffff) {
throw new ZipException('general out of range');
}
$this->general = $general;
+
if ($this->method === ZipFileInterface::METHOD_DEFLATED) {
$bit1 = $this->getGeneralPurposeBitFlag(self::GPBF_COMPRESSION_FLAG1);
$bit2 = $this->getGeneralPurposeBitFlag(self::GPBF_COMPRESSION_FLAG2);
+
if ($bit1 && !$bit2) {
$this->compressionLevel = ZipFileInterface::LEVEL_BEST_COMPRESSION;
} elseif (!$bit1 && $bit2) {
@@ -359,6 +375,7 @@ abstract class ZipAbstractEntry implements ZipEntry
$this->compressionLevel = ZipFileInterface::LEVEL_DEFAULT_COMPRESSION;
}
}
+
return $this;
}
@@ -376,6 +393,7 @@ abstract class ZipAbstractEntry implements ZipEntry
* Returns the indexed General Purpose Bit Flag.
*
* @param int $mask
+ *
* @return bool
*/
public function getGeneralPurposeBitFlag($mask)
@@ -387,24 +405,26 @@ abstract class ZipAbstractEntry implements ZipEntry
* Sets the encryption property to false and removes any other
* encryption artifacts.
*
- * @return ZipEntry
* @throws ZipException
+ *
+ * @return ZipEntry
*/
public function disableEncryption()
{
$this->setEncrypted(false);
$headerId = WinZipAesEntryExtraField::getHeaderId();
+
if (isset($this->extraFieldsCollection[$headerId])) {
- /**
- * @var WinZipAesEntryExtraField $field
- */
+ /** @var WinZipAesEntryExtraField $field */
$field = $this->extraFieldsCollection[$headerId];
- if (self::METHOD_WINZIP_AES === $this->getMethod()) {
+
+ if ($this->getMethod() === self::METHOD_WINZIP_AES) {
$this->setMethod($field === null ? self::UNKNOWN : $field->getMethod());
}
unset($this->extraFieldsCollection[$headerId]);
}
$this->password = null;
+
return $this;
}
@@ -412,12 +432,14 @@ abstract class ZipAbstractEntry implements ZipEntry
* Sets the encryption flag for this ZIP entry.
*
* @param bool $encrypted
+ *
* @return ZipEntry
*/
public function setEncrypted($encrypted)
{
- $encrypted = (bool)$encrypted;
+ $encrypted = (bool) $encrypted;
$this->setGeneralPurposeBitFlag(self::GPBF_ENCRYPTED, $encrypted);
+
return $this;
}
@@ -429,6 +451,7 @@ abstract class ZipAbstractEntry implements ZipEntry
public function getMethod()
{
$isInit = $this->isInit(self::BIT_METHOD);
+
return $isInit ?
$this->method & 0xffff :
self::UNKNOWN;
@@ -438,17 +461,21 @@ abstract class ZipAbstractEntry implements ZipEntry
* Sets the compression method for this entry.
*
* @param int $method
+ *
+ * @throws ZipException if method is not STORED, DEFLATED, BZIP2 or UNKNOWN
+ *
* @return ZipEntry
- * @throws ZipException If method is not STORED, DEFLATED, BZIP2 or UNKNOWN.
*/
public function setMethod($method)
{
if ($method === self::UNKNOWN) {
$this->method = $method;
$this->setInit(self::BIT_METHOD, false);
+
return $this;
}
- if (0x0000 > $method || $method > 0xffff) {
+
+ if ($method < 0x0000 || $method > 0xffff) {
throw new ZipException('method out of range: ' . $method);
}
switch ($method) {
@@ -461,13 +488,14 @@ abstract class ZipAbstractEntry implements ZipEntry
break;
default:
- throw new ZipException($this->name . " (unsupported compression method $method)");
+ throw new ZipException($this->name . " (unsupported compression method {$method})");
}
+
return $this;
}
/**
- * Get Unix Timestamp
+ * Get Unix Timestamp.
*
* @return int
*/
@@ -476,11 +504,12 @@ abstract class ZipAbstractEntry implements ZipEntry
if (!$this->isInit(self::BIT_DATE_TIME)) {
return self::UNKNOWN;
}
+
return DateTimeConverter::toUnixTimestamp($this->getDosTime());
}
/**
- * Get Dos Time
+ * Get Dos Time.
*
* @return int
*/
@@ -490,14 +519,17 @@ abstract class ZipAbstractEntry implements ZipEntry
}
/**
- * Set Dos Time
+ * Set Dos Time.
+ *
* @param int $dosTime
+ *
* @throws ZipException
*/
public function setDosTime($dosTime)
{
- $dosTime = sprintf('%u', $dosTime);
- if (0x00000000 > $dosTime || $dosTime > 0xffffffff) {
+ $dosTime = (int) $dosTime;
+
+ if ($dosTime < 0x00000000 || $dosTime > 0xffffffff) {
throw new ZipException('DosTime out of range');
}
$this->dosTime = $dosTime;
@@ -508,49 +540,57 @@ abstract class ZipAbstractEntry implements ZipEntry
* Set time from unix timestamp.
*
* @param int $unixTimestamp
- * @return ZipEntry
+ *
* @throws ZipException
+ *
+ * @return ZipEntry
*/
public function setTime($unixTimestamp)
{
- $known = self::UNKNOWN != $unixTimestamp;
+ $known = $unixTimestamp !== self::UNKNOWN;
+
if ($known) {
$this->dosTime = DateTimeConverter::toDosTime($unixTimestamp);
} else {
$this->dosTime = 0;
}
$this->setInit(self::BIT_DATE_TIME, $known);
+
return $this;
}
/**
* Returns the external file attributes.
*
- * @return int The external file attributes.
+ * @return int the external file attributes
*/
public function getExternalAttributes()
{
if (!$this->isInit(self::BIT_EXTERNAL_ATTR)) {
return $this->isDirectory() ? 0x10 : 0;
}
+
return $this->externalAttributes;
}
/**
* Sets the external file attributes.
*
- * @param int $externalAttributes the external file attributes.
+ * @param int $externalAttributes the external file attributes
+ *
* @return ZipEntry
*/
public function setExternalAttributes($externalAttributes)
{
- $known = self::UNKNOWN != $externalAttributes;
+ $known = $externalAttributes !== self::UNKNOWN;
+
if ($known) {
$this->externalAttributes = $externalAttributes;
} else {
$this->externalAttributes = 0;
}
$this->setInit(self::BIT_EXTERNAL_ATTR, $known);
+
return $this;
}
@@ -575,8 +615,10 @@ abstract class ZipAbstractEntry implements ZipEntry
/**
* Returns a protective copy of the serialized Extra Fields.
- * @return string
+ *
* @throws ZipException
+ *
+ * @return string
*/
public function getExtra()
{
@@ -591,7 +633,8 @@ abstract class ZipAbstractEntry implements ZipEntry
* (application) data.
* Consider storing such data in a separate entry instead.
*
- * @param string $data The byte array holding the serialized Extra Fields.
+ * @param string $data the byte array holding the serialized Extra Fields
+ *
* @throws ZipException if the serialized Extra Fields exceed 64 KB
*/
public function setExtra($data)
@@ -600,32 +643,36 @@ abstract class ZipAbstractEntry implements ZipEntry
}
/**
- * Returns comment entry
+ * Returns comment entry.
*
* @return string
*/
public function getComment()
{
- return null !== $this->comment ? $this->comment : "";
+ return $this->comment !== null ? $this->comment : '';
}
/**
* Set entry comment.
*
* @param $comment
- * @return ZipEntry
+ *
* @throws ZipException
+ *
+ * @return ZipEntry
*/
public function setComment($comment)
{
if ($comment !== null) {
- $commentLength = strlen($comment);
- if (0x0000 > $commentLength || $commentLength > 0xffff) {
- throw new ZipException("Comment too long");
+ $commentLength = \strlen($comment);
+
+ if ($commentLength < 0x0000 || $commentLength > 0xffff) {
+ throw new ZipException('Comment too long');
}
}
$this->setGeneralPurposeBitFlag(self::GPBF_UTF8, true);
$this->comment = $comment;
+
return $this;
}
@@ -634,11 +681,11 @@ abstract class ZipAbstractEntry implements ZipEntry
*/
public function isDataDescriptorRequired()
{
- return ($this->getCrc() | $this->getCompressedSize() | $this->getSize()) == self::UNKNOWN;
+ return ($this->getCrc() | $this->getCompressedSize() | $this->getSize()) === self::UNKNOWN;
}
/**
- * Return crc32 content or 0 for WinZip AES v2
+ * Return crc32 content or 0 for WinZip AES v2.
*
* @return int
*/
@@ -651,12 +698,14 @@ abstract class ZipAbstractEntry implements ZipEntry
* Set crc32 content.
*
* @param int $crc
+ *
* @return ZipEntry
*/
public function setCrc($crc)
{
$this->crc = $crc;
$this->setInit(self::BIT_CRC, true);
+
return $this;
}
@@ -669,24 +718,29 @@ abstract class ZipAbstractEntry implements ZipEntry
}
/**
- * Set password and encryption method from entry
+ * Set password and encryption method from entry.
+ *
+ * @param string $password
+ * @param int|null $encryptionMethod
*
- * @param string $password
- * @param null|int $encryptionMethod
- * @return ZipEntry
* @throws ZipException
+ *
+ * @return ZipEntry
*/
public function setPassword($password, $encryptionMethod = null)
{
$this->password = $password;
+
if ($encryptionMethod !== null) {
$this->setEncryptionMethod($encryptionMethod);
}
+
if (!empty($this->password)) {
$this->setEncrypted(true);
} else {
$this->disableEncryption();
}
+
return $this;
}
@@ -699,20 +753,22 @@ abstract class ZipAbstractEntry implements ZipEntry
}
/**
- * Set encryption method
+ * Set encryption method.
*
+ * @param int $encryptionMethod
+ *
+ * @throws ZipException
+ *
+ * @return ZipEntry
+ *
+ * @see ZipFileInterface::ENCRYPTION_METHOD_WINZIP_AES_256
* @see ZipFileInterface::ENCRYPTION_METHOD_TRADITIONAL
* @see ZipFileInterface::ENCRYPTION_METHOD_WINZIP_AES_128
* @see ZipFileInterface::ENCRYPTION_METHOD_WINZIP_AES_192
- * @see ZipFileInterface::ENCRYPTION_METHOD_WINZIP_AES_256
- *
- * @param int $encryptionMethod
- * @return ZipEntry
- * @throws ZipException
*/
public function setEncryptionMethod($encryptionMethod)
{
- if (null !== $encryptionMethod) {
+ if ($encryptionMethod !== null) {
if (
$encryptionMethod !== ZipFileInterface::ENCRYPTION_METHOD_TRADITIONAL
&& $encryptionMethod !== ZipFileInterface::ENCRYPTION_METHOD_WINZIP_AES_128
@@ -723,6 +779,7 @@ abstract class ZipAbstractEntry implements ZipEntry
}
$this->encryptionMethod = $encryptionMethod;
}
+
return $this;
}
@@ -736,6 +793,7 @@ abstract class ZipAbstractEntry implements ZipEntry
/**
* @param int $compressionLevel
+ *
* @return ZipEntry
*/
public function setCompressionLevel($compressionLevel = ZipFileInterface::LEVEL_DEFAULT_COMPRESSION)
@@ -743,15 +801,18 @@ abstract class ZipAbstractEntry implements ZipEntry
if ($compressionLevel < ZipFileInterface::LEVEL_DEFAULT_COMPRESSION ||
$compressionLevel > ZipFileInterface::LEVEL_BEST_COMPRESSION
) {
- throw new InvalidArgumentException('Invalid compression level. Minimum level ' .
- ZipFileInterface::LEVEL_DEFAULT_COMPRESSION . '. Maximum level ' . ZipFileInterface::LEVEL_BEST_COMPRESSION);
+ throw new InvalidArgumentException(
+ 'Invalid compression level. Minimum level ' .
+ ZipFileInterface::LEVEL_DEFAULT_COMPRESSION . '. Maximum level ' . ZipFileInterface::LEVEL_BEST_COMPRESSION
+ );
}
$this->compressionLevel = $compressionLevel;
+
return $this;
}
/**
- * Clone extra fields
+ * Clone extra fields.
*/
public function __clone()
{
diff --git a/src/PhpZip/Model/Entry/ZipChangesEntry.php b/src/PhpZip/Model/Entry/ZipChangesEntry.php
index 17e8144..f2f1b46 100644
--- a/src/PhpZip/Model/Entry/ZipChangesEntry.php
+++ b/src/PhpZip/Model/Entry/ZipChangesEntry.php
@@ -2,26 +2,27 @@
namespace PhpZip\Model\Entry;
+use PhpZip\Exception\InvalidArgumentException;
use PhpZip\Exception\ZipException;
/**
- * Source Entry Changes
+ * Source Entry Changes.
*
* @author Ne-Lexa alexey@nelexa.ru
* @license MIT
*/
class ZipChangesEntry extends ZipAbstractEntry
{
- /**
- * @var ZipSourceEntry
- */
+ /** @var ZipSourceEntry */
protected $entry;
/**
* ZipChangesEntry constructor.
+ *
* @param ZipSourceEntry $entry
+ *
* @throws ZipException
- * @throws \PhpZip\Exception\InvalidArgumentException
+ * @throws InvalidArgumentException
*/
public function __construct(ZipSourceEntry $entry)
{
@@ -47,8 +48,9 @@ class ZipChangesEntry extends ZipAbstractEntry
/**
* Returns an string content of the given entry.
*
- * @return null|string
* @throws ZipException
+ *
+ * @return string|null
*/
public function getEntryContent()
{
diff --git a/src/PhpZip/Model/Entry/ZipNewEntry.php b/src/PhpZip/Model/Entry/ZipNewEntry.php
index 57074f9..2f8a3f8 100644
--- a/src/PhpZip/Model/Entry/ZipNewEntry.php
+++ b/src/PhpZip/Model/Entry/ZipNewEntry.php
@@ -11,23 +11,22 @@ use PhpZip\ZipFileInterface;
*/
class ZipNewEntry extends ZipAbstractEntry
{
- /**
- * @var resource|string|null
- */
+ /** @var resource|string|null */
protected $content;
- /**
- * @var bool
- */
+
+ /** @var bool */
private $clone = false;
/**
* ZipNewEntry constructor.
+ *
* @param string|resource|null $content
*/
public function __construct($content = null)
{
parent::__construct();
- if ($content !== null && !is_string($content) && !is_resource($content)) {
+
+ if ($content !== null && !\is_string($content) && !\is_resource($content)) {
throw new InvalidArgumentException('invalid content');
}
$this->content = $content;
@@ -36,16 +35,18 @@ class ZipNewEntry extends ZipAbstractEntry
/**
* Returns an string content of the given entry.
*
- * @return null|string
+ * @return string|null
*/
public function getEntryContent()
{
- if (is_resource($this->content)) {
+ if (\is_resource($this->content)) {
if (stream_get_meta_data($this->content)['seekable']) {
rewind($this->content);
}
+
return stream_get_contents($this->content);
}
+
return $this->content;
}
@@ -57,18 +58,19 @@ class ZipNewEntry extends ZipAbstractEntry
public function getVersionNeededToExtract()
{
$method = $this->getMethod();
- return self::METHOD_WINZIP_AES === $method ? 51 :
+
+ return $method === self::METHOD_WINZIP_AES ? 51 :
(
- ZipFileInterface::METHOD_BZIP2 === $method ? 46 :
+ $method === ZipFileInterface::METHOD_BZIP2 ? 46 :
(
- $this->isZip64ExtensionsRequired() ? 45 :
- (ZipFileInterface::METHOD_DEFLATED === $method || $this->isDirectory() ? 20 : 10)
+ $this->isZip64ExtensionsRequired() ? 45 :
+ ($method === ZipFileInterface::METHOD_DEFLATED || $this->isDirectory() ? 20 : 10)
)
);
}
/**
- * Clone extra fields
+ * Clone extra fields.
*/
public function __clone()
{
@@ -78,7 +80,7 @@ class ZipNewEntry extends ZipAbstractEntry
public function __destruct()
{
- if (!$this->clone && $this->content !== null && is_resource($this->content)) {
+ if (!$this->clone && $this->content !== null && \is_resource($this->content)) {
fclose($this->content);
$this->content = null;
}
diff --git a/src/PhpZip/Model/Entry/ZipNewFileEntry.php b/src/PhpZip/Model/Entry/ZipNewFileEntry.php
index 3c1335c..7a2bead 100644
--- a/src/PhpZip/Model/Entry/ZipNewFileEntry.php
+++ b/src/PhpZip/Model/Entry/ZipNewFileEntry.php
@@ -12,28 +12,31 @@ use PhpZip\Exception\ZipException;
*/
class ZipNewFileEntry extends ZipAbstractEntry
{
- /**
- * @var string Filename
- */
+ /** @var string Filename */
protected $file;
/**
* ZipNewEntry constructor.
+ *
* @param string $file
+ *
* @throws ZipException
*/
public function __construct($file)
{
parent::__construct();
+
if ($file === null) {
- throw new InvalidArgumentException("file is null");
+ throw new InvalidArgumentException('file is null');
}
- $file = (string)$file;
+ $file = (string) $file;
+
if (!is_file($file)) {
- throw new ZipException("File $file does not exist.");
+ throw new ZipException("File {$file} does not exist.");
}
+
if (!is_readable($file)) {
- throw new ZipException("The '$file' file could not be read. Check permissions.");
+ throw new ZipException("The '{$file}' file could not be read. Check permissions.");
}
$this->file = $file;
}
@@ -41,13 +44,14 @@ class ZipNewFileEntry extends ZipAbstractEntry
/**
* Returns an string content of the given entry.
*
- * @return null|string
+ * @return string|null
*/
public function getEntryContent()
{
if (!is_file($this->file)) {
throw new RuntimeException("File {$this->file} does not exist.");
}
+
return file_get_contents($this->file);
}
}
diff --git a/src/PhpZip/Model/Entry/ZipSourceEntry.php b/src/PhpZip/Model/Entry/ZipSourceEntry.php
index dc80c27..5a992ea 100644
--- a/src/PhpZip/Model/Entry/ZipSourceEntry.php
+++ b/src/PhpZip/Model/Entry/ZipSourceEntry.php
@@ -9,34 +9,27 @@ use PhpZip\Stream\ZipInputStreamInterface;
* This class is used to represent a ZIP file entry.
*
* @see https://pkware.cachefly.net/webdocs/casestudies/APPNOTE.TXT .ZIP File Format Specification
+ *
* @author Ne-Lexa alexey@nelexa.ru
* @license MIT
*/
class ZipSourceEntry extends ZipAbstractEntry
{
- /**
- * Max size cached content in memory.
- */
+ /** Max size cached content in memory. */
const MAX_SIZE_CACHED_CONTENT_IN_MEMORY = 524288; // 512 kb
- /**
- * @var ZipInputStreamInterface
- */
+
+ /** @var ZipInputStreamInterface */
protected $inputStream;
- /**
- * @var string|resource Cached entry content.
- */
+
+ /** @var string|resource cached entry content */
protected $entryContent;
- /**
- * @var string
- */
- protected $readPassword;
- /**
- * @var bool
- */
+
+ /** @var bool */
private $clone = false;
/**
* ZipSourceEntry constructor.
+ *
* @param ZipInputStreamInterface $inputStream
*/
public function __construct(ZipInputStreamInterface $inputStream)
@@ -56,6 +49,8 @@ class ZipSourceEntry extends ZipAbstractEntry
/**
* Returns an string content of the given entry.
*
+ * @throws ZipException
+ *
* @return string
*/
public function getEntryContent()
@@ -63,23 +58,28 @@ class ZipSourceEntry extends ZipAbstractEntry
if ($this->entryContent === null) {
// In order not to unpack again, we cache the content in memory or on disk
$content = $this->inputStream->readEntryContent($this);
+
if ($this->getSize() < self::MAX_SIZE_CACHED_CONTENT_IN_MEMORY) {
$this->entryContent = $content;
} else {
$this->entryContent = fopen('php://temp', 'r+b');
fwrite($this->entryContent, $content);
}
+
return $content;
}
- if (is_resource($this->entryContent)) {
+
+ if (\is_resource($this->entryContent)) {
rewind($this->entryContent);
+
return stream_get_contents($this->entryContent);
}
+
return $this->entryContent;
}
/**
- * Clone extra fields
+ * Clone extra fields.
*/
public function __clone()
{
@@ -89,7 +89,7 @@ class ZipSourceEntry extends ZipAbstractEntry
public function __destruct()
{
- if (!$this->clone && $this->entryContent !== null && is_resource($this->entryContent)) {
+ if (!$this->clone && $this->entryContent !== null && \is_resource($this->entryContent)) {
fclose($this->entryContent);
}
}
diff --git a/src/PhpZip/Model/ZipEntry.php b/src/PhpZip/Model/ZipEntry.php
index 015b4ac..eca9d9d 100644
--- a/src/PhpZip/Model/ZipEntry.php
+++ b/src/PhpZip/Model/ZipEntry.php
@@ -10,26 +10,32 @@ use PhpZip\ZipFileInterface;
* ZIP file entry.
*
* @see https://pkware.cachefly.net/webdocs/casestudies/APPNOTE.TXT .ZIP File Format Specification
+ *
* @author Ne-Lexa alexey@nelexa.ru
* @license MIT
*/
interface ZipEntry
{
// Bit masks for initialized fields.
- const BIT_PLATFORM = 1,
- BIT_METHOD = 2 /* 1 << 1 */,
- BIT_CRC = 4 /* 1 << 2 */,
- BIT_DATE_TIME = 64 /* 1 << 6 */,
- BIT_EXTERNAL_ATTR = 128 /* 1 << 7*/
- ;
+ const BIT_PLATFORM = 1;
+
+ const BIT_METHOD = 2;
+
+ const BIT_CRC = 4;
+
+ const BIT_DATE_TIME = 64;
+
+ const BIT_EXTERNAL_ATTR = 128;
/** The unknown value for numeric properties. */
const UNKNOWN = -1;
/** Windows platform. */
const PLATFORM_FAT = 0;
+
/** Unix platform. */
const PLATFORM_UNIX = 3;
+
/** MacOS platform */
const PLATFORM_OS_X = 19;
@@ -40,7 +46,9 @@ interface ZipEntry
const METHOD_WINZIP_AES = 99;
/** General Purpose Bit Flag mask for encrypted data. */
- const GPBF_ENCRYPTED = 1; // 1 << 0
+ const GPBF_ENCRYPTED = 1;
+
+ // 1 << 0
// (For Methods 8 and 9 - Deflating)
// Bit 2 Bit 1
// 0 0 Normal compression
@@ -48,18 +56,24 @@ interface ZipEntry
// 1 0 Fast compression
// 1 1 Super Fast compression
const GPBF_COMPRESSION_FLAG1 = 2; // 1 << 1
+
const GPBF_COMPRESSION_FLAG2 = 4; // 1 << 2
+
/** General Purpose Bit Flag mask for data descriptor. */
const GPBF_DATA_DESCRIPTOR = 8; // 1 << 3
+
/** General Purpose Bit Flag mask for strong encryption. */
const GPBF_STRONG_ENCRYPTION = 64; // 1 << 6
+
/** General Purpose Bit Flag mask for UTF-8. */
const GPBF_UTF8 = 2048; // 1 << 11
/** Local File Header signature. */
const LOCAL_FILE_HEADER_SIG = 0x04034B50;
+
/** Data Descriptor signature. */
const DATA_DESCRIPTOR_SIG = 0x08074B50;
+
/**
* The minimum length of the Local File Header record.
*
@@ -76,6 +90,7 @@ interface ZipEntry
* extra field length 2
*/
const LOCAL_FILE_HEADER_MIN_LEN = 30;
+
/**
* Local File Header signature 4
* Version Needed To Extract 2
@@ -85,12 +100,11 @@ interface ZipEntry
* Last Mod File Date 2
* CRC-32 4
* Compressed Size 4
- * Uncompressed Size 4
+ * Uncompressed Size 4.
*/
const LOCAL_FILE_HEADER_FILE_NAME_LENGTH_POS = 26;
- /**
- * Default compression level for bzip2
- */
+
+ /** Default compression level for bzip2 */
const LEVEL_DEFAULT_BZIP2_COMPRESSION = 4;
/**
@@ -104,8 +118,10 @@ interface ZipEntry
* Set entry name.
*
* @param string $name New entry name
- * @return ZipEntry
+ *
* @throws ZipException
+ *
+ * @return ZipEntry
*/
public function setName($name);
@@ -115,11 +131,13 @@ interface ZipEntry
public function getPlatform();
/**
- * Set platform
+ * Set platform.
*
* @param int $platform
- * @return ZipEntry
+ *
* @throws ZipException
+ *
+ * @return ZipEntry
*/
public function setPlatform($platform);
@@ -134,6 +152,7 @@ interface ZipEntry
* Set version needed to extract.
*
* @param int $version
+ *
* @return ZipEntry
*/
public function setVersionNeededToExtract($version);
@@ -153,9 +172,11 @@ interface ZipEntry
/**
* Sets the compressed size of this entry.
*
- * @param int $compressedSize The Compressed Size.
- * @return ZipEntry
+ * @param int $compressedSize the Compressed Size
+ *
* @throws ZipException
+ *
+ * @return ZipEntry
*/
public function setCompressedSize($compressedSize);
@@ -169,9 +190,11 @@ interface ZipEntry
/**
* Sets the uncompressed size of this entry.
*
- * @param int $size The (Uncompressed) Size.
- * @return ZipEntry
+ * @param int $size the (Uncompressed) Size
+ *
* @throws ZipException
+ *
+ * @return ZipEntry
*/
public function setSize($size);
@@ -184,8 +207,10 @@ interface ZipEntry
/**
* @param int $offset
- * @return ZipEntry
+ *
* @throws ZipException
+ *
+ * @return ZipEntry
*/
public function setOffset($offset);
@@ -207,9 +232,13 @@ interface ZipEntry
/**
* Sets the General Purpose Bit Flags.
*
- * @var int general
- * @return ZipEntry
+ * @param mixed $general
+ *
* @throws ZipException
+ *
+ * @return ZipEntry
+ *
+ * @var int general
*/
public function setGeneralPurposeBitFlags($general);
@@ -217,6 +246,7 @@ interface ZipEntry
* Returns the indexed General Purpose Bit Flag.
*
* @param int $mask
+ *
* @return bool
*/
public function getGeneralPurposeBitFlag($mask);
@@ -224,8 +254,9 @@ interface ZipEntry
/**
* Sets the indexed General Purpose Bit Flag.
*
- * @param int $mask
+ * @param int $mask
* @param bool $bit
+ *
* @return ZipEntry
*/
public function setGeneralPurposeBitFlag($mask, $bit);
@@ -241,6 +272,7 @@ interface ZipEntry
* Sets the encryption flag for this ZIP entry.
*
* @param bool $encrypted
+ *
* @return ZipEntry
*/
public function setEncrypted($encrypted);
@@ -264,13 +296,15 @@ interface ZipEntry
* Sets the compression method for this entry.
*
* @param int $method
+ *
+ * @throws ZipException if method is not STORED, DEFLATED, BZIP2 or UNKNOWN
+ *
* @return ZipEntry
- * @throws ZipException If method is not STORED, DEFLATED, BZIP2 or UNKNOWN.
*/
public function setMethod($method);
/**
- * Get Unix Timestamp
+ * Get Unix Timestamp.
*
* @return int
*/
@@ -280,20 +314,23 @@ interface ZipEntry
* Set time from unix timestamp.
*
* @param int $unixTimestamp
+ *
* @return ZipEntry
*/
public function setTime($unixTimestamp);
/**
- * Get Dos Time
+ * Get Dos Time.
*
* @return int
*/
public function getDosTime();
/**
- * Set Dos Time
+ * Set Dos Time.
+ *
* @param int $dosTime
+ *
* @throws ZipException
*/
public function setDosTime($dosTime);
@@ -301,16 +338,18 @@ interface ZipEntry
/**
* Returns the external file attributes.
*
- * @return int The external file attributes.
+ * @return int the external file attributes
*/
public function getExternalAttributes();
/**
* Sets the external file attributes.
*
- * @param int $externalAttributes the external file attributes.
- * @return ZipEntry
+ * @param int $externalAttributes the external file attributes
+ *
* @throws ZipException
+ *
+ * @return ZipEntry
*/
public function setExternalAttributes($externalAttributes);
@@ -335,13 +374,14 @@ interface ZipEntry
* (application) data.
* Consider storing such data in a separate entry instead.
*
- * @param string $data The byte array holding the serialized Extra Fields.
+ * @param string $data the byte array holding the serialized Extra Fields
+ *
* @throws ZipException if the serialized Extra Fields exceed 64 KB
*/
public function setExtra($data);
/**
- * Returns comment entry
+ * Returns comment entry.
*
* @return string
*/
@@ -351,6 +391,7 @@ interface ZipEntry
* Set entry comment.
*
* @param $comment
+ *
* @return ZipEntry
*/
public function setComment($comment);
@@ -361,7 +402,7 @@ interface ZipEntry
public function isDataDescriptorRequired();
/**
- * Return crc32 content or 0 for WinZip AES v2
+ * Return crc32 content or 0 for WinZip AES v2.
*
* @return int
*/
@@ -371,8 +412,10 @@ interface ZipEntry
* Set crc32 content.
*
* @param int $crc
- * @return ZipEntry
+ *
* @throws ZipException
+ *
+ * @return ZipEntry
*/
public function setCrc($crc);
@@ -382,10 +425,11 @@ interface ZipEntry
public function getPassword();
/**
- * Set password and encryption method from entry
+ * Set password and encryption method from entry.
+ *
+ * @param string $password
+ * @param int|null $encryptionMethod
*
- * @param string $password
- * @param null|int $encryptionMethod
* @return ZipEntry
*/
public function setPassword($password, $encryptionMethod = null);
@@ -396,29 +440,33 @@ interface ZipEntry
public function getEncryptionMethod();
/**
- * Set encryption method
+ * Set encryption method.
*
+ * @param int $encryptionMethod
+ *
+ * @throws ZipException
+ *
+ * @return ZipEntry
+ *
+ * @see ZipFileInterface::ENCRYPTION_METHOD_WINZIP_AES_256
* @see ZipFileInterface::ENCRYPTION_METHOD_TRADITIONAL
* @see ZipFileInterface::ENCRYPTION_METHOD_WINZIP_AES_128
* @see ZipFileInterface::ENCRYPTION_METHOD_WINZIP_AES_192
- * @see ZipFileInterface::ENCRYPTION_METHOD_WINZIP_AES_256
- *
- * @param int $encryptionMethod
- * @return ZipEntry
- * @throws ZipException
*/
public function setEncryptionMethod($encryptionMethod);
/**
* Returns an string content of the given entry.
*
- * @return null|string
* @throws ZipException
+ *
+ * @return string|null
*/
public function getEntryContent();
/**
* @param int $compressionLevel
+ *
* @return ZipEntry
*/
public function setCompressionLevel($compressionLevel = ZipFileInterface::LEVEL_DEFAULT_COMPRESSION);
diff --git a/src/PhpZip/Model/ZipEntryMatcher.php b/src/PhpZip/Model/ZipEntryMatcher.php
index 0c99138..4ff484f 100644
--- a/src/PhpZip/Model/ZipEntryMatcher.php
+++ b/src/PhpZip/Model/ZipEntryMatcher.php
@@ -8,18 +8,15 @@ namespace PhpZip\Model;
*/
class ZipEntryMatcher implements \Countable
{
- /**
- * @var ZipModel
- */
+ /** @var ZipModel */
protected $zipModel;
- /**
- * @var array
- */
+ /** @var array */
protected $matches = [];
/**
* ZipEntryMatcher constructor.
+ *
* @param ZipModel $zipModel
*/
public function __construct(ZipModel $zipModel)
@@ -29,44 +26,59 @@ class ZipEntryMatcher implements \Countable
/**
* @param string|array $entries
+ *
* @return ZipEntryMatcher
*/
public function add($entries)
{
- $entries = (array)$entries;
- $entries = array_map(function ($entry) {
- return $entry instanceof ZipEntry ? $entry->getName() : $entry;
- }, $entries);
- $this->matches = array_unique(
- array_merge(
- $this->matches,
- array_keys(
- array_intersect_key(
- $this->zipModel->getEntries(),
- array_flip($entries)
+ $entries = (array) $entries;
+ $entries = array_map(
+ static function ($entry) {
+ return $entry instanceof ZipEntry ? $entry->getName() : (string) $entry;
+ },
+ $entries
+ );
+ $this->matches = array_values(
+ array_map(
+ 'strval',
+ array_unique(
+ array_merge(
+ $this->matches,
+ array_keys(
+ array_intersect_key(
+ $this->zipModel->getEntries(),
+ array_flip($entries)
+ )
+ )
)
)
)
);
+
return $this;
}
/**
* @param string $regexp
+ *
* @return ZipEntryMatcher
*/
public function match($regexp)
{
- array_walk($this->zipModel->getEntries(), function (
- /** @noinspection PhpUnusedParameterInspection */
- $entry,
- $entryName
- ) use ($regexp) {
- if (preg_match($regexp, $entryName)) {
- $this->matches[] = $entryName;
+ array_walk(
+ $this->zipModel->getEntries(),
+ function (
+ /** @noinspection PhpUnusedParameterInspection */
+ $entry,
+ $entryName
+ ) use ($regexp) {
+ if (preg_match($regexp, $entryName)) {
+ $this->matches[] = (string) $entryName;
+ }
}
- });
+ );
$this->matches = array_unique($this->matches);
+
return $this;
}
@@ -76,6 +88,7 @@ class ZipEntryMatcher implements \Countable
public function all()
{
$this->matches = array_keys($this->zipModel->getEntries());
+
return $this;
}
@@ -90,9 +103,12 @@ class ZipEntryMatcher implements \Countable
public function invoke(callable $callable)
{
if (!empty($this->matches)) {
- array_walk($this->matches, function ($entryName) use ($callable) {
- call_user_func($callable, $entryName);
- });
+ array_walk(
+ $this->matches,
+ static function ($entryName) use ($callable) {
+ $callable($entryName);
+ }
+ );
}
}
@@ -106,24 +122,31 @@ class ZipEntryMatcher implements \Countable
public function delete()
{
- array_walk($this->matches, function ($entry) {
- $this->zipModel->deleteEntry($entry);
- });
+ array_walk(
+ $this->matches,
+ function ($entry) {
+ $this->zipModel->deleteEntry($entry);
+ }
+ );
$this->matches = [];
}
/**
* @param string|null $password
- * @param int|null $encryptionMethod
+ * @param int|null $encryptionMethod
*/
public function setPassword($password, $encryptionMethod = null)
{
- array_walk($this->matches, function ($entry) use ($password, $encryptionMethod) {
- $entry = $this->zipModel->getEntry($entry);
- if (!$entry->isDirectory()) {
- $this->zipModel->getEntryForChanges($entry)->setPassword($password, $encryptionMethod);
+ array_walk(
+ $this->matches,
+ function ($entry) use ($password, $encryptionMethod) {
+ $entry = $this->zipModel->getEntry($entry);
+
+ if (!$entry->isDirectory()) {
+ $this->zipModel->getEntryForChanges($entry)->setPassword($password, $encryptionMethod);
+ }
}
- });
+ );
}
/**
@@ -131,36 +154,47 @@ class ZipEntryMatcher implements \Countable
*/
public function setEncryptionMethod($encryptionMethod)
{
- array_walk($this->matches, function ($entry) use ($encryptionMethod) {
- $entry = $this->zipModel->getEntry($entry);
- if (!$entry->isDirectory()) {
- $this->zipModel->getEntryForChanges($entry)->setEncryptionMethod($encryptionMethod);
+ array_walk(
+ $this->matches,
+ function ($entry) use ($encryptionMethod) {
+ $entry = $this->zipModel->getEntry($entry);
+
+ if (!$entry->isDirectory()) {
+ $this->zipModel->getEntryForChanges($entry)->setEncryptionMethod($encryptionMethod);
+ }
}
- });
+ );
}
public function disableEncryption()
{
- array_walk($this->matches, function ($entry) {
- $entry = $this->zipModel->getEntry($entry);
- if (!$entry->isDirectory()) {
- $entry = $this->zipModel->getEntryForChanges($entry);
- $entry->disableEncryption();
+ array_walk(
+ $this->matches,
+ function ($entry) {
+ $entry = $this->zipModel->getEntry($entry);
+
+ if (!$entry->isDirectory()) {
+ $entry = $this->zipModel->getEntryForChanges($entry);
+ $entry->disableEncryption();
+ }
}
- });
+ );
}
/**
- * Count elements of an object
- * @link http://php.net/manual/en/countable.count.php
+ * Count elements of an object.
+ *
+ * @see http://php.net/manual/en/countable.count.php
+ *
* @return int The custom count as an integer.
- *
- *
- * The return value is cast to an integer.
+ *
+ *
+ * The return value is cast to an integer.
+ *
* @since 5.1.0
*/
public function count()
{
- return count($this->matches);
+ return \count($this->matches);
}
}
diff --git a/src/PhpZip/Model/ZipInfo.php b/src/PhpZip/Model/ZipInfo.php
index 4fbb608..234a849 100644
--- a/src/PhpZip/Model/ZipInfo.php
+++ b/src/PhpZip/Model/ZipInfo.php
@@ -1,14 +1,15 @@
- 'FAT',
@@ -113,80 +157,63 @@ class ZipInfo
ZipEntry::METHOD_WINZIP_AES => 'WinZip AES',
];
- /**
- * @var string
- */
+ /** @var string */
private $name;
- /**
- * @var bool
- */
+
+ /** @var bool */
private $folder;
- /**
- * @var int
- */
+
+ /** @var int */
private $size;
- /**
- * @var int
- */
+
+ /** @var int */
private $compressedSize;
- /**
- * @var int
- */
+
+ /** @var int */
private $mtime;
- /**
- * @var int|null
- */
+
+ /** @var int|null */
private $ctime;
- /**
- * @var int|null
- */
+
+ /** @var int|null */
private $atime;
- /**
- * @var bool
- */
+
+ /** @var bool */
private $encrypted;
- /**
- * @var string|null
- */
+
+ /** @var string|null */
private $comment;
- /**
- * @var int
- */
+
+ /** @var int */
private $crc;
- /**
- * @var string
- */
+
+ /** @var string */
private $methodName;
- /**
- * @var int
- */
+
+ /** @var int */
private $compressionMethod;
- /**
- * @var string
- */
+
+ /** @var string */
private $platform;
- /**
- * @var int
- */
+
+ /** @var int */
private $version;
- /**
- * @var string
- */
+
+ /** @var string */
private $attributes;
- /**
- * @var int|null
- */
+
+ /** @var int|null */
private $encryptionMethod;
- /**
- * @var int|null
- */
+
+ /** @var int|null */
private $compressionLevel;
/**
* ZipInfo constructor.
*
* @param ZipEntry $entry
- * @throws \PhpZip\Exception\ZipException
+ *
+ * @throws ZipException
*/
public function __construct(ZipEntry $entry)
{
@@ -195,7 +222,8 @@ class ZipInfo
$ctime = null;
$field = $entry->getExtraFieldsCollection()->get(NtfsExtraField::getHeaderId());
- if (null !== $field && $field instanceof NtfsExtraField) {
+
+ if ($field instanceof NtfsExtraField) {
/**
* @var NtfsExtraField $field
*/
@@ -206,10 +234,10 @@ class ZipInfo
$this->name = $entry->getName();
$this->folder = $entry->isDirectory();
- $this->size = PHP_INT_SIZE === 4 ?
+ $this->size = \PHP_INT_SIZE === 4 ?
sprintf('%u', $entry->getSize()) :
$entry->getSize();
- $this->compressedSize = PHP_INT_SIZE === 4 ?
+ $this->compressedSize = \PHP_INT_SIZE === 4 ?
sprintf('%u', $entry->getCompressedSize()) :
$entry->getCompressedSize();
$this->mtime = $mtime;
@@ -225,65 +253,74 @@ class ZipInfo
$this->version = $entry->getVersionNeededToExtract();
$this->compressionLevel = $entry->getCompressionLevel();
- $attributes = str_repeat(" ", 12);
+ $attributes = str_repeat(' ', 12);
$externalAttributes = $entry->getExternalAttributes();
- $externalAttributes = PHP_INT_SIZE === 4 ?
+ $externalAttributes = \PHP_INT_SIZE === 4 ?
sprintf('%u', $externalAttributes) :
$externalAttributes;
$xattr = (($externalAttributes >> 16) & 0xFFFF);
switch ($entry->getPlatform()) {
case self::MADE_BY_MS_DOS:
case self::MADE_BY_WINDOWS_NTFS:
- if ($entry->getPlatform() != self::MADE_BY_MS_DOS ||
- ($xattr & 0700) !=
+ if ($entry->getPlatform() !== self::MADE_BY_MS_DOS ||
+ ($xattr & 0700) !==
(0400 |
(!($externalAttributes & 1) << 7) |
(($externalAttributes & 0x10) << 2))
) {
$xattr = $externalAttributes & 0xFF;
- $attributes = ".r.-... ";
+ $attributes = '.r.-... ';
$attributes[2] = ($xattr & 0x01) ? '-' : 'w';
$attributes[5] = ($xattr & 0x02) ? 'h' : '-';
$attributes[6] = ($xattr & 0x04) ? 's' : '-';
$attributes[4] = ($xattr & 0x20) ? 'a' : '-';
+
if ($xattr & 0x10) {
$attributes[0] = 'd';
$attributes[3] = 'x';
} else {
$attributes[0] = '-';
}
+
if ($xattr & 0x08) {
$attributes[0] = 'V';
} else {
- $ext = strtolower(pathinfo($entry->getName(), PATHINFO_EXTENSION));
- if (in_array($ext, ["com", "exe", "btm", "cmd", "bat"])) {
+ $ext = strtolower(pathinfo($entry->getName(), \PATHINFO_EXTENSION));
+
+ if (\in_array($ext, ['com', 'exe', 'btm', 'cmd', 'bat'])) {
$attributes[3] = 'x';
}
}
break;
- } /* else: fall through! */
+ } // else: fall through!
// no break
- default: /* assume Unix-like */
+ default: // assume Unix-like
switch ($xattr & self::UNX_IFMT) {
case self::UNX_IFDIR:
$attributes[0] = 'd';
break;
+
case self::UNX_IFREG:
$attributes[0] = '-';
break;
+
case self::UNX_IFLNK:
$attributes[0] = 'l';
break;
+
case self::UNX_IFBLK:
$attributes[0] = 'b';
break;
+
case self::UNX_IFCHR:
$attributes[0] = 'c';
break;
+
case self::UNX_IFIFO:
$attributes[0] = 'p';
break;
+
case self::UNX_IFSOCK:
$attributes[0] = 's';
break;
@@ -302,68 +339,75 @@ class ZipInfo
$attributes[3] = ($xattr & self::UNX_ISUID) ? 's' : 'x';
} else {
$attributes[3] = ($xattr & self::UNX_ISUID) ? 'S' : '-';
- } /* S==undefined */
+ } // S==undefined
if ($xattr & self::UNX_IXGRP) {
$attributes[6] = ($xattr & self::UNX_ISGID) ? 's' : 'x';
- } /* == UNX_ENFMT */
+ } // == UNX_ENFMT
else {
$attributes[6] = ($xattr & self::UNX_ISGID) ? 'S' : '-';
- } /* SunOS 4.1.x */
+ } // SunOS 4.1.x
if ($xattr & self::UNX_IXOTH) {
$attributes[9] = ($xattr & self::UNX_ISVTX) ? 't' : 'x';
- } /* "sticky bit" */
+ } // "sticky bit"
else {
$attributes[9] = ($xattr & self::UNX_ISVTX) ? 'T' : '-';
- } /* T==undefined */
+ } // T==undefined
}
$this->attributes = trim($attributes);
}
/**
* @param ZipEntry $entry
+ *
+ * @throws ZipException
+ *
* @return int
- * @throws \PhpZip\Exception\ZipException
*/
private static function getMethodId(ZipEntry $entry)
{
$method = $entry->getMethod();
- if ($entry->isEncrypted()) {
- if ($entry->getMethod() === ZipEntry::METHOD_WINZIP_AES) {
- $field = $entry->getExtraFieldsCollection()->get(WinZipAesEntryExtraField::getHeaderId());
- if (null !== $field) {
- /**
- * @var WinZipAesEntryExtraField $field
- */
- $method = $field->getMethod();
- }
+
+ if ($entry->isEncrypted() && $entry->getMethod() === ZipEntry::METHOD_WINZIP_AES) {
+ $field = $entry->getExtraFieldsCollection()->get(WinZipAesEntryExtraField::getHeaderId());
+
+ if ($field !== null) {
+ /**
+ * @var WinZipAesEntryExtraField $field
+ */
+ $method = $field->getMethod();
}
}
+
return $method;
}
/**
* @param ZipEntry $entry
+ *
+ * @throws ZipException
+ *
* @return string
- * @throws \PhpZip\Exception\ZipException
*/
private static function getEntryMethodName(ZipEntry $entry)
{
$return = '';
+
if ($entry->isEncrypted()) {
if ($entry->getMethod() === ZipEntry::METHOD_WINZIP_AES) {
$return = ucfirst(self::$valuesCompressionMethod[$entry->getMethod()]);
+ /** @var WinZipAesEntryExtraField|null $field */
$field = $entry->getExtraFieldsCollection()->get(WinZipAesEntryExtraField::getHeaderId());
- if (null !== $field) {
- /**
- * @var WinZipAesEntryExtraField $field
- */
+
+ if ($field !== null) {
$return .= '-' . $field->getKeyStrength();
+
if (isset(self::$valuesCompressionMethod[$field->getMethod()])) {
$return .= ' ' . ucfirst(self::$valuesCompressionMethod[$field->getMethod()]);
}
}
} else {
$return .= 'ZipCrypto';
+
if (isset(self::$valuesCompressionMethod[$entry->getMethod()])) {
$return .= ' ' . ucfirst(self::$valuesCompressionMethod[$entry->getMethod()]);
}
@@ -373,20 +417,22 @@ class ZipInfo
} else {
$return = 'unknown';
}
+
return $return;
}
/**
* @param ZipEntry $entry
+ *
* @return string
*/
public static function getPlatformName(ZipEntry $entry)
{
if (isset(self::$valuesMadeBy[$entry->getPlatform()])) {
return self::$valuesMadeBy[$entry->getPlatform()];
- } else {
- return 'unknown';
}
+
+ return 'unknown';
}
/**
@@ -399,6 +445,7 @@ class ZipInfo
/**
* @return string
+ *
* @deprecated use \PhpZip\Model\ZipInfo::getName()
*/
public function getPath()
@@ -407,7 +454,7 @@ class ZipInfo
}
/**
- * @return boolean
+ * @return bool
*/
public function isFolder()
{
@@ -463,7 +510,7 @@ class ZipInfo
}
/**
- * @return boolean
+ * @return bool
*/
public function isEncrypted()
{
@@ -471,7 +518,7 @@ class ZipInfo
}
/**
- * @return null|string
+ * @return string|null
*/
public function getComment()
{
@@ -488,6 +535,7 @@ class ZipInfo
/**
* @return string
+ *
* @deprecated use \PhpZip\Model\ZipInfo::getMethodName()
*/
public function getMethod()
@@ -566,7 +614,7 @@ class ZipInfo
'method_name' => $this->getMethodName(),
'compression_method' => $this->getCompressionMethod(),
'platform' => $this->getPlatform(),
- 'version' => $this->getVersion()
+ 'version' => $this->getVersion(),
];
}
@@ -580,9 +628,9 @@ class ZipInfo
. ($this->isFolder() ? 'Folder, ' : '')
. 'Size="' . FilesUtil::humanSize($this->getSize()) . '"'
. ', Compressed size="' . FilesUtil::humanSize($this->getCompressedSize()) . '"'
- . ', Modified time="' . date(DATE_W3C, $this->getMtime()) . '", '
- . ($this->getCtime() !== null ? 'Created time="' . date(DATE_W3C, $this->getCtime()) . '", ' : '')
- . ($this->getAtime() !== null ? 'Accessed time="' . date(DATE_W3C, $this->getAtime()) . '", ' : '')
+ . ', Modified time="' . date(\DATE_W3C, $this->getMtime()) . '", '
+ . ($this->getCtime() !== null ? 'Created time="' . date(\DATE_W3C, $this->getCtime()) . '", ' : '')
+ . ($this->getAtime() !== null ? 'Accessed time="' . date(\DATE_W3C, $this->getAtime()) . '", ' : '')
. ($this->isEncrypted() ? 'Encrypted, ' : '')
. (!empty($this->comment) ? 'Comment="' . $this->getComment() . '", ' : '')
. (!empty($this->crc) ? 'Crc=0x' . dechex($this->getCrc()) . ', ' : '')
diff --git a/src/PhpZip/Model/ZipModel.php b/src/PhpZip/Model/ZipModel.php
index 49d2d0c..39fb999 100644
--- a/src/PhpZip/Model/ZipModel.php
+++ b/src/PhpZip/Model/ZipModel.php
@@ -10,65 +10,60 @@ use PhpZip\Model\Entry\ZipSourceEntry;
use PhpZip\ZipFileInterface;
/**
- * Zip Model
+ * Zip Model.
*
* @author Ne-Lexa alexey@nelexa.ru
* @license MIT
*/
class ZipModel implements \Countable
{
- /**
- * @var ZipSourceEntry[]
- */
+ /** @var ZipSourceEntry[] */
protected $inputEntries = [];
- /**
- * @var ZipEntry[]
- */
+
+ /** @var ZipEntry[] */
protected $outEntries = [];
- /**
- * @var string|null
- */
+
+ /** @var string|null */
protected $archiveComment;
- /**
- * @var string|null
- */
+
+ /** @var string|null */
protected $archiveCommentChanges;
- /**
- * @var bool
- */
+
+ /** @var bool */
protected $archiveCommentChanged = false;
- /**
- * @var int|null
- */
+
+ /** @var int|null */
protected $zipAlign;
- /**
- * @var bool
- */
+
+ /** @var bool */
private $zip64;
/**
- * @param ZipSourceEntry[] $entries
+ * @param ZipSourceEntry[] $entries
* @param EndOfCentralDirectory $endOfCentralDirectory
+ *
* @return ZipModel
*/
public static function newSourceModel(array $entries, EndOfCentralDirectory $endOfCentralDirectory)
{
- $model = new self;
+ $model = new self();
$model->inputEntries = $entries;
$model->outEntries = $entries;
$model->archiveComment = $endOfCentralDirectory->getComment();
$model->zip64 = $endOfCentralDirectory->isZip64();
+
return $model;
}
/**
- * @return null|string
+ * @return string|null
*/
public function getArchiveComment()
{
if ($this->archiveCommentChanged) {
return $this->archiveCommentChanges;
}
+
return $this->archiveComment;
}
@@ -77,13 +72,15 @@ class ZipModel implements \Countable
*/
public function setArchiveComment($comment)
{
- if ($comment !== null && strlen($comment) !== 0) {
- $comment = (string)$comment;
- $length = strlen($comment);
- if (0x0000 > $length || $length > 0xffff) {
+ if ($comment !== null && $comment !== '') {
+ $comment = (string) $comment;
+ $length = \strlen($comment);
+
+ if ($length > 0xffff) {
throw new InvalidArgumentException('Length comment out of range');
}
}
+
if ($comment !== $this->archiveComment) {
$this->archiveCommentChanges = $comment;
$this->archiveCommentChanged = true;
@@ -95,7 +92,8 @@ class ZipModel implements \Countable
/**
* Specify a password for extracting files.
*
- * @param null|string $password
+ * @param string|null $password
+ *
* @throws ZipException
*/
public function setReadPassword($password)
@@ -110,6 +108,7 @@ class ZipModel implements \Countable
/**
* @param string $entryName
* @param string $password
+ *
* @throws ZipEntryNotFoundException
* @throws ZipException
*/
@@ -118,6 +117,7 @@ class ZipModel implements \Countable
if (!isset($this->inputEntries[$entryName])) {
throw new ZipEntryNotFoundException($entryName);
}
+
if ($this->inputEntries[$entryName]->isEncrypted()) {
$this->inputEntries[$entryName]->setPassword($password);
}
@@ -136,7 +136,7 @@ class ZipModel implements \Countable
*/
public function setZipAlign($zipAlign)
{
- $this->zipAlign = $zipAlign === null ? null : (int)$zipAlign;
+ $this->zipAlign = $zipAlign === null ? null : (int) $zipAlign;
}
/**
@@ -144,11 +144,11 @@ class ZipModel implements \Countable
*/
public function isZipAlign()
{
- return $this->zipAlign != null;
+ return $this->zipAlign !== null;
}
/**
- * @param null|string $writePassword
+ * @param string|null $writePassword
*/
public function setWritePassword($writePassword)
{
@@ -156,7 +156,7 @@ class ZipModel implements \Countable
}
/**
- * Remove password
+ * Remove password.
*/
public function removePassword()
{
@@ -182,15 +182,16 @@ class ZipModel implements \Countable
/**
* @param string|ZipEntry $old
* @param string|ZipEntry $new
+ *
* @throws ZipException
*/
public function renameEntry($old, $new)
{
- $old = $old instanceof ZipEntry ? $old->getName() : (string)$old;
- $new = $new instanceof ZipEntry ? $new->getName() : (string)$new;
+ $old = $old instanceof ZipEntry ? $old->getName() : (string) $old;
+ $new = $new instanceof ZipEntry ? $new->getName() : (string) $new;
if (isset($this->outEntries[$new])) {
- throw new InvalidArgumentException("New entry name " . $new . ' is exists.');
+ throw new InvalidArgumentException('New entry name ' . $new . ' is exists.');
}
$entry = $this->getEntryForChanges($old);
@@ -201,45 +202,57 @@ class ZipModel implements \Countable
/**
* @param string|ZipEntry $entry
- * @return ZipChangesEntry|ZipEntry
+ *
* @throws ZipException
* @throws ZipEntryNotFoundException
+ *
+ * @return ZipChangesEntry|ZipEntry
*/
public function getEntryForChanges($entry)
{
$entry = $this->getEntry($entry);
+
if ($entry instanceof ZipSourceEntry) {
$entry = new ZipChangesEntry($entry);
$this->addEntry($entry);
}
+
return $entry;
}
/**
* @param string|ZipEntry $entryName
- * @return ZipEntry
+ *
* @throws ZipEntryNotFoundException
+ *
+ * @return ZipEntry
*/
public function getEntry($entryName)
{
- $entryName = $entryName instanceof ZipEntry ? $entryName->getName() : (string)$entryName;
+ $entryName = $entryName instanceof ZipEntry ? $entryName->getName() : (string) $entryName;
+
if (isset($this->outEntries[$entryName])) {
return $this->outEntries[$entryName];
}
+
throw new ZipEntryNotFoundException($entryName);
}
/**
* @param string|ZipEntry $entry
+ *
* @return bool
*/
public function deleteEntry($entry)
{
- $entry = $entry instanceof ZipEntry ? $entry->getName() : (string)$entry;
+ $entry = $entry instanceof ZipEntry ? $entry->getName() : (string) $entry;
+
if (isset($this->outEntries[$entry])) {
unset($this->outEntries[$entry]);
+
return true;
}
+
return false;
}
@@ -263,11 +276,13 @@ class ZipModel implements \Countable
/**
* @param string|ZipEntry $entryName
+ *
* @return bool
*/
public function hasEntry($entryName)
{
- $entryName = $entryName instanceof ZipEntry ? $entryName->getName() : (string)$entryName;
+ $entryName = $entryName instanceof ZipEntry ? $entryName->getName() : (string) $entryName;
+
return isset($this->outEntries[$entryName]);
}
@@ -280,21 +295,24 @@ class ZipModel implements \Countable
}
/**
- * Count elements of an object
- * @link http://php.net/manual/en/countable.count.php
+ * Count elements of an object.
+ *
+ * @see http://php.net/manual/en/countable.count.php
+ *
* @return int The custom count as an integer.
- *
- *
- * The return value is cast to an integer.
+ *
+ *
+ * The return value is cast to an integer.
+ *
* @since 5.1.0
*/
public function count()
{
- return sizeof($this->outEntries);
+ return \count($this->outEntries);
}
/**
- * Undo all changes done in the archive
+ * Undo all changes done in the archive.
*/
public function unchangeAll()
{
@@ -303,7 +321,7 @@ class ZipModel implements \Countable
}
/**
- * Undo change archive comment
+ * Undo change archive comment.
*/
public function unchangeArchiveComment()
{
@@ -315,15 +333,19 @@ class ZipModel implements \Countable
* Revert all changes done to an entry with the given name.
*
* @param string|ZipEntry $entry Entry name or ZipEntry
+ *
* @return bool
*/
public function unchangeEntry($entry)
{
- $entry = $entry instanceof ZipEntry ? $entry->getName() : (string)$entry;
- if (isset($this->outEntries[$entry]) && isset($this->inputEntries[$entry])) {
+ $entry = $entry instanceof ZipEntry ? $entry->getName() : (string) $entry;
+
+ if (isset($this->outEntries[$entry], $this->inputEntries[$entry])) {
$this->outEntries[$entry] = $this->inputEntries[$entry];
+
return true;
}
+
return false;
}
diff --git a/src/PhpZip/Stream/ResponseStream.php b/src/PhpZip/Stream/ResponseStream.php
index 172de1e..0f37f4b 100644
--- a/src/PhpZip/Stream/ResponseStream.php
+++ b/src/PhpZip/Stream/ResponseStream.php
@@ -5,59 +5,77 @@ namespace PhpZip\Stream;
use Psr\Http\Message\StreamInterface;
/**
- * Implement PSR Message Stream
+ * Implement PSR Message Stream.
*/
class ResponseStream implements StreamInterface
{
- /**
- * @var array
- */
+ /** @var array */
private static $readWriteHash = [
'read' => [
- 'r' => true, 'w+' => true, 'r+' => true, 'x+' => true, 'c+' => true,
- 'rb' => true, 'w+b' => true, 'r+b' => true, 'x+b' => true,
- 'c+b' => true, 'rt' => true, 'w+t' => true, 'r+t' => true,
- 'x+t' => true, 'c+t' => true, 'a+' => true,
+ 'r' => true,
+ 'w+' => true,
+ 'r+' => true,
+ 'x+' => true,
+ 'c+' => true,
+ 'rb' => true,
+ 'w+b' => true,
+ 'r+b' => true,
+ 'x+b' => true,
+ 'c+b' => true,
+ 'rt' => true,
+ 'w+t' => true,
+ 'r+t' => true,
+ 'x+t' => true,
+ 'c+t' => true,
+ 'a+' => true,
],
'write' => [
- 'w' => true, 'w+' => true, 'rw' => true, 'r+' => true, 'x+' => true,
- 'c+' => true, 'wb' => true, 'w+b' => true, 'r+b' => true,
- 'x+b' => true, 'c+b' => true, 'w+t' => true, 'r+t' => true,
- 'x+t' => true, 'c+t' => true, 'a' => true, 'a+' => true,
+ 'w' => true,
+ 'w+' => true,
+ 'rw' => true,
+ 'r+' => true,
+ 'x+' => true,
+ 'c+' => true,
+ 'wb' => true,
+ 'w+b' => true,
+ 'r+b' => true,
+ 'x+b' => true,
+ 'c+b' => true,
+ 'w+t' => true,
+ 'r+t' => true,
+ 'x+t' => true,
+ 'c+t' => true,
+ 'a' => true,
+ 'a+' => true,
],
];
- /**
- * @var resource
- */
+
+ /** @var resource */
private $stream;
- /**
- * @var int
- */
+
+ /** @var int */
private $size;
- /**
- * @var bool
- */
+
+ /** @var bool */
private $seekable;
- /**
- * @var bool
- */
+
+ /** @var bool */
private $readable;
- /**
- * @var bool
- */
+
+ /** @var bool */
private $writable;
- /**
- * @var array|mixed|null
- */
+
+ /** @var array|mixed|null */
private $uri;
/**
- * @param resource $stream Stream resource to wrap.
+ * @param resource $stream stream resource to wrap
+ *
* @throws \InvalidArgumentException if the stream is not a stream resource
*/
public function __construct($stream)
{
- if (!is_resource($stream)) {
+ if (!\is_resource($stream)) {
throw new \InvalidArgumentException('Stream must be a resource');
}
$this->stream = $stream;
@@ -74,11 +92,13 @@ class ResponseStream implements StreamInterface
* The keys returned are identical to the keys returned from PHP's
* stream_get_meta_data() function.
*
- * @link http://php.net/manual/en/function.stream-get-meta-data.php
- * @param string $key Specific metadata to retrieve.
+ * @see http://php.net/manual/en/function.stream-get-meta-data.php
+ *
+ * @param string $key specific metadata to retrieve
+ *
* @return array|mixed|null Returns an associative array if no key is
- * provided. Returns a specific key value if a key is provided and the
- * value is found, or null if the key is not found.
+ * provided. Returns a specific key value if a key is provided and the
+ * value is found, or null if the key is not found.
*/
public function getMetadata($key = null)
{
@@ -86,6 +106,7 @@ class ResponseStream implements StreamInterface
return $key ? null : [];
}
$meta = stream_get_meta_data($this->stream);
+
return isset($meta[$key]) ? $meta[$key] : null;
}
@@ -101,6 +122,7 @@ class ResponseStream implements StreamInterface
* string casting operations.
*
* @see http://php.net/manual/en/language.oop5.magic.php#object.tostring
+ *
* @return string
*/
public function __toString()
@@ -109,7 +131,8 @@ class ResponseStream implements StreamInterface
return '';
}
$this->rewind();
- return (string)stream_get_contents($this->stream);
+
+ return (string) stream_get_contents($this->stream);
}
/**
@@ -118,9 +141,10 @@ class ResponseStream implements StreamInterface
* If the stream is not seekable, this method will raise an exception;
* otherwise, it will perform a seek(0).
*
+ * @throws \RuntimeException on failure
+ *
+ * @see http://www.php.net/manual/en/function.fseek.php
* @see seek()
- * @link http://www.php.net/manual/en/function.fseek.php
- * @throws \RuntimeException on failure.
*/
public function rewind()
{
@@ -130,13 +154,14 @@ class ResponseStream implements StreamInterface
/**
* Get the size of the stream if known.
*
- * @return int|null Returns the size in bytes if known, or null if unknown.
+ * @return int|null returns the size in bytes if known, or null if unknown
*/
public function getSize()
{
if ($this->size !== null) {
return $this->size;
}
+
if (!$this->stream) {
return null;
}
@@ -145,18 +170,22 @@ class ResponseStream implements StreamInterface
clearstatcache(true, $this->uri);
}
$stats = fstat($this->stream);
+
if (isset($stats['size'])) {
$this->size = $stats['size'];
+
return $this->size;
}
+
return null;
}
/**
- * Returns the current position of the file read/write pointer
+ * Returns the current position of the file read/write pointer.
+ *
+ * @throws \RuntimeException on error
*
* @return int Position of the file pointer
- * @throws \RuntimeException on error.
*/
public function tell()
{
@@ -186,16 +215,18 @@ class ResponseStream implements StreamInterface
/**
* Seek to a position in the stream.
*
- * @link http://www.php.net/manual/en/function.fseek.php
+ * @see http://www.php.net/manual/en/function.fseek.php
+ *
* @param int $offset Stream offset
* @param int $whence Specifies how the cursor position will be calculated
- * based on the seek offset. Valid values are identical to the built-in
- * PHP $whence values for `fseek()`. SEEK_SET: Set position equal to
- * offset bytes SEEK_CUR: Set position to current location plus offset
- * SEEK_END: Set position to end-of-stream plus offset.
- * @throws \RuntimeException on failure.
+ * based on the seek offset. Valid values are identical to the built-in
+ * PHP $whence values for `fseek()`. SEEK_SET: Set position equal to
+ * offset bytes SEEK_CUR: Set position to current location plus offset
+ * SEEK_END: Set position to end-of-stream plus offset.
+ *
+ * @throws \RuntimeException on failure
*/
- public function seek($offset, $whence = SEEK_SET)
+ public function seek($offset, $whence = \SEEK_SET)
{
$this->seekable && fseek($this->stream, $offset, $whence);
}
@@ -213,13 +244,16 @@ class ResponseStream implements StreamInterface
/**
* Write data to the stream.
*
- * @param string $string The string that is to be written.
- * @return int Returns the number of bytes written to the stream.
- * @throws \RuntimeException on failure.
+ * @param string $string the string that is to be written
+ *
+ * @throws \RuntimeException on failure
+ *
+ * @return int returns the number of bytes written to the stream
*/
public function write($string)
{
$this->size = null;
+
return $this->writable ? fwrite($this->stream, $string) : false;
}
@@ -237,23 +271,26 @@ class ResponseStream implements StreamInterface
* Read data from the stream.
*
* @param int $length Read up to $length bytes from the object and return
- * them. Fewer than $length bytes may be returned if underlying stream
- * call returns fewer bytes.
- * @return string Returns the data read from the stream, or an empty string
- * if no bytes are available.
- * @throws \RuntimeException if an error occurs.
+ * them. Fewer than $length bytes may be returned if underlying stream
+ * call returns fewer bytes.
+ *
+ * @throws \RuntimeException if an error occurs
+ *
+ * @return string returns the data read from the stream, or an empty string
+ * if no bytes are available
*/
public function read($length)
{
- return $this->readable ? fread($this->stream, $length) : "";
+ return $this->readable ? fread($this->stream, $length) : '';
}
/**
- * Returns the remaining contents in a string
+ * Returns the remaining contents in a string.
+ *
+ * @throws \RuntimeException if unable to read or an error occurs while
+ * reading
*
* @return string
- * @throws \RuntimeException if unable to read or an error occurs while
- * reading.
*/
public function getContents()
{
@@ -261,7 +298,7 @@ class ResponseStream implements StreamInterface
}
/**
- * Closes the stream when the destructed
+ * Closes the stream when the destructed.
*/
public function __destruct()
{
@@ -270,12 +307,10 @@ class ResponseStream implements StreamInterface
/**
* Closes the stream and any underlying resources.
- *
- * @return void
*/
public function close()
{
- if (is_resource($this->stream)) {
+ if (\is_resource($this->stream)) {
fclose($this->stream);
}
$this->detach();
@@ -293,6 +328,7 @@ class ResponseStream implements StreamInterface
$result = $this->stream;
$this->stream = $this->size = $this->uri = null;
$this->readable = $this->writable = $this->seekable = false;
+
return $result;
}
}
diff --git a/src/PhpZip/Stream/ZipInputStream.php b/src/PhpZip/Stream/ZipInputStream.php
index dbbbd3e..b2e677f 100644
--- a/src/PhpZip/Stream/ZipInputStream.php
+++ b/src/PhpZip/Stream/ZipInputStream.php
@@ -25,41 +25,36 @@ use PhpZip\Util\StringUtil;
use PhpZip\ZipFileInterface;
/**
- * Read zip file
+ * Read zip file.
*
* @author Ne-Lexa alexey@nelexa.ru
* @license MIT
*/
class ZipInputStream implements ZipInputStreamInterface
{
- /**
- * @var resource
- */
+ /** @var resource */
protected $in;
- /**
- * @var PositionMapper
- */
+
+ /** @var PositionMapper */
protected $mapper;
- /**
- * @var int The number of bytes in the preamble of this ZIP file.
- */
+
+ /** @var int the number of bytes in the preamble of this ZIP file */
protected $preamble = 0;
- /**
- * @var int The number of bytes in the postamble of this ZIP file.
- */
+
+ /** @var int the number of bytes in the postamble of this ZIP file */
protected $postamble = 0;
- /**
- * @var ZipModel
- */
+
+ /** @var ZipModel */
protected $zipModel;
/**
* ZipInputStream constructor.
+ *
* @param resource $in
*/
public function __construct($in)
{
- if (!is_resource($in)) {
+ if (!\is_resource($in)) {
throw new RuntimeException('$in must be resource');
}
$this->in = $in;
@@ -67,8 +62,9 @@ class ZipInputStream implements ZipInputStreamInterface
}
/**
- * @return ZipModel
* @throws ZipException
+ *
+ * @return ZipModel
*/
public function readZip()
{
@@ -76,11 +72,12 @@ class ZipInputStream implements ZipInputStreamInterface
$endOfCentralDirectory = $this->readEndOfCentralDirectory();
$entries = $this->mountCentralDirectory($endOfCentralDirectory);
$this->zipModel = ZipModel::newSourceModel($entries, $endOfCentralDirectory);
+
return $this->zipModel;
}
/**
- * Check zip file signature
+ * Check zip file signature.
*
* @throws ZipException if this not .ZIP file.
*/
@@ -90,22 +87,27 @@ class ZipInputStream implements ZipInputStreamInterface
// Constraint: A ZIP file must start with a Local File Header
// or a (ZIP64) End Of Central Directory Record if it's empty.
$signatureBytes = fread($this->in, 4);
- if (strlen($signatureBytes) < 4) {
- throw new ZipException("Invalid zip file.");
+
+ if (\strlen($signatureBytes) < 4) {
+ throw new ZipException('Invalid zip file.');
}
$signature = unpack('V', $signatureBytes)[1];
+
if (
- ZipEntry::LOCAL_FILE_HEADER_SIG !== $signature
- && EndOfCentralDirectory::ZIP64_END_OF_CENTRAL_DIRECTORY_RECORD_SIG !== $signature
- && EndOfCentralDirectory::END_OF_CENTRAL_DIRECTORY_RECORD_SIG !== $signature
+ $signature !== ZipEntry::LOCAL_FILE_HEADER_SIG
+ && $signature !== EndOfCentralDirectory::ZIP64_END_OF_CENTRAL_DIRECTORY_RECORD_SIG
+ && $signature !== EndOfCentralDirectory::END_OF_CENTRAL_DIRECTORY_RECORD_SIG
) {
- throw new ZipException("Expected Local File Header or (ZIP64) End Of Central Directory Record! Signature: " . $signature);
+ throw new ZipException(
+ 'Expected Local File Header or (ZIP64) End Of Central Directory Record! Signature: ' . $signature
+ );
}
}
/**
- * @return EndOfCentralDirectory
* @throws ZipException
+ *
+ * @return EndOfCentralDirectory
*/
protected function readEndOfCentralDirectory()
{
@@ -116,9 +118,9 @@ class ZipInputStream implements ZipInputStreamInterface
$max = $size - EndOfCentralDirectory::END_OF_CENTRAL_DIRECTORY_RECORD_MIN_LEN;
$min = $max >= 0xffff ? $max - 0xffff : 0;
for ($endOfCentralDirRecordPos = $max; $endOfCentralDirRecordPos >= $min; $endOfCentralDirRecordPos--) {
- fseek($this->in, $endOfCentralDirRecordPos, SEEK_SET);
+ fseek($this->in, $endOfCentralDirRecordPos, \SEEK_SET);
// end of central dir signature 4 bytes (0x06054b50)
- if (EndOfCentralDirectory::END_OF_CENTRAL_DIRECTORY_RECORD_SIG !== unpack('V', fread($this->in, 4))[1]) {
+ if (unpack('V', fread($this->in, 4))[1] !== EndOfCentralDirectory::END_OF_CENTRAL_DIRECTORY_RECORD_SIG) {
continue;
}
@@ -138,15 +140,16 @@ class ZipInputStream implements ZipInputStreamInterface
fread($this->in, 18)
);
- if (0 !== $data['diskNo'] || 0 !== $data['cdDiskNo'] || $data['cdEntriesDisk'] !== $data['cdEntries']) {
+ if ($data['diskNo'] !== 0 || $data['cdDiskNo'] !== 0 || $data['cdEntriesDisk'] !== $data['cdEntries']) {
throw new ZipException(
- "ZIP file spanning/splitting is not supported!"
+ 'ZIP file spanning/splitting is not supported!'
);
}
// .ZIP file comment (variable size)
if ($data['commentLength'] > 0) {
$comment = '';
$offset = 0;
+
while ($offset < $data['commentLength']) {
$read = min(8192 /* chunk size */, $data['commentLength'] - $offset);
$comment .= fread($this->in, $read);
@@ -159,22 +162,27 @@ class ZipInputStream implements ZipInputStreamInterface
// Check for ZIP64 End Of Central Directory Locator.
$endOfCentralDirLocatorPos = $endOfCentralDirRecordPos - EndOfCentralDirectory::ZIP64_END_OF_CENTRAL_DIRECTORY_LOCATOR_LEN;
- fseek($this->in, $endOfCentralDirLocatorPos, SEEK_SET);
+ fseek($this->in, $endOfCentralDirLocatorPos, \SEEK_SET);
// zip64 end of central dir locator
// signature 4 bytes (0x07064b50)
if (
- 0 > $endOfCentralDirLocatorPos ||
+ $endOfCentralDirLocatorPos < 0 ||
ftell($this->in) === $size ||
- EndOfCentralDirectory::ZIP64_END_OF_CENTRAL_DIRECTORY_LOCATOR_SIG !== unpack('V', fread($this->in, 4))[1]
+ unpack(
+ 'V',
+ fread($this->in, 4)
+ )[1] !== EndOfCentralDirectory::ZIP64_END_OF_CENTRAL_DIRECTORY_LOCATOR_SIG
) {
// Seek and check first CFH, probably requiring an offset mapper.
$offset = $endOfCentralDirRecordPos - $data['cdSize'];
- fseek($this->in, $offset, SEEK_SET);
+ fseek($this->in, $offset, \SEEK_SET);
$offset -= $data['cdPos'];
+
if ($offset !== 0) {
$this->mapper = new OffsetPositionMapper($offset);
}
$entryCount = $data['cdEntries'];
+
return new EndOfCentralDirectory($entryCount, $comment);
}
@@ -187,21 +195,23 @@ class ZipInputStream implements ZipInputStreamInterface
$zip64EndOfCentralDirectoryRecordPos = PackUtil::unpackLongLE(fread($this->in, 8));
// total number of disks 4 bytes
$totalDisks = unpack('V', fread($this->in, 4))[1];
- if (0 !== $zip64EndOfCentralDirectoryRecordDisk || 1 !== $totalDisks) {
- throw new ZipException("ZIP file spanning/splitting is not supported!");
+
+ if ($zip64EndOfCentralDirectoryRecordDisk !== 0 || $totalDisks !== 1) {
+ throw new ZipException('ZIP file spanning/splitting is not supported!');
}
- fseek($this->in, $zip64EndOfCentralDirectoryRecordPos, SEEK_SET);
+ fseek($this->in, $zip64EndOfCentralDirectoryRecordPos, \SEEK_SET);
// zip64 end of central dir
// signature 4 bytes (0x06064b50)
$zip64EndOfCentralDirSig = unpack('V', fread($this->in, 4))[1];
- if (EndOfCentralDirectory::ZIP64_END_OF_CENTRAL_DIRECTORY_RECORD_SIG !== $zip64EndOfCentralDirSig) {
- throw new ZipException("Expected ZIP64 End Of Central Directory Record!");
+
+ if ($zip64EndOfCentralDirSig !== EndOfCentralDirectory::ZIP64_END_OF_CENTRAL_DIRECTORY_RECORD_SIG) {
+ throw new ZipException('Expected ZIP64 End Of Central Directory Record!');
}
// size of zip64 end of central
// directory record 8 bytes
// version made by 2 bytes
// version needed to extract 2 bytes
- fseek($this->in, 12, SEEK_CUR);
+ fseek($this->in, 12, \SEEK_CUR);
// number of this disk 4 bytes
$diskNo = unpack('V', fread($this->in, 4))[1];
// number of the disk with the
@@ -213,28 +223,32 @@ class ZipInputStream implements ZipInputStreamInterface
// total number of entries in the
// central directory 8 bytes
$cdEntries = PackUtil::unpackLongLE(fread($this->in, 8));
- if (0 !== $diskNo || 0 !== $cdDiskNo || $cdEntriesDisk !== $cdEntries) {
- throw new ZipException("ZIP file spanning/splitting is not supported!");
+
+ if ($diskNo !== 0 || $cdDiskNo !== 0 || $cdEntriesDisk !== $cdEntries) {
+ throw new ZipException('ZIP file spanning/splitting is not supported!');
}
- if ($cdEntries < 0 || 0x7fffffff < $cdEntries) {
- throw new ZipException("Total Number Of Entries In The Central Directory out of range!");
+
+ if ($cdEntries < 0 || $cdEntries > 0x7fffffff) {
+ throw new ZipException('Total Number Of Entries In The Central Directory out of range!');
}
// size of the central directory 8 bytes
- fseek($this->in, 8, SEEK_CUR);
+ fseek($this->in, 8, \SEEK_CUR);
// offset of start of central
// directory with respect to
// the starting disk number 8 bytes
$cdPos = PackUtil::unpackLongLE(fread($this->in, 8));
// zip64 extensible data sector (variable size)
- fseek($this->in, $cdPos, SEEK_SET);
+ fseek($this->in, $cdPos, \SEEK_SET);
$this->preamble = $zip64EndOfCentralDirectoryRecordPos;
$entryCount = $cdEntries;
$zip64 = true;
+
return new EndOfCentralDirectory($entryCount, $comment, $zip64);
}
// Start recovering file entries from min.
$this->preamble = $min;
$this->postamble = $size - $min;
+
return new EndOfCentralDirectory(0, $comment);
}
@@ -247,8 +261,10 @@ class ZipInputStream implements ZipInputStreamInterface
* file header or additional data to be read.
*
* @param EndOfCentralDirectory $endOfCentralDirectory
- * @return ZipEntry[]
+ *
* @throws ZipException
+ *
+ * @return ZipEntry[]
*/
protected function mountCentralDirectory(EndOfCentralDirectory $endOfCentralDirectory)
{
@@ -261,7 +277,8 @@ class ZipInputStream implements ZipInputStreamInterface
// Extra Field may have been parsed, map it to the real
// offset and conditionally update the preamble size from it.
$lfhOff = $this->mapper->map($entry->getOffset());
- $lfhOff = PHP_INT_SIZE === 4 ? sprintf('%u', $lfhOff) : $lfhOff;
+ $lfhOff = \PHP_INT_SIZE === 4 ? sprintf('%u', $lfhOff) : $lfhOff;
+
if ($lfhOff < $this->preamble) {
$this->preamble = $lfhOff;
}
@@ -269,9 +286,11 @@ class ZipInputStream implements ZipInputStreamInterface
}
if (($numEntries % 0x10000) !== 0) {
- throw new ZipException("Expected " . abs($numEntries) .
- ($numEntries > 0 ? " more" : " less") .
- " entries in the Central Directory!");
+ throw new ZipException(
+ 'Expected ' . abs($numEntries) .
+ ($numEntries > 0 ? ' more' : ' less') .
+ ' entries in the Central Directory!'
+ );
}
if ($this->preamble + $this->postamble >= fstat($this->in)['size']) {
@@ -282,15 +301,17 @@ class ZipInputStream implements ZipInputStreamInterface
}
/**
- * @return ZipEntry
* @throws ZipException
+ *
+ * @return ZipEntry
*/
public function readEntry()
{
// central file header signature 4 bytes (0x02014b50)
$fileHeaderSig = unpack('V', fread($this->in, 4))[1];
+
if ($fileHeaderSig !== ZipOutputStreamInterface::CENTRAL_FILE_HEADER_SIG) {
- throw new InvalidArgumentException("Corrupt zip file. Can not read zip entry.");
+ throw new InvalidArgumentException('Corrupt zip file. Can not read zip entry.');
}
// version made by 2 bytes
@@ -322,6 +343,7 @@ class ZipInputStream implements ZipInputStreamInterface
// See appendix D of PKWARE's ZIP File Format Specification.
$name = '';
$offset = 0;
+
while ($offset < $data['fileLength']) {
$read = min(8192 /* chunk size */, $data['fileLength'] - $offset);
$name .= fread($this->in, $read);
@@ -343,6 +365,7 @@ class ZipInputStream implements ZipInputStreamInterface
if ($data['extraLength'] > 0) {
$extra = '';
$offset = 0;
+
while ($offset < $data['extraLength']) {
$read = min(8192 /* chunk size */, $data['extraLength'] - $offset);
$extra .= fread($this->in, $read);
@@ -350,9 +373,11 @@ class ZipInputStream implements ZipInputStreamInterface
}
$entry->setExtra($extra);
}
+
if ($data['commentLength'] > 0) {
$comment = '';
$offset = 0;
+
while ($offset < $data['commentLength']) {
$read = min(8192 /* chunk size */, $data['commentLength'] - $offset);
$comment .= fread($this->in, $read);
@@ -360,29 +385,34 @@ class ZipInputStream implements ZipInputStreamInterface
}
$entry->setComment($comment);
}
+
return $entry;
}
/**
* @param ZipEntry $entry
- * @return string
+ *
* @throws ZipException
+ *
+ * @return string
*/
public function readEntryContent(ZipEntry $entry)
{
if ($entry->isDirectory()) {
return null;
}
+
if (!($entry instanceof ZipSourceEntry)) {
throw new InvalidArgumentException('entry must be ' . ZipSourceEntry::class);
}
$isEncrypted = $entry->isEncrypted();
+
if ($isEncrypted && $entry->getPassword() === null) {
- throw new ZipException("Can not password from entry " . $entry->getName());
+ throw new ZipException('Can not password from entry ' . $entry->getName());
}
$pos = $entry->getOffset();
- $pos = PHP_INT_SIZE === 4
+ $pos = \PHP_INT_SIZE === 4
? sprintf('%u', $pos) // PHP 32-Bit
: $pos; // PHP 64-Bit
@@ -391,7 +421,7 @@ class ZipInputStream implements ZipInputStreamInterface
// local file header signature 4 bytes (0x04034b50)
if (unpack('V', fread($this->in, 4))[1] !== ZipEntry::LOCAL_FILE_HEADER_SIG) {
- throw new ZipException($entry->getName() . " (expected Local File Header)");
+ throw new ZipException($entry->getName() . ' (expected Local File Header)');
}
fseek($this->in, $pos + ZipEntry::LOCAL_FILE_HEADER_FILE_NAME_LENGTH_POS);
// file name length 2 bytes
@@ -399,7 +429,7 @@ class ZipInputStream implements ZipInputStreamInterface
$data = unpack('vfileLength/vextraLength', fread($this->in, 4));
$pos += ZipEntry::LOCAL_FILE_HEADER_MIN_LEN + $data['fileLength'] + $data['extraLength'];
- assert(ZipEntry::UNKNOWN !== $entry->getCrc());
+ \assert($entry->getCrc() !== ZipEntry::UNKNOWN);
$method = $entry->getMethod();
@@ -407,10 +437,12 @@ class ZipInputStream implements ZipInputStreamInterface
// Get raw entry content
$compressedSize = $entry->getCompressedSize();
- $compressedSize = PHP_INT_SIZE === 4 ? sprintf('%u', $compressedSize) : $compressedSize;
+ $compressedSize = \PHP_INT_SIZE === 4 ? sprintf('%u', $compressedSize) : $compressedSize;
$content = '';
+
if ($compressedSize > 0) {
$offset = 0;
+
while ($offset < $compressedSize) {
$read = min(8192 /* chunk size */, $compressedSize - $offset);
$content .= fread($this->in, $read);
@@ -419,6 +451,7 @@ class ZipInputStream implements ZipInputStreamInterface
}
$skipCheckCrc = false;
+
if ($isEncrypted) {
if ($method === ZipEntry::METHOD_WINZIP_AES) {
// Strong Encryption Specification - WinZip AES
@@ -441,6 +474,7 @@ class ZipInputStream implements ZipInputStreamInterface
if (!$skipCheckCrc) {
// Check CRC32 in the Local File Header or Data Descriptor.
$localCrc = null;
+
if ($entry->getGeneralPurposeBitFlag(ZipEntry::GPBF_DATA_DESCRIPTOR)) {
// The CRC32 is in the Data Descriptor after the compressed size.
// Note the Data Descriptor's Signature is optional:
@@ -448,20 +482,22 @@ class ZipInputStream implements ZipInputStreamInterface
// but older apps might not.
fseek($this->in, $pos + $compressedSize);
$localCrc = unpack('V', fread($this->in, 4))[1];
+
if ($localCrc === ZipEntry::DATA_DESCRIPTOR_SIG) {
$localCrc = unpack('V', fread($this->in, 4))[1];
}
} else {
fseek($this->in, $startPos + 14);
// The CRC32 in the Local File Header.
- $localCrc = sprintf('%u', fread($this->in, 4)[1]);
- $localCrc = PHP_INT_SIZE === 4 ? sprintf('%u', $localCrc) : $localCrc;
+ $localCrc = fread($this->in, 4)[1];
}
- $crc = PHP_INT_SIZE === 4 ? sprintf('%u', $entry->getCrc()) : $entry->getCrc();
-
- if ($crc != $localCrc) {
- throw new Crc32Exception($entry->getName(), $crc, $localCrc);
+ if (\PHP_INT_SIZE === 4) {
+ if (sprintf('%u', $entry->getCrc()) === sprintf('%u', $localCrc)) {
+ throw new Crc32Exception($entry->getName(), $entry->getCrc(), $localCrc);
+ }
+ } elseif ($localCrc !== $entry->getCrc()) {
+ throw new Crc32Exception($entry->getName(), $entry->getCrc(), $localCrc);
}
}
}
@@ -469,51 +505,64 @@ class ZipInputStream implements ZipInputStreamInterface
switch ($method) {
case ZipFileInterface::METHOD_STORED:
break;
+
case ZipFileInterface::METHOD_DEFLATED:
$content = @gzinflate($content);
break;
+
case ZipFileInterface::METHOD_BZIP2:
- if (!extension_loaded('bz2')) {
+ if (!\extension_loaded('bz2')) {
throw new ZipException('Extension bzip2 not install');
}
/** @noinspection PhpComposerExtensionStubsInspection */
$content = bzdecompress($content);
- if (is_int($content)) { // decompress error
+
+ if (\is_int($content)) { // decompress error
$content = false;
}
break;
default:
- throw new ZipUnsupportMethodException($entry->getName() .
- " (compression method " . $method . " is not supported)");
+ throw new ZipUnsupportMethodException(
+ $entry->getName() .
+ ' (compression method ' . $method . ' is not supported)'
+ );
}
if ($content === false) {
if ($isEncrypted) {
- throw new ZipAuthenticationException(sprintf(
- 'Invalid password for zip entry "%s"',
- $entry->getName()
- ));
+ throw new ZipAuthenticationException(
+ sprintf(
+ 'Invalid password for zip entry "%s"',
+ $entry->getName()
+ )
+ );
}
- throw new ZipException(sprintf(
- 'Failed to get the contents of the zip entry "%s"',
- $entry->getName()
- ));
+
+ throw new ZipException(
+ sprintf(
+ 'Failed to get the contents of the zip entry "%s"',
+ $entry->getName()
+ )
+ );
}
if (!$skipCheckCrc) {
$localCrc = crc32($content);
- $localCrc = PHP_INT_SIZE === 4 ? sprintf('%u', $localCrc) : $localCrc;
- $crc = PHP_INT_SIZE === 4 ? sprintf('%u', $entry->getCrc()) : $entry->getCrc();
- if ($crc != $localCrc) {
+
+ if (sprintf('%u', $entry->getCrc()) !== sprintf('%u', $localCrc)) {
if ($isEncrypted) {
- throw new ZipAuthenticationException(sprintf(
- 'Invalid password for zip entry "%s"',
- $entry->getName()
- ));
+ throw new ZipAuthenticationException(
+ sprintf(
+ 'Invalid password for zip entry "%s"',
+ $entry->getName()
+ )
+ );
}
- throw new Crc32Exception($entry->getName(), $crc, $localCrc);
+
+ throw new Crc32Exception($entry->getName(), $entry->getCrc(), $localCrc);
}
}
+
return $content;
}
@@ -529,36 +578,39 @@ class ZipInputStream implements ZipInputStreamInterface
* Copy the input stream of the LOC entry zip and the data into
* the output stream and zip the alignment if necessary.
*
- * @param ZipEntry $entry
+ * @param ZipEntry $entry
* @param ZipOutputStreamInterface $out
+ *
* @throws ZipException
*/
public function copyEntry(ZipEntry $entry, ZipOutputStreamInterface $out)
{
$pos = $entry->getOffset();
- assert(ZipEntry::UNKNOWN !== $pos);
- $pos = PHP_INT_SIZE === 4 ? sprintf('%u', $pos) : $pos;
+ \assert($pos !== ZipEntry::UNKNOWN);
+ $pos = \PHP_INT_SIZE === 4 ? sprintf('%u', $pos) : $pos;
$pos = $this->mapper->map($pos);
- $nameLength = strlen($entry->getName());
+ $nameLength = \strlen($entry->getName());
- fseek($this->in, $pos + ZipEntry::LOCAL_FILE_HEADER_MIN_LEN - 2, SEEK_SET);
+ fseek($this->in, $pos + ZipEntry::LOCAL_FILE_HEADER_MIN_LEN - 2, \SEEK_SET);
$sourceExtraLength = $destExtraLength = unpack('v', fread($this->in, 2))[1];
if ($sourceExtraLength > 0) {
// read Local File Header extra fields
- fseek($this->in, $pos + ZipEntry::LOCAL_FILE_HEADER_MIN_LEN + $nameLength, SEEK_SET);
+ fseek($this->in, $pos + ZipEntry::LOCAL_FILE_HEADER_MIN_LEN + $nameLength, \SEEK_SET);
$extra = '';
$offset = 0;
+
while ($offset < $sourceExtraLength) {
$read = min(8192 /* chunk size */, $sourceExtraLength - $offset);
$extra .= fread($this->in, $read);
$offset += $read;
}
$extraFieldsCollection = ExtraFieldsFactory::createExtraFieldCollections($extra, $entry);
+
if (isset($extraFieldsCollection[ApkAlignmentExtraField::getHeaderId()]) && $this->zipModel->isZipAlign()) {
unset($extraFieldsCollection[ApkAlignmentExtraField::getHeaderId()]);
- $destExtraLength = strlen(ExtraFieldsFactory::createSerializedData($extraFieldsCollection));
+ $destExtraLength = \strlen(ExtraFieldsFactory::createSerializedData($extraFieldsCollection));
}
} else {
$extraFieldsCollection = new ExtraFieldsCollection();
@@ -567,7 +619,7 @@ class ZipInputStream implements ZipInputStreamInterface
$dataAlignmentMultiple = $this->zipModel->getZipAlign();
$copyInToOutLength = $entry->getCompressedSize();
- fseek($this->in, $pos, SEEK_SET);
+ fseek($this->in, $pos, \SEEK_SET);
if (
$this->zipModel->isZipAlign() &&
@@ -599,23 +651,25 @@ class ZipInputStream implements ZipInputStreamInterface
// from input stream to output stream
stream_copy_to_stream($this->in, $out->getStream(), ZipEntry::LOCAL_FILE_HEADER_MIN_LEN - 2);
// write new extra field length (2 bytes) to output stream
- fwrite($out->getStream(), pack('v', strlen($extra)));
+ fwrite($out->getStream(), pack('v', \strlen($extra)));
// skip 2 bytes to input stream
- fseek($this->in, 2, SEEK_CUR);
+ fseek($this->in, 2, \SEEK_CUR);
// copy name from input stream to output stream
stream_copy_to_stream($this->in, $out->getStream(), $nameLength);
// write extra field to output stream
fwrite($out->getStream(), $extra);
// skip source extraLength from input stream
- fseek($this->in, $sourceExtraLength, SEEK_CUR);
+ fseek($this->in, $sourceExtraLength, \SEEK_CUR);
} else {
$copyInToOutLength += ZipEntry::LOCAL_FILE_HEADER_MIN_LEN + $sourceExtraLength + $nameLength;
}
+
if ($entry->getGeneralPurposeBitFlag(ZipEntry::GPBF_DATA_DESCRIPTOR)) {
// crc-32 4 bytes
// compressed size 4 bytes
// uncompressed size 4 bytes
$copyInToOutLength += 12;
+
if ($entry->isZip64ExtensionsRequired()) {
// compressed size +4 bytes
// uncompressed size +4 bytes
@@ -627,20 +681,20 @@ class ZipInputStream implements ZipInputStreamInterface
}
/**
- * @param ZipEntry $entry
+ * @param ZipEntry $entry
* @param ZipOutputStreamInterface $out
*/
public function copyEntryData(ZipEntry $entry, ZipOutputStreamInterface $out)
{
$offset = $entry->getOffset();
- $offset = PHP_INT_SIZE === 4 ? sprintf('%u', $offset) : $offset;
+ $offset = \PHP_INT_SIZE === 4 ? sprintf('%u', $offset) : $offset;
$offset = $this->mapper->map($offset);
- $nameLength = strlen($entry->getName());
+ $nameLength = \strlen($entry->getName());
- fseek($this->in, $offset + ZipEntry::LOCAL_FILE_HEADER_MIN_LEN - 2, SEEK_SET);
+ fseek($this->in, $offset + ZipEntry::LOCAL_FILE_HEADER_MIN_LEN - 2, \SEEK_SET);
$extraLength = unpack('v', fread($this->in, 2))[1];
- fseek($this->in, $offset + ZipEntry::LOCAL_FILE_HEADER_MIN_LEN + $nameLength + $extraLength, SEEK_SET);
+ fseek($this->in, $offset + ZipEntry::LOCAL_FILE_HEADER_MIN_LEN + $nameLength + $extraLength, \SEEK_SET);
// copy raw data from input stream to output stream
stream_copy_to_stream($this->in, $out->getStream(), $entry->getCompressedSize());
}
diff --git a/src/PhpZip/Stream/ZipInputStreamInterface.php b/src/PhpZip/Stream/ZipInputStreamInterface.php
index cf8e122..5c21091 100644
--- a/src/PhpZip/Stream/ZipInputStreamInterface.php
+++ b/src/PhpZip/Stream/ZipInputStreamInterface.php
@@ -7,7 +7,7 @@ use PhpZip\Model\ZipEntry;
use PhpZip\Model\ZipModel;
/**
- * Read zip file
+ * Read zip file.
*
* @author Ne-Lexa alexey@nelexa.ru
* @license MIT
@@ -26,8 +26,10 @@ interface ZipInputStreamInterface
/**
* @param ZipEntry $entry
- * @return string
+ *
* @throws ZipException
+ *
+ * @return string
*/
public function readEntryContent(ZipEntry $entry);
@@ -40,13 +42,13 @@ interface ZipInputStreamInterface
* Copy the input stream of the LOC entry zip and the data into
* the output stream and zip the alignment if necessary.
*
- * @param ZipEntry $entry
+ * @param ZipEntry $entry
* @param ZipOutputStreamInterface $out
*/
public function copyEntry(ZipEntry $entry, ZipOutputStreamInterface $out);
/**
- * @param ZipEntry $entry
+ * @param ZipEntry $entry
* @param ZipOutputStreamInterface $out
*/
public function copyEntryData(ZipEntry $entry, ZipOutputStreamInterface $out);
diff --git a/src/PhpZip/Stream/ZipOutputStream.php b/src/PhpZip/Stream/ZipOutputStream.php
index ce0cd74..fca9074 100644
--- a/src/PhpZip/Stream/ZipOutputStream.php
+++ b/src/PhpZip/Stream/ZipOutputStream.php
@@ -22,30 +22,28 @@ use PhpZip\Util\StringUtil;
use PhpZip\ZipFileInterface;
/**
- * Write zip file
+ * Write zip file.
*
* @author Ne-Lexa alexey@nelexa.ru
* @license MIT
*/
class ZipOutputStream implements ZipOutputStreamInterface
{
- /**
- * @var resource
- */
+ /** @var resource */
protected $out;
- /**
- * @var ZipModel
- */
+
+ /** @var ZipModel */
protected $zipModel;
/**
* ZipOutputStream constructor.
+ *
* @param resource $out
* @param ZipModel $zipModel
*/
public function __construct($out, ZipModel $zipModel)
{
- if (!is_resource($out)) {
+ if (!\is_resource($out)) {
throw new InvalidArgumentException('$out must be resource');
}
$this->out = $out;
@@ -59,11 +57,13 @@ class ZipOutputStream implements ZipOutputStreamInterface
{
$entries = $this->zipModel->getEntries();
$outPosEntries = [];
+
foreach ($entries as $entry) {
$outPosEntries[] = new OutputOffsetEntry(ftell($this->out), $entry);
$this->writeEntry($entry);
}
$centralDirectoryOffset = ftell($this->out);
+
foreach ($outPosEntries as $outputEntry) {
$this->writeCentralDirectoryHeader($outputEntry);
}
@@ -72,12 +72,14 @@ class ZipOutputStream implements ZipOutputStreamInterface
/**
* @param ZipEntry $entry
+ *
* @throws ZipException
*/
public function writeEntry(ZipEntry $entry)
{
if ($entry instanceof ZipSourceEntry) {
$entry->getInputStream()->copyEntry($entry, $this);
+
return;
}
@@ -88,8 +90,8 @@ class ZipOutputStream implements ZipOutputStreamInterface
$extra = $entry->getExtra();
- $nameLength = strlen($entry->getName());
- $extraLength = strlen($extra);
+ $nameLength = \strlen($entry->getName());
+ $extraLength = \strlen($extra);
// zip align
if (
@@ -98,6 +100,7 @@ class ZipOutputStream implements ZipOutputStreamInterface
$entry->getMethod() === ZipFileInterface::METHOD_STORED
) {
$dataAlignmentMultiple = $this->zipModel->getZipAlign();
+
if (StringUtil::endsWith($entry->getName(), '.so')) {
$dataAlignmentMultiple = ApkAlignmentExtraField::ANDROID_COMMON_PAGE_ALIGNMENT_BYTES;
}
@@ -120,15 +123,16 @@ class ZipOutputStream implements ZipOutputStreamInterface
$extraFieldsCollection->add($alignExtra);
$extra = ExtraFieldsFactory::createSerializedData($extraFieldsCollection);
- $extraLength = strlen($extra);
+ $extraLength = \strlen($extra);
}
$size = $nameLength + $extraLength;
+
if ($size > 0xffff) {
throw new ZipException(
- $entry->getName() . " (the total size of " . $size .
- " bytes for the name, extra fields and comment " .
- "exceeds the maximum size of " . 0xffff . " bytes)"
+ $entry->getName() . ' (the total size of ' . $size .
+ ' bytes for the name, extra fields and comment ' .
+ 'exceeds the maximum size of ' . 0xffff . ' bytes)'
);
}
@@ -160,9 +164,11 @@ class ZipOutputStream implements ZipOutputStreamInterface
$extraLength
)
);
+
if ($nameLength > 0) {
fwrite($this->out, $entry->getName());
}
+
if ($extraLength > 0) {
fwrite($this->out, $extra);
}
@@ -173,8 +179,9 @@ class ZipOutputStream implements ZipOutputStreamInterface
fwrite($this->out, $entryContent);
}
- assert(ZipEntry::UNKNOWN !== $entry->getCrc());
- assert(ZipEntry::UNKNOWN !== $entry->getSize());
+ \assert($entry->getCrc() !== ZipEntry::UNKNOWN);
+ \assert($entry->getSize() !== ZipEntry::UNKNOWN);
+
if ($entry->getGeneralPurposeBitFlag(ZipEntry::GPBF_DATA_DESCRIPTOR)) {
// data descriptor signature 4 bytes (0x08074b50)
// crc-32 4 bytes
@@ -187,25 +194,28 @@ class ZipOutputStream implements ZipOutputStreamInterface
} else {
fwrite($this->out, pack('VV', $entry->getCompressedSize(), $entry->getSize()));
}
- } elseif ($compressedSize != $entry->getCompressedSize()) {
+ } elseif ($compressedSize !== $entry->getCompressedSize()) {
throw new ZipException(
- $entry->getName() . " (expected compressed entry size of "
- . $entry->getCompressedSize() . " bytes, " .
- "but is actually " . $compressedSize . " bytes)"
+ $entry->getName() . ' (expected compressed entry size of '
+ . $entry->getCompressedSize() . ' bytes, ' .
+ 'but is actually ' . $compressedSize . ' bytes)'
);
}
}
/**
* @param ZipEntry $entry
- * @return null|string
+ *
* @throws ZipException
+ *
+ * @return string|null
*/
protected function entryCommitChangesAndReturnContent(ZipEntry $entry)
{
if ($entry->getPlatform() === ZipEntry::UNKNOWN) {
$entry->setPlatform(ZipEntry::PLATFORM_UNIX);
}
+
if ($entry->getTime() === ZipEntry::UNKNOWN) {
$entry->setTime(time());
}
@@ -216,7 +226,7 @@ class ZipOutputStream implements ZipOutputStreamInterface
$utf8 = true;
if ($encrypted && $entry->getPassword() === null) {
- throw new ZipException("Can not password from entry " . $entry->getName());
+ throw new ZipException('Can not password from entry ' . $entry->getName());
}
// Compose General Purpose Bit Flag.
@@ -226,11 +236,12 @@ class ZipOutputStream implements ZipOutputStreamInterface
$entryContent = null;
$extraFieldsCollection = $entry->getExtraFieldsCollection();
+
if (!($entry instanceof ZipChangesEntry && !$entry->isChangedContent())) {
$entryContent = $entry->getEntryContent();
if ($entryContent !== null) {
- $entry->setSize(strlen($entryContent));
+ $entry->setSize(\strlen($entryContent));
$entry->setCrc(crc32($entryContent));
if ($encrypted && $method === ZipEntry::METHOD_WINZIP_AES) {
@@ -238,6 +249,7 @@ class ZipOutputStream implements ZipOutputStreamInterface
* @var WinZipAesEntryExtraField $field
*/
$field = $extraFieldsCollection->get(WinZipAesEntryExtraField::getHeaderId());
+
if ($field !== null) {
$method = $field->getMethod();
}
@@ -252,12 +264,14 @@ class ZipOutputStream implements ZipOutputStreamInterface
break;
case ZipFileInterface::METHOD_BZIP2:
- $compressionLevel = $entry->getCompressionLevel() === ZipFileInterface::LEVEL_DEFAULT_COMPRESSION ?
+ $compressionLevel = $entry->getCompressionLevel(
+ ) === ZipFileInterface::LEVEL_DEFAULT_COMPRESSION ?
ZipEntry::LEVEL_DEFAULT_BZIP2_COMPRESSION :
$entry->getCompressionLevel();
/** @noinspection PhpComposerExtensionStubsInspection */
$entryContent = bzcompress($entryContent, $compressionLevel);
- if (is_int($entryContent)) {
+
+ if (\is_int($entryContent)) {
throw new ZipException('Error bzip2 compress. Error code: ' . $entryContent);
}
break;
@@ -268,7 +282,7 @@ class ZipOutputStream implements ZipOutputStreamInterface
break;
default:
- throw new ZipException($entry->getName() . " (unsupported compression method " . $method . ")");
+ throw new ZipException($entry->getName() . ' (unsupported compression method ' . $method . ')');
}
if ($method === ZipFileInterface::METHOD_DEFLATED) {
@@ -294,16 +308,23 @@ class ZipOutputStream implements ZipOutputStreamInterface
}
if ($encrypted) {
- if (in_array($entry->getEncryptionMethod(), [
- ZipFileInterface::ENCRYPTION_METHOD_WINZIP_AES_128,
- ZipFileInterface::ENCRYPTION_METHOD_WINZIP_AES_192,
- ZipFileInterface::ENCRYPTION_METHOD_WINZIP_AES_256,
- ], true)) {
- $keyStrength = WinZipAesEntryExtraField::getKeyStrangeFromEncryptionMethod($entry->getEncryptionMethod()); // size bits
+ if (\in_array(
+ $entry->getEncryptionMethod(),
+ [
+ ZipFileInterface::ENCRYPTION_METHOD_WINZIP_AES_128,
+ ZipFileInterface::ENCRYPTION_METHOD_WINZIP_AES_192,
+ ZipFileInterface::ENCRYPTION_METHOD_WINZIP_AES_256,
+ ],
+ true
+ )) {
+ $keyStrength = WinZipAesEntryExtraField::getKeyStrangeFromEncryptionMethod(
+ $entry->getEncryptionMethod()
+ ); // size bits
$field = ExtraFieldsFactory::createWinZipAesEntryExtra();
$field->setKeyStrength($keyStrength);
$field->setMethod($method);
$size = $entry->getSize();
+
if ($size >= 20 && $method !== ZipFileInterface::METHOD_BZIP2) {
$field->setVendorVersion(WinZipAesEntryExtraField::VV_AE_1);
} else {
@@ -321,7 +342,7 @@ class ZipOutputStream implements ZipOutputStreamInterface
}
}
- $compressedSize = strlen($entryContent);
+ $compressedSize = \strlen($entryContent);
$entry->setCompressedSize($compressedSize);
}
}
@@ -334,25 +355,31 @@ class ZipOutputStream implements ZipOutputStreamInterface
} elseif ($extraFieldsCollection->has(Zip64ExtraField::getHeaderId())) {
$extraFieldsCollection->remove(Zip64ExtraField::getHeaderId());
}
+
return $entryContent;
}
/**
* @param ZipEntry $entry
- * @param string $content
- * @return string
+ * @param string $content
+ *
* @throws ZipException
+ *
+ * @return string
*/
protected function determineBestCompressionMethod(ZipEntry $entry, $content)
{
if ($content !== null) {
$entryContent = gzdeflate($content, $entry->getCompressionLevel());
- if (strlen($entryContent) < strlen($content)) {
+
+ if (\strlen($entryContent) < \strlen($content)) {
$entry->setMethod(ZipFileInterface::METHOD_DEFLATED);
+
return $entryContent;
}
$entry->setMethod(ZipFileInterface::METHOD_STORED);
}
+
return $content;
}
@@ -369,12 +396,12 @@ class ZipOutputStream implements ZipOutputStreamInterface
// This test MUST NOT include the CRC-32 because VV_AE_2 sets it to
// UNKNOWN!
if (($compressedSize | $size) === ZipEntry::UNKNOWN) {
- throw new RuntimeException("invalid entry");
+ throw new RuntimeException('invalid entry');
}
$extra = $entry->getExtra();
- $extraSize = strlen($extra);
+ $extraSize = \strlen($extra);
- $commentLength = strlen($entry->getComment());
+ $commentLength = \strlen($entry->getComment());
fwrite(
$this->out,
pack(
@@ -398,7 +425,7 @@ class ZipOutputStream implements ZipOutputStreamInterface
// uncompressed size 4 bytes
$entry->getSize(),
// file name length 2 bytes
- strlen($entry->getName()),
+ \strlen($entry->getName()),
// extra field length 2 bytes
$extraSize,
// file comment length 2 bytes
@@ -415,31 +442,38 @@ class ZipOutputStream implements ZipOutputStreamInterface
);
// file name (variable size)
fwrite($this->out, $entry->getName());
+
if ($extraSize > 0) {
// extra field (variable size)
fwrite($this->out, $extra);
}
+
if ($commentLength > 0) {
// file comment (variable size)
fwrite($this->out, $entry->getComment());
}
}
+ /**
+ * @param int $centralDirectoryOffset
+ */
protected function writeEndOfCentralDirectoryRecord($centralDirectoryOffset)
{
- $centralDirectoryEntriesCount = count($this->zipModel);
+ $centralDirectoryOffset = (int) $centralDirectoryOffset;
+ $centralDirectoryEntriesCount = \count($this->zipModel);
$position = ftell($this->out);
$centralDirectorySize = $position - $centralDirectoryOffset;
$centralDirectoryEntriesZip64 = $centralDirectoryEntriesCount > 0xffff;
$centralDirectorySizeZip64 = $centralDirectorySize > 0xffffffff;
$centralDirectoryOffsetZip64 = $centralDirectoryOffset > 0xffffffff;
- $centralDirectoryEntries16 = $centralDirectoryEntriesZip64 ? 0xffff : (int)$centralDirectoryEntriesCount;
+ $centralDirectoryEntries16 = $centralDirectoryEntriesZip64 ? 0xffff : $centralDirectoryEntriesCount;
$centralDirectorySize32 = $centralDirectorySizeZip64 ? 0xffffffff : $centralDirectorySize;
$centralDirectoryOffset32 = $centralDirectoryOffsetZip64 ? 0xffffffff : $centralDirectoryOffset;
$zip64 // ZIP64 extensions?
= $centralDirectoryEntriesZip64
|| $centralDirectorySizeZip64
|| $centralDirectoryOffsetZip64;
+
if ($zip64) {
// [zip64 end of central directory record]
// relative offset of the zip64 end of central directory record
@@ -449,7 +483,10 @@ class ZipOutputStream implements ZipOutputStreamInterface
fwrite($this->out, pack('V', EndOfCentralDirectory::ZIP64_END_OF_CENTRAL_DIRECTORY_RECORD_SIG));
// size of zip64 end of central
// directory record 8 bytes
- fwrite($this->out, PackUtil::packLongLE(EndOfCentralDirectory::ZIP64_END_OF_CENTRAL_DIRECTORY_RECORD_MIN_LEN - 12));
+ fwrite(
+ $this->out,
+ PackUtil::packLongLE(EndOfCentralDirectory::ZIP64_END_OF_CENTRAL_DIRECTORY_RECORD_MIN_LEN - 12)
+ );
// version made by 2 bytes
// version needed to extract 2 bytes
// due to potential use of BZIP2 compression
@@ -484,7 +521,7 @@ class ZipOutputStream implements ZipOutputStreamInterface
fwrite($this->out, pack('V', 1));
}
$comment = $this->zipModel->getArchiveComment();
- $commentLength = strlen($comment);
+ $commentLength = \strlen($comment);
fwrite(
$this->out,
pack(
@@ -512,6 +549,7 @@ class ZipOutputStream implements ZipOutputStreamInterface
$commentLength
)
);
+
if ($commentLength > 0) {
// .ZIP file comment (variable size)
fwrite($this->out, $comment);
diff --git a/src/PhpZip/Stream/ZipOutputStreamInterface.php b/src/PhpZip/Stream/ZipOutputStreamInterface.php
index 57c397e..dc50801 100644
--- a/src/PhpZip/Stream/ZipOutputStreamInterface.php
+++ b/src/PhpZip/Stream/ZipOutputStreamInterface.php
@@ -5,7 +5,7 @@ namespace PhpZip\Stream;
use PhpZip\Model\ZipEntry;
/**
- * Write zip file
+ * Write zip file.
*
* @author Ne-Lexa alexey@nelexa.ru
* @license MIT
diff --git a/src/PhpZip/Util/CryptoUtil.php b/src/PhpZip/Util/CryptoUtil.php
index d7a659c..0d7958b 100644
--- a/src/PhpZip/Util/CryptoUtil.php
+++ b/src/PhpZip/Util/CryptoUtil.php
@@ -5,31 +5,31 @@ namespace PhpZip\Util;
use PhpZip\Exception\RuntimeException;
/**
- * Crypto Utils
+ * Crypto Utils.
*/
class CryptoUtil
{
-
/**
* Returns random bytes.
*
* @param int $length
+ *
* @return string
*/
final public static function randomBytes($length)
{
- $length = (int)$length;
- if (function_exists('random_bytes')) {
+ $length = (int) $length;
+
+ if (\function_exists('random_bytes')) {
try {
return random_bytes($length);
} catch (\Exception $e) {
- throw new \RuntimeException("Could not generate a random string.");
+ throw new \RuntimeException('Could not generate a random string.');
}
- } elseif (function_exists('openssl_random_pseudo_bytes')) {
+ } elseif (\function_exists('openssl_random_pseudo_bytes')) {
/** @noinspection PhpComposerExtensionStubsInspection */
return openssl_random_pseudo_bytes($length);
- } elseif (function_exists('mcrypt_create_iv')) {
- /** @noinspection PhpDeprecationInspection */
+ } elseif (\function_exists('mcrypt_create_iv')) {
/** @noinspection PhpComposerExtensionStubsInspection */
return mcrypt_create_iv($length);
} else {
diff --git a/src/PhpZip/Util/DateTimeConverter.php b/src/PhpZip/Util/DateTimeConverter.php
index e63f56b..5007bf9 100644
--- a/src/PhpZip/Util/DateTimeConverter.php
+++ b/src/PhpZip/Util/DateTimeConverter.php
@@ -28,13 +28,14 @@ class DateTimeConverter
* Convert a 32 bit integer DOS date/time value to a UNIX timestamp value.
*
* @param int $dosTime Dos date/time
+ *
* @return int Unix timestamp
*/
public static function toUnixTimestamp($dosTime)
{
- if (self::MIN_DOS_TIME > $dosTime) {
+ if ($dosTime < self::MIN_DOS_TIME) {
$dosTime = self::MIN_DOS_TIME;
- } elseif (self::MAX_DOS_TIME < $dosTime) {
+ } elseif ($dosTime > self::MAX_DOS_TIME) {
$dosTime = self::MAX_DOS_TIME;
}
@@ -51,17 +52,19 @@ class DateTimeConverter
/**
* Converts a UNIX timestamp value to a DOS date/time value.
*
- * @param int $unixTimestamp The number of seconds since midnight, January 1st,
- * 1970 AD UTC.
- * @return int A DOS date/time value reflecting the local time zone and
- * rounded down to even seconds
- * and is in between DateTimeConverter::MIN_DOS_TIME and DateTimeConverter::MAX_DOS_TIME.
- * @throws ZipException If unix timestamp is negative.
+ * @param int $unixTimestamp the number of seconds since midnight, January 1st,
+ * 1970 AD UTC
+ *
+ * @throws ZipException if unix timestamp is negative
+ *
+ * @return int a DOS date/time value reflecting the local time zone and
+ * rounded down to even seconds
+ * and is in between DateTimeConverter::MIN_DOS_TIME and DateTimeConverter::MAX_DOS_TIME
*/
public static function toDosTime($unixTimestamp)
{
- if (0 > $unixTimestamp) {
- throw new ZipException("Negative unix timestamp: " . $unixTimestamp);
+ if ($unixTimestamp < 0) {
+ throw new ZipException('Negative unix timestamp: ' . $unixTimestamp);
}
$date = getdate($unixTimestamp);
@@ -71,8 +74,9 @@ class DateTimeConverter
}
$date['year'] -= 1980;
- return ($date['year'] << 25 | $date['mon'] << 21 |
+
+ return $date['year'] << 25 | $date['mon'] << 21 |
$date['mday'] << 16 | $date['hours'] << 11 |
- $date['minutes'] << 5 | $date['seconds'] >> 1);
+ $date['minutes'] << 5 | $date['seconds'] >> 1;
}
}
diff --git a/src/PhpZip/Util/FilesUtil.php b/src/PhpZip/Util/FilesUtil.php
index 0aae7bf..784a6e4 100644
--- a/src/PhpZip/Util/FilesUtil.php
+++ b/src/PhpZip/Util/FilesUtil.php
@@ -10,14 +10,16 @@ use PhpZip\Util\Iterator\IgnoreFilesRecursiveFilterIterator;
*
* @author Ne-Lexa alexey@nelexa.ru
* @license MIT
+ *
+ * @internal
*/
-class FilesUtil
+final class FilesUtil
{
-
/**
- * Is empty directory
+ * Is empty directory.
*
* @param string $dir Directory
+ *
* @return bool
*/
public static function isEmptyDir($dir)
@@ -25,13 +27,14 @@ class FilesUtil
if (!is_readable($dir)) {
return false;
}
- return count(scandir($dir)) === 2;
+
+ return \count(scandir($dir)) === 2;
}
/**
* Remove recursive directory.
*
- * @param string $dir Directory path.
+ * @param string $dir directory path
*/
public static function removeDir($dir)
{
@@ -39,6 +42,7 @@ class FilesUtil
new \RecursiveDirectoryIterator($dir, \RecursiveDirectoryIterator::SKIP_DOTS),
\RecursiveIteratorIterator::CHILD_FIRST
);
+
foreach ($files as $fileInfo) {
$function = ($fileInfo->isDir() ? 'rmdir' : 'unlink');
$function($fileInfo->getRealPath());
@@ -46,11 +50,11 @@ class FilesUtil
rmdir($dir);
}
-
/**
* Convert glob pattern to regex pattern.
*
* @param string $globPattern
+ *
* @return string
*/
public static function convertGlobToRegEx($globPattern)
@@ -61,16 +65,19 @@ class FilesUtil
$inCurrent = 0;
$chars = str_split($globPattern);
$regexPattern = '';
+
foreach ($chars as $currentChar) {
switch ($currentChar) {
case '*':
- $regexPattern .= ($escaping ? "\\*" : '.*');
+ $regexPattern .= ($escaping ? '\\*' : '.*');
$escaping = false;
break;
+
case '?':
- $regexPattern .= ($escaping ? "\\?" : '.');
+ $regexPattern .= ($escaping ? '\\?' : '.');
$escaping = false;
break;
+
case '.':
case '(':
case ')':
@@ -83,41 +90,45 @@ class FilesUtil
$regexPattern .= '\\' . $currentChar;
$escaping = false;
break;
+
case '\\':
if ($escaping) {
- $regexPattern .= "\\\\";
+ $regexPattern .= '\\\\';
$escaping = false;
} else {
$escaping = true;
}
break;
+
case '{':
if ($escaping) {
- $regexPattern .= "\\{";
+ $regexPattern .= '\\{';
} else {
$regexPattern = '(';
$inCurrent++;
}
$escaping = false;
break;
+
case '}':
if ($inCurrent > 0 && !$escaping) {
$regexPattern .= ')';
$inCurrent--;
} elseif ($escaping) {
- $regexPattern = "\\}";
+ $regexPattern = '\\}';
} else {
- $regexPattern = "}";
+ $regexPattern = '}';
}
$escaping = false;
break;
+
case ',':
if ($inCurrent > 0 && !$escaping) {
$regexPattern .= '|';
} elseif ($escaping) {
- $regexPattern .= "\\,";
+ $regexPattern .= '\\,';
} else {
- $regexPattern = ",";
+ $regexPattern = ',';
}
break;
default:
@@ -125,6 +136,7 @@ class FilesUtil
$regexPattern .= $currentChar;
}
}
+
return $regexPattern;
}
@@ -132,8 +144,9 @@ class FilesUtil
* Search files.
*
* @param string $inputDir
- * @param bool $recursive
- * @param array $ignoreFiles
+ * @param bool $recursive
+ * @param array $ignoreFiles
+ *
* @return array Searched file list
*/
public static function fileSearchWithIgnore($inputDir, $recursive = true, array $ignoreFiles = [])
@@ -153,11 +166,13 @@ class FilesUtil
new \IteratorIterator($directoryIterator);
$fileList = [];
+
foreach ($iterator as $file) {
if ($file instanceof \SplFileInfo) {
$fileList[] = $file->getPathname();
}
}
+
return $fileList;
}
@@ -165,21 +180,27 @@ class FilesUtil
* Search files from glob pattern.
*
* @param string $globPattern
- * @param int $flags
- * @param bool $recursive
+ * @param int $flags
+ * @param bool $recursive
+ *
* @return array Searched file list
*/
public static function globFileSearch($globPattern, $flags = 0, $recursive = true)
{
- $flags = (int)$flags;
- $recursive = (bool)$recursive;
+ $flags = (int) $flags;
+ $recursive = (bool) $recursive;
$files = glob($globPattern, $flags);
+
if (!$recursive) {
return $files;
}
- foreach (glob(dirname($globPattern) . '/*', GLOB_ONLYDIR | GLOB_NOSORT) as $dir) {
+
+ foreach (glob(\dirname($globPattern) . '/*', \GLOB_ONLYDIR | \GLOB_NOSORT) as $dir) {
+ // Unpacking the argument via ... is supported starting from php 5.6 only
+ /** @noinspection SlowArrayOperationsInLoopInspection */
$files = array_merge($files, self::globFileSearch($dir . '/' . basename($globPattern), $flags, $recursive));
}
+
return $files;
}
@@ -188,48 +209,58 @@ class FilesUtil
*
* @param string $folder
* @param string $pattern
- * @param bool $recursive
+ * @param bool $recursive
+ *
* @return array Searched file list
*/
public static function regexFileSearch($folder, $pattern, $recursive = true)
{
$directoryIterator = $recursive ? new \RecursiveDirectoryIterator($folder) : new \DirectoryIterator($folder);
- $iterator = $recursive ? new \RecursiveIteratorIterator($directoryIterator) : new \IteratorIterator($directoryIterator);
+ $iterator = $recursive ? new \RecursiveIteratorIterator($directoryIterator) : new \IteratorIterator(
+ $directoryIterator
+ );
$regexIterator = new \RegexIterator($iterator, $pattern, \RegexIterator::MATCH);
$fileList = [];
+
foreach ($regexIterator as $file) {
if ($file instanceof \SplFileInfo) {
$fileList[] = $file->getPathname();
}
}
+
return $fileList;
}
/**
* Convert bytes to human size.
*
- * @param int $size Size bytes
+ * @param int $size Size bytes
* @param string|null $unit Unit support 'GB', 'MB', 'KB'
+ *
* @return string
*/
public static function humanSize($size, $unit = null)
{
- if (($unit === null && $size >= 1 << 30) || $unit === "GB") {
- return number_format($size / (1 << 30), 2) . "GB";
+ if (($unit === null && $size >= 1 << 30) || $unit === 'GB') {
+ return number_format($size / (1 << 30), 2) . 'GB';
}
- if (($unit === null && $size >= 1 << 20) || $unit === "MB") {
- return number_format($size / (1 << 20), 2) . "MB";
+
+ if (($unit === null && $size >= 1 << 20) || $unit === 'MB') {
+ return number_format($size / (1 << 20), 2) . 'MB';
}
- if (($unit === null && $size >= 1 << 10) || $unit === "KB") {
- return number_format($size / (1 << 10), 2) . "KB";
+
+ if (($unit === null && $size >= 1 << 10) || $unit === 'KB') {
+ return number_format($size / (1 << 10), 2) . 'KB';
}
- return number_format($size) . " bytes";
+
+ return number_format($size) . ' bytes';
}
/**
* Normalizes zip path.
*
* @param string $path Zip path
+ *
* @return string
*/
public static function normalizeZipPath($path)
@@ -237,7 +268,7 @@ class FilesUtil
return implode(
'/',
array_filter(
- explode('/', (string)$path),
+ explode('/', (string) $path),
static function ($part) {
return $part !== '.' && $part !== '..';
}
diff --git a/src/PhpZip/Util/Iterator/IgnoreFilesFilterIterator.php b/src/PhpZip/Util/Iterator/IgnoreFilesFilterIterator.php
index 40e8fe0..c13734e 100644
--- a/src/PhpZip/Util/Iterator/IgnoreFilesFilterIterator.php
+++ b/src/PhpZip/Util/Iterator/IgnoreFilesFilterIterator.php
@@ -13,7 +13,7 @@ use PhpZip\Util\StringUtil;
class IgnoreFilesFilterIterator extends \FilterIterator
{
/**
- * Ignore list files
+ * Ignore list files.
*
* @var array
*/
@@ -21,7 +21,7 @@ class IgnoreFilesFilterIterator extends \FilterIterator
/**
* @param \Iterator $iterator
- * @param array $ignoreFiles
+ * @param array $ignoreFiles
*/
public function __construct(\Iterator $iterator, array $ignoreFiles)
{
@@ -30,9 +30,12 @@ class IgnoreFilesFilterIterator extends \FilterIterator
}
/**
- * Check whether the current element of the iterator is acceptable
- * @link http://php.net/manual/en/filteriterator.accept.php
- * @return bool true if the current element is acceptable, otherwise false.
+ * Check whether the current element of the iterator is acceptable.
+ *
+ * @see http://php.net/manual/en/filteriterator.accept.php
+ *
+ * @return bool true if the current element is acceptable, otherwise false
+ *
* @since 5.1.0
*/
public function accept()
@@ -42,6 +45,7 @@ class IgnoreFilesFilterIterator extends \FilterIterator
*/
$fileInfo = $this->current();
$pathname = str_replace('\\', '/', $fileInfo->getPathname());
+
foreach ($this->ignoreFiles as $ignoreFile) {
// handler dir and sub dir
if ($fileInfo->isDir()
@@ -56,6 +60,7 @@ class IgnoreFilesFilterIterator extends \FilterIterator
return false;
}
}
+
return true;
}
}
diff --git a/src/PhpZip/Util/Iterator/IgnoreFilesRecursiveFilterIterator.php b/src/PhpZip/Util/Iterator/IgnoreFilesRecursiveFilterIterator.php
index da6670f..8935127 100644
--- a/src/PhpZip/Util/Iterator/IgnoreFilesRecursiveFilterIterator.php
+++ b/src/PhpZip/Util/Iterator/IgnoreFilesRecursiveFilterIterator.php
@@ -13,7 +13,7 @@ use PhpZip\Util\StringUtil;
class IgnoreFilesRecursiveFilterIterator extends \RecursiveFilterIterator
{
/**
- * Ignore list files
+ * Ignore list files.
*
* @var array
*/
@@ -21,7 +21,7 @@ class IgnoreFilesRecursiveFilterIterator extends \RecursiveFilterIterator
/**
* @param \RecursiveIterator $iterator
- * @param array $ignoreFiles
+ * @param array $ignoreFiles
*/
public function __construct(\RecursiveIterator $iterator, array $ignoreFiles)
{
@@ -30,9 +30,12 @@ class IgnoreFilesRecursiveFilterIterator extends \RecursiveFilterIterator
}
/**
- * Check whether the current element of the iterator is acceptable
- * @link http://php.net/manual/en/filteriterator.accept.php
- * @return bool true if the current element is acceptable, otherwise false.
+ * Check whether the current element of the iterator is acceptable.
+ *
+ * @see http://php.net/manual/en/filteriterator.accept.php
+ *
+ * @return bool true if the current element is acceptable, otherwise false
+ *
* @since 5.1.0
*/
public function accept()
@@ -42,10 +45,11 @@ class IgnoreFilesRecursiveFilterIterator extends \RecursiveFilterIterator
*/
$fileInfo = $this->current();
$pathname = str_replace('\\', '/', $fileInfo->getPathname());
+
foreach ($this->ignoreFiles as $ignoreFile) {
// handler dir and sub dir
if ($fileInfo->isDir()
- && $ignoreFile[strlen($ignoreFile) - 1] === '/'
+ && $ignoreFile[\strlen($ignoreFile) - 1] === '/'
&& StringUtil::endsWith($pathname, substr($ignoreFile, 0, -1))
) {
return false;
@@ -56,6 +60,7 @@ class IgnoreFilesRecursiveFilterIterator extends \RecursiveFilterIterator
return false;
}
}
+
return true;
}
@@ -64,7 +69,6 @@ class IgnoreFilesRecursiveFilterIterator extends \RecursiveFilterIterator
*/
public function getChildren()
{
- /** @noinspection PhpUndefinedMethodInspection */
return new self($this->getInnerIterator()->getChildren(), $this->ignoreFiles);
}
}
diff --git a/src/PhpZip/Util/PackUtil.php b/src/PhpZip/Util/PackUtil.php
index 5b3be4e..bd50ee2 100644
--- a/src/PhpZip/Util/PackUtil.php
+++ b/src/PhpZip/Util/PackUtil.php
@@ -3,22 +3,24 @@
namespace PhpZip\Util;
/**
- * Pack util
+ * Pack util.
*
* @author Ne-Lexa alexey@nelexa.ru
* @license MIT
+ *
+ * @internal
*/
-class PackUtil
+final class PackUtil
{
-
/**
* @param int|string $longValue
+ *
* @return string
*/
public static function packLongLE($longValue)
{
- if (PHP_INT_SIZE === 8 && PHP_VERSION_ID >= 506030) {
- return pack("P", $longValue);
+ if (\PHP_INT_SIZE === 8 && \PHP_VERSION_ID >= 506030) {
+ return pack('P', $longValue);
}
$left = 0xffffffff00000000;
@@ -32,31 +34,36 @@ class PackUtil
/**
* @param string|int $value
+ *
* @return int
*/
public static function unpackLongLE($value)
{
- if (PHP_INT_SIZE === 8 && PHP_VERSION_ID >= 506030) {
+ if (\PHP_INT_SIZE === 8 && \PHP_VERSION_ID >= 506030) {
return unpack('P', $value)[1];
}
$unpack = unpack('Va/Vb', $value);
+
return $unpack['a'] + ($unpack['b'] << 32);
}
/**
- * Cast to signed int 32-bit
+ * Cast to signed int 32-bit.
*
* @param int $int
+ *
* @return int
*/
public static function toSignedInt32($int)
{
- if (PHP_INT_SIZE === 8) {
- $int = $int & 0xffffffff;
+ if (\PHP_INT_SIZE === 8) {
+ $int &= 0xffffffff;
+
if ($int & 0x80000000) {
return $int - 0x100000000;
}
}
+
return $int;
}
}
diff --git a/src/PhpZip/Util/StringUtil.php b/src/PhpZip/Util/StringUtil.php
index b579eac..8b067db 100644
--- a/src/PhpZip/Util/StringUtil.php
+++ b/src/PhpZip/Util/StringUtil.php
@@ -3,54 +3,32 @@
namespace PhpZip\Util;
/**
- * String Util
+ * String Util.
+ *
+ * @internal
*/
-class StringUtil
+final class StringUtil
{
-
/**
* @param string $haystack
* @param string $needle
+ *
* @return bool
*/
public static function startsWith($haystack, $needle)
{
- return $needle === "" || strrpos($haystack, $needle, -strlen($haystack)) !== false;
+ return $needle === '' || strrpos($haystack, $needle, -\strlen($haystack)) !== false;
}
/**
* @param string $haystack
* @param string $needle
+ *
* @return bool
*/
public static function endsWith($haystack, $needle)
{
- return $needle === "" || (($temp = strlen($haystack) - strlen($needle)) >= 0
+ return $needle === '' || (($temp = \strlen($haystack) - \strlen($needle)) >= 0
&& strpos($haystack, $needle, $temp) !== false);
}
-
- /**
- * @param string $str
- * @return string
- */
- public static function cp866toUtf8($str)
- {
- if (function_exists('iconv')) {
- /** @noinspection PhpComposerExtensionStubsInspection */
- return iconv('CP866', 'UTF-8//IGNORE', $str);
- } elseif (function_exists('mb_convert_encoding')) {
- /** @noinspection PhpComposerExtensionStubsInspection */
- return mb_convert_encoding($str, 'UTF-8', 'CP866');
- } elseif (class_exists('UConverter')) {
- /** @noinspection PhpComposerExtensionStubsInspection */
- $converter = new \UConverter('UTF-8', 'CP866');
- return $converter->convert($str, false);
- } else {
- static $cp866Utf8Pairs;
- if (empty($cp866Utf8Pairs)) {
- $cp866Utf8Pairs = require __DIR__ . '/encodings/cp866-utf8.php';
- }
- return strtr($str, $cp866Utf8Pairs);
- }
- }
}
diff --git a/src/PhpZip/Util/encodings/cp866-utf8.php b/src/PhpZip/Util/encodings/cp866-utf8.php
deleted file mode 100644
index b61d753b0f50ae009c44a0f0092a3c60aca60f67..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001
literal 3831
zcmZwKWpoo+7{>9%A#iZl0ZIjmJE`FAE=58cXrYvnCO~m1P~6hs?(S~8tb18^>AJfc
z^!}gwZ9mQXJMYb8?#%PfITI6~o}BJ-W%xb*ltd>i$>aApv5v>*^JF@aF2{*@D8h-2
z%RfZts{ks13ZjCj5GsTUqr#{NDuRllqNo@uhKi%&s01p3T*!q=qLQc-D)oOWOVcY&
zuM8@K%A&HU94d#(qw=T%s(>n@il`E*ges%Ts0ylrs-mi>8mfk>qw1&zs)1^vny414
zg=(YPs1B-w9OR(7s4l99>Y@6mJ_BkF`Yq0Xo?>VmqUuBa>O
zhPt8ds5|O`dZ3=DC+dZIq28!B>Vx{AzNjzihx(!Zs6QHj2B3jxAR2@Qp}}Y{8iIzP
zp=c-?hK8ZxXgC^yMxc>sBpQWAq0wkG8iU55gar8DXfiz(jz#0pI5ZxOM-$KlYlhI_9jFM3bNyYkU{E{=bHqb1Bp!xa#3OL4coc3EkHPKYakxV~0e6Zg;V$tM
z+%2Ald&DzvuXq;j6VJi@;(2&LyZ{f17vUlC5Yr>%88&sZz@&suA2p0n0~K5wo4yxhP<>z&4&FUN08s#_Tpw9P}^&0N)+j1xyzhj++-?i5I
z_pEh4-nZ8C`T*Y(KNJ^pwmeZ`|43X)_hV6i{fW4Y?x*5%_?fr@elBVoUx+K|ekrbk
zUx};X*P^!gjkuQXx8geZowy!;4|BD_AJo-!{iv>X^pm>E;?L@83%{tVN&Hn^{qJw;
zD)+y`yLzww0rRpIqd(Qw+wd>j)>Qm0XX&l+kCrQ>|Ee9*5d5chKBL?&SD4S65lHnr
evEh8ex?O>^46i@Ze9z`D@Ok|KUz($JZr6SP>0BBB
diff --git a/src/PhpZip/ZipFile.php b/src/PhpZip/ZipFile.php
index 4c1d97e..aacf4e0 100644
--- a/src/PhpZip/ZipFile.php
+++ b/src/PhpZip/ZipFile.php
@@ -29,49 +29,41 @@ use Psr\Http\Message\ResponseInterface;
* Support ZipAlign functional.
*
* @see https://pkware.cachefly.net/webdocs/casestudies/APPNOTE.TXT .ZIP File Format Specification
+ *
* @author Ne-Lexa alexey@nelexa.ru
* @license MIT
*/
class ZipFile implements ZipFileInterface
{
- /**
- * @var int[] Allow compression methods.
- */
+ /** @var int[] allow compression methods */
private static $allowCompressionMethods = [
self::METHOD_STORED,
self::METHOD_DEFLATED,
self::METHOD_BZIP2,
- ZipEntry::UNKNOWN
+ ZipEntry::UNKNOWN,
];
- /**
- * @var int[] Allow encryption methods.
- */
+ /** @var int[] allow encryption methods */
private static $allowEncryptionMethods = [
self::ENCRYPTION_METHOD_TRADITIONAL,
self::ENCRYPTION_METHOD_WINZIP_AES_128,
self::ENCRYPTION_METHOD_WINZIP_AES_192,
- self::ENCRYPTION_METHOD_WINZIP_AES_256
+ self::ENCRYPTION_METHOD_WINZIP_AES_256,
];
- /**
- * @var array Default mime types.
- */
+ /** @var array default mime types */
private static $defaultMimeTypes = [
'zip' => 'application/zip',
'apk' => 'application/vnd.android.package-archive',
'docx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
'jar' => 'application/java-archive',
- 'epub' => 'application/epub+zip'
+ 'epub' => 'application/epub+zip',
];
- /**
- * @var ZipInputStreamInterface Input seekable input stream.
- */
+ /** @var ZipInputStreamInterface input seekable input stream */
protected $inputStream;
- /**
- * @var ZipModel
- */
+
+ /** @var ZipModel */
protected $zipModel;
/**
@@ -83,21 +75,25 @@ class ZipFile implements ZipFileInterface
}
/**
- * Open zip archive from file
+ * Open zip archive from file.
*
* @param string $filename
+ *
+ * @throws ZipException if can't open file
+ *
* @return ZipFileInterface
- * @throws ZipException if can't open file.
*/
public function openFile($filename)
{
if (!file_exists($filename)) {
- throw new ZipException("File $filename does not exist.");
+ throw new ZipException("File {$filename} does not exist.");
}
+
if (!($handle = @fopen($filename, 'rb'))) {
- throw new ZipException("File $filename can't open.");
+ throw new ZipException("File {$filename} can't open.");
}
$this->openFromStream($handle);
+
return $this;
}
@@ -105,61 +101,71 @@ class ZipFile implements ZipFileInterface
* Open zip archive from raw string data.
*
* @param string $data
+ *
+ * @throws ZipException if can't open temp stream
+ *
* @return ZipFileInterface
- * @throws ZipException if can't open temp stream.
*/
public function openFromString($data)
{
- if ($data === null || strlen($data) === 0) {
- throw new InvalidArgumentException("Empty string passed");
+ if ($data === null || $data === '') {
+ throw new InvalidArgumentException('Empty string passed');
}
+
if (!($handle = fopen('php://temp', 'r+b'))) {
throw new ZipException("Can't open temp stream.");
}
fwrite($handle, $data);
rewind($handle);
$this->openFromStream($handle);
+
return $this;
}
/**
- * Open zip archive from stream resource
+ * Open zip archive from stream resource.
*
* @param resource $handle
- * @return ZipFileInterface
+ *
* @throws ZipException
+ *
+ * @return ZipFileInterface
*/
public function openFromStream($handle)
{
- if (!is_resource($handle)) {
- throw new InvalidArgumentException("Invalid stream resource.");
+ if (!\is_resource($handle)) {
+ throw new InvalidArgumentException('Invalid stream resource.');
}
$type = get_resource_type($handle);
+
if ($type !== 'stream') {
- throw new InvalidArgumentException("Invalid resource type - $type.");
+ throw new InvalidArgumentException("Invalid resource type - {$type}.");
}
$meta = stream_get_meta_data($handle);
+
if ($meta['stream_type'] === 'dir') {
throw new InvalidArgumentException("Invalid stream type - {$meta['stream_type']}.");
}
+
if (!$meta['seekable']) {
- throw new InvalidArgumentException("Resource cannot seekable stream.");
+ throw new InvalidArgumentException('Resource cannot seekable stream.');
}
$this->inputStream = new ZipInputStream($handle);
$this->zipModel = $this->inputStream->readZip();
+
return $this;
}
/**
- * @return string[] Returns the list files.
+ * @return string[] returns the list files
*/
public function getListFiles()
{
- return array_keys($this->zipModel->getEntries());
+ return array_map('strval', array_keys($this->zipModel->getEntries()));
}
/**
- * @return int Returns the number of entries in this ZIP file.
+ * @return int returns the number of entries in this ZIP file
*/
public function count()
{
@@ -169,7 +175,7 @@ class ZipFile implements ZipFileInterface
/**
* Returns the file comment.
*
- * @return string The file comment.
+ * @return string|null the file comment
*/
public function getArchiveComment()
{
@@ -179,12 +185,14 @@ class ZipFile implements ZipFileInterface
/**
* Set archive comment.
*
- * @param null|string $comment
+ * @param string|null $comment
+ *
* @return ZipFileInterface
*/
public function setArchiveComment($comment = null)
{
$this->zipModel->setArchiveComment($comment);
+
return $this;
}
@@ -194,8 +202,10 @@ class ZipFile implements ZipFileInterface
* (i.e. end with '/').
*
* @param string $entryName
- * @return bool
+ *
* @throws ZipEntryNotFoundException
+ *
+ * @return bool
*/
public function isDirectory($entryName)
{
@@ -206,8 +216,10 @@ class ZipFile implements ZipFileInterface
* Returns entry comment.
*
* @param string $entryName
- * @return string
+ *
* @throws ZipEntryNotFoundException
+ *
+ * @return string
*/
public function getEntryComment($entryName)
{
@@ -217,15 +229,18 @@ class ZipFile implements ZipFileInterface
/**
* Set entry comment.
*
- * @param string $entryName
+ * @param string $entryName
* @param string|null $comment
- * @return ZipFileInterface
- * @throws ZipException
+ *
* @throws ZipEntryNotFoundException
+ * @throws ZipException
+ *
+ * @return ZipFileInterface
*/
public function setEntryComment($entryName, $comment = null)
{
$this->zipModel->getEntryForChanges($entryName)->setComment($comment);
+
return $this;
}
@@ -233,8 +248,10 @@ class ZipFile implements ZipFileInterface
* Returns the entry contents.
*
* @param string $entryName
- * @return string
+ *
* @throws ZipException
+ *
+ * @return string
*/
public function getEntryContents($entryName)
{
@@ -245,6 +262,7 @@ class ZipFile implements ZipFileInterface
* Checks if there is an entry in the archive.
*
* @param string $entryName
+ *
* @return bool
*/
public function hasEntry($entryName)
@@ -256,9 +274,11 @@ class ZipFile implements ZipFileInterface
* Get info by entry.
*
* @param string|ZipEntry $entryName
- * @return ZipInfo
- * @throws ZipEntryNotFoundException
+ *
* @throws ZipException
+ * @throws ZipEntryNotFoundException
+ *
+ * @return ZipInfo
*/
public function getEntryInfo($entryName)
{
@@ -284,24 +304,28 @@ class ZipFile implements ZipFileInterface
}
/**
- * Extract the archive contents
+ * Extract the archive contents.
*
* Extract the complete archive or the given files to the specified destination.
*
- * @param string $destination Location where to extract the files.
- * @param array|string|null $entries The entries to extract. It accepts either
- * a single entry name or an array of names.
- * @return ZipFileInterface
+ * @param string $destination location where to extract the files
+ * @param array|string|null $entries The entries to extract. It accepts either
+ * a single entry name or an array of names.
+ *
* @throws ZipException
+ *
+ * @return ZipFileInterface
*/
public function extractTo($destination, $entries = null)
{
if (!file_exists($destination)) {
throw new ZipException(sprintf('Destination %s not found', $destination));
}
+
if (!is_dir($destination)) {
throw new ZipException('Destination is not directory');
}
+
if (!is_writable($destination)) {
throw new ZipException('Destination is not writable directory');
}
@@ -309,21 +333,26 @@ class ZipFile implements ZipFileInterface
$zipEntries = $this->zipModel->getEntries();
if (!empty($entries)) {
- if (is_string($entries)) {
- $entries = (array)$entries;
+ if (\is_string($entries)) {
+ $entries = (array) $entries;
}
- if (is_array($entries)) {
+
+ if (\is_array($entries)) {
$entries = array_unique($entries);
$flipEntries = array_flip($entries);
- $zipEntries = array_filter($zipEntries, static function (ZipEntry $zipEntry) use ($flipEntries) {
- return isset($flipEntries[$zipEntry->getName()]);
- });
+ $zipEntries = array_filter(
+ $zipEntries,
+ static function (ZipEntry $zipEntry) use ($flipEntries) {
+ return isset($flipEntries[$zipEntry->getName()]);
+ }
+ );
}
}
foreach ($zipEntries as $entry) {
$entryName = FilesUtil::normalizeZipPath($entry->getName());
- $file = $destination . DIRECTORY_SEPARATOR . $entryName;
+ $file = $destination . \DIRECTORY_SEPARATOR . $entryName;
+
if ($entry->isDirectory()) {
if (!is_dir($file)) {
if (!mkdir($file, 0755, true) && !is_dir($file)) {
@@ -332,9 +361,11 @@ class ZipFile implements ZipFileInterface
chmod($file, 0755);
touch($file, $entry->getTime());
}
+
continue;
}
- $dir = dirname($file);
+ $dir = \dirname($file);
+
if (!is_dir($dir)) {
if (!mkdir($dir, 0755, true) && !is_dir($dir)) {
throw new ZipException('Can not create dir ' . $dir);
@@ -342,24 +373,29 @@ class ZipFile implements ZipFileInterface
chmod($dir, 0755);
touch($dir, $entry->getTime());
}
+
if (file_put_contents($file, $entry->getEntryContent()) === false) {
throw new ZipException('Can not extract file ' . $entry->getName());
}
touch($file, $entry->getTime());
}
+
return $this;
}
/**
* Add entry from the string.
*
- * @param string $localName Zip entry name.
- * @param string $contents String contents.
+ * @param string $localName zip entry name
+ * @param string $contents string contents
* @param int|null $compressionMethod Compression method.
- * Use {@see ZipFile::METHOD_STORED}, {@see ZipFile::METHOD_DEFLATED} or {@see ZipFile::METHOD_BZIP2}.
- * If null, then auto choosing method.
- * @return ZipFileInterface
+ * Use {@see ZipFile::METHOD_STORED}, {@see ZipFile::METHOD_DEFLATED} or
+ * {@see ZipFile::METHOD_BZIP2}. If null, then auto choosing method.
+ *
* @throws ZipException
+ *
+ * @return ZipFileInterface
+ *
* @see ZipFileInterface::METHOD_STORED
* @see ZipFileInterface::METHOD_DEFLATED
* @see ZipFileInterface::METHOD_BZIP2
@@ -367,24 +403,27 @@ class ZipFile implements ZipFileInterface
public function addFromString($localName, $contents, $compressionMethod = null)
{
if ($contents === null) {
- throw new InvalidArgumentException("Contents is null");
+ throw new InvalidArgumentException('Contents is null');
}
+
if ($localName === null) {
- throw new InvalidArgumentException("Entry name is null");
+ throw new InvalidArgumentException('Entry name is null');
}
- $localName = ltrim((string)$localName, "\\/");
- if (strlen($localName) === 0) {
- throw new InvalidArgumentException("Empty entry name");
+ $localName = ltrim((string) $localName, '\\/');
+
+ if ($localName === '') {
+ throw new InvalidArgumentException('Empty entry name');
}
- $contents = (string)$contents;
- $length = strlen($contents);
+ $contents = (string) $contents;
+ $length = \strlen($contents);
+
if ($compressionMethod === null) {
if ($length >= 512) {
$compressionMethod = ZipEntry::UNKNOWN;
} else {
$compressionMethod = self::METHOD_STORED;
}
- } elseif (!in_array($compressionMethod, self::$allowCompressionMethods, true)) {
+ } elseif (!\in_array($compressionMethod, self::$allowCompressionMethods, true)) {
throw new ZipUnsupportMethodException('Unsupported compression method ' . $compressionMethod);
}
$externalAttributes = 0100644 << 16;
@@ -396,19 +435,23 @@ class ZipFile implements ZipFileInterface
$entry->setExternalAttributes($externalAttributes);
$this->zipModel->addEntry($entry);
+
return $this;
}
/**
* Add entry from the file.
*
- * @param string $filename Destination file.
- * @param string|null $localName Zip Entry name.
- * @param int|null $compressionMethod Compression method.
- * Use ZipFile::METHOD_STORED, ZipFile::METHOD_DEFLATED or ZipFile::METHOD_BZIP2.
- * If null, then auto choosing method.
- * @return ZipFileInterface
+ * @param string $filename destination file
+ * @param string|null $localName zip Entry name
+ * @param int|null $compressionMethod Compression method.
+ * Use ZipFile::METHOD_STORED, ZipFile::METHOD_DEFLATED or
+ * ZipFile::METHOD_BZIP2. If null, then auto choosing method.
+ *
* @throws ZipException
+ *
+ * @return ZipFileInterface
+ *
* @see ZipFileInterface::METHOD_STORED
* @see ZipFileInterface::METHOD_DEFLATED
* @see ZipFileInterface::METHOD_BZIP2
@@ -418,10 +461,11 @@ class ZipFile implements ZipFileInterface
$entry = new ZipNewFileEntry($filename);
if ($compressionMethod === null) {
- if (function_exists('mime_content_type')) {
+ if (\function_exists('mime_content_type')) {
/** @noinspection PhpComposerExtensionStubsInspection */
$mimeType = @mime_content_type($filename);
$type = strtok($mimeType, '/');
+
if ($type === 'image') {
$compressionMethod = self::METHOD_STORED;
} elseif ($type === 'text' && filesize($filename) < 150) {
@@ -434,16 +478,17 @@ class ZipFile implements ZipFileInterface
} else {
$compressionMethod = self::METHOD_STORED;
}
- } elseif (!in_array($compressionMethod, self::$allowCompressionMethods, true)) {
+ } elseif (!\in_array($compressionMethod, self::$allowCompressionMethods, true)) {
throw new ZipUnsupportMethodException('Unsupported compression method ' . $compressionMethod);
}
if ($localName === null) {
$localName = basename($filename);
}
- $localName = ltrim((string)$localName, "\\/");
- if (strlen($localName) === 0) {
- throw new InvalidArgumentException("Empty entry name");
+ $localName = ltrim((string) $localName, '\\/');
+
+ if ($localName === '') {
+ throw new InvalidArgumentException('Empty entry name');
}
$stat = stat($filename);
@@ -456,48 +501,62 @@ class ZipFile implements ZipFileInterface
$entry->setExternalAttributes($externalAttributes);
$this->zipModel->addEntry($entry);
+
return $this;
}
/**
* Add entry from the stream.
*
- * @param resource $stream Stream resource.
- * @param string $localName Zip Entry name.
+ * @param resource $stream stream resource
+ * @param string $localName zip Entry name
* @param int|null $compressionMethod Compression method.
- * Use ZipFile::METHOD_STORED, ZipFile::METHOD_DEFLATED or ZipFile::METHOD_BZIP2.
- * If null, then auto choosing method.
- * @return ZipFileInterface
+ * Use ZipFile::METHOD_STORED, ZipFile::METHOD_DEFLATED or ZipFile::METHOD_BZIP2.
+ * If null, then auto choosing method.
+ *
* @throws ZipException
+ *
+ * @return ZipFileInterface
+ *
* @see ZipFileInterface::METHOD_STORED
* @see ZipFileInterface::METHOD_DEFLATED
* @see ZipFileInterface::METHOD_BZIP2
*/
public function addFromStream($stream, $localName, $compressionMethod = null)
{
- if (!is_resource($stream)) {
- throw new InvalidArgumentException("Stream is not resource");
+ if (!\is_resource($stream)) {
+ throw new InvalidArgumentException('Stream is not resource');
}
+
if ($localName === null) {
- throw new InvalidArgumentException("Entry name is null");
+ throw new InvalidArgumentException('Entry name is null');
}
- $localName = ltrim((string)$localName, "\\/");
- if (strlen($localName) === 0) {
- throw new InvalidArgumentException("Empty entry name");
+ $localName = ltrim((string) $localName, '\\/');
+
+ if ($localName === '') {
+ throw new InvalidArgumentException('Empty entry name');
}
$fstat = fstat($stream);
- $length = $fstat['size'];
- if ($compressionMethod === null) {
- if ($length >= 512) {
- $compressionMethod = ZipEntry::UNKNOWN;
- } else {
- $compressionMethod = self::METHOD_STORED;
+
+ if ($fstat !== false) {
+ $mode = sprintf('%o', $fstat['mode']);
+ $length = $fstat['size'];
+
+ if ($compressionMethod === null) {
+ if ($length >= 512) {
+ $compressionMethod = ZipEntry::UNKNOWN;
+ } else {
+ $compressionMethod = self::METHOD_STORED;
+ }
}
- } elseif (!in_array($compressionMethod, self::$allowCompressionMethods, true)) {
+ } else {
+ $mode = 010644;
+ }
+
+ if ($compressionMethod !== null && !\in_array($compressionMethod, self::$allowCompressionMethods, true)) {
throw new ZipUnsupportMethodException('Unsupported method ' . $compressionMethod);
}
- $mode = sprintf('%o', $fstat['mode']);
$externalAttributes = (octdec($mode) & 0xffff) << 16;
$entry = new ZipNewEntry($stream);
@@ -507,6 +566,7 @@ class ZipFile implements ZipFileInterface
$entry->setExternalAttributes($externalAttributes);
$this->zipModel->addEntry($entry);
+
return $this;
}
@@ -514,17 +574,20 @@ class ZipFile implements ZipFileInterface
* Add an empty directory in the zip archive.
*
* @param string $dirName
- * @return ZipFileInterface
+ *
* @throws ZipException
+ *
+ * @return ZipFileInterface
*/
public function addEmptyDir($dirName)
{
if ($dirName === null) {
- throw new InvalidArgumentException("Dir name is null");
+ throw new InvalidArgumentException('Dir name is null');
}
- $dirName = ltrim((string)$dirName, "\\/");
- if (strlen($dirName) === 0) {
- throw new InvalidArgumentException("Empty dir name");
+ $dirName = ltrim((string) $dirName, '\\/');
+
+ if ($dirName === '') {
+ throw new InvalidArgumentException('Empty dir name');
}
$dirName = rtrim($dirName, '\\/') . '/';
$externalAttributes = 040755 << 16;
@@ -539,80 +602,95 @@ class ZipFile implements ZipFileInterface
$entry->setExternalAttributes($externalAttributes);
$this->zipModel->addEntry($entry);
+
return $this;
}
/**
* Add directory not recursively to the zip archive.
*
- * @param string $inputDir Input directory
- * @param string $localPath Add files to this directory, or the root.
+ * @param string $inputDir Input directory
+ * @param string $localPath add files to this directory, or the root
* @param int|null $compressionMethod Compression method.
- * Use ZipFile::METHOD_STORED, ZipFile::METHOD_DEFLATED or ZipFile::METHOD_BZIP2.
- * If null, then auto choosing method.
- * @return ZipFileInterface
+ * Use ZipFile::METHOD_STORED, ZipFile::METHOD_DEFLATED or ZipFile::METHOD_BZIP2.
+ * If null, then auto choosing method.
+ *
* @throws ZipException
+ *
+ * @return ZipFileInterface
*/
- public function addDir($inputDir, $localPath = "/", $compressionMethod = null)
+ public function addDir($inputDir, $localPath = '/', $compressionMethod = null)
{
if ($inputDir === null) {
throw new InvalidArgumentException('Input dir is null');
}
- $inputDir = (string)$inputDir;
- if (strlen($inputDir) === 0) {
+ $inputDir = (string) $inputDir;
+
+ if ($inputDir === '') {
throw new InvalidArgumentException('The input directory is not specified');
}
+
if (!is_dir($inputDir)) {
throw new InvalidArgumentException(sprintf('The "%s" directory does not exist.', $inputDir));
}
- $inputDir = rtrim($inputDir, '/\\') . DIRECTORY_SEPARATOR;
+ $inputDir = rtrim($inputDir, '/\\') . \DIRECTORY_SEPARATOR;
$directoryIterator = new \DirectoryIterator($inputDir);
+
return $this->addFilesFromIterator($directoryIterator, $localPath, $compressionMethod);
}
/**
* Add recursive directory to the zip archive.
*
- * @param string $inputDir Input directory
- * @param string $localPath Add files to this directory, or the root.
+ * @param string $inputDir Input directory
+ * @param string $localPath add files to this directory, or the root
* @param int|null $compressionMethod Compression method.
- * Use ZipFile::METHOD_STORED, ZipFile::METHOD_DEFLATED or ZipFile::METHOD_BZIP2.
- * If null, then auto choosing method.
- * @return ZipFileInterface
+ * Use ZipFile::METHOD_STORED, ZipFile::METHOD_DEFLATED or ZipFile::METHOD_BZIP2.
+ * If null, then auto choosing method.
+ *
* @throws ZipException
+ *
+ * @return ZipFileInterface
+ *
* @see ZipFileInterface::METHOD_STORED
* @see ZipFileInterface::METHOD_DEFLATED
* @see ZipFileInterface::METHOD_BZIP2
*/
- public function addDirRecursive($inputDir, $localPath = "/", $compressionMethod = null)
+ public function addDirRecursive($inputDir, $localPath = '/', $compressionMethod = null)
{
if ($inputDir === null) {
throw new InvalidArgumentException('Input dir is null');
}
- $inputDir = (string)$inputDir;
- if (strlen($inputDir) === 0) {
+ $inputDir = (string) $inputDir;
+
+ if ($inputDir === '') {
throw new InvalidArgumentException('The input directory is not specified');
}
+
if (!is_dir($inputDir)) {
throw new InvalidArgumentException(sprintf('The "%s" directory does not exist.', $inputDir));
}
- $inputDir = rtrim($inputDir, '/\\') . DIRECTORY_SEPARATOR;
+ $inputDir = rtrim($inputDir, '/\\') . \DIRECTORY_SEPARATOR;
$directoryIterator = new \RecursiveDirectoryIterator($inputDir);
+
return $this->addFilesFromIterator($directoryIterator, $localPath, $compressionMethod);
}
/**
* Add directories from directory iterator.
*
- * @param \Iterator $iterator Directory iterator.
- * @param string $localPath Add files to this directory, or the root.
- * @param int|null $compressionMethod Compression method.
- * Use ZipFile::METHOD_STORED, ZipFile::METHOD_DEFLATED or ZipFile::METHOD_BZIP2.
- * If null, then auto choosing method.
- * @return ZipFileInterface
+ * @param \Iterator $iterator directory iterator
+ * @param string $localPath add files to this directory, or the root
+ * @param int|null $compressionMethod Compression method.
+ * Use ZipFile::METHOD_STORED, ZipFile::METHOD_DEFLATED or
+ * ZipFile::METHOD_BZIP2. If null, then auto choosing method.
+ *
* @throws ZipException
+ *
+ * @return ZipFileInterface
+ *
* @see ZipFileInterface::METHOD_STORED
* @see ZipFileInterface::METHOD_DEFLATED
* @see ZipFileInterface::METHOD_BZIP2
@@ -622,11 +700,12 @@ class ZipFile implements ZipFileInterface
$localPath = '/',
$compressionMethod = null
) {
- $localPath = (string)$localPath;
- if (strlen($localPath) !== 0) {
+ $localPath = (string) $localPath;
+
+ if ($localPath !== '') {
$localPath = trim($localPath, '\\/');
} else {
- $localPath = "";
+ $localPath = '';
}
$iterator = $iterator instanceof \RecursiveIterator ?
@@ -634,50 +713,58 @@ class ZipFile implements ZipFileInterface
new \IteratorIterator($iterator);
/**
* @var string[] $files
- * @var string $path
+ * @var string $path
*/
$files = [];
+
foreach ($iterator as $file) {
if ($file instanceof \SplFileInfo) {
if ($file->getBasename() === '..') {
continue;
}
+
if ($file->getBasename() === '.') {
- $files[] = dirname($file->getPathname());
+ $files[] = \dirname($file->getPathname());
} else {
$files[] = $file->getPathname();
}
}
}
+
if (empty($files)) {
return $this;
}
natcasesort($files);
$path = array_shift($files);
+
foreach ($files as $file) {
$relativePath = str_replace($path, $localPath, $file);
$relativePath = ltrim($relativePath, '\\/');
+
if (is_dir($file) && FilesUtil::isEmptyDir($file)) {
$this->addEmptyDir($relativePath);
} elseif (is_file($file)) {
$this->addFile($file, $relativePath, $compressionMethod);
}
}
+
return $this;
}
/**
* Add files from glob pattern.
*
- * @param string $inputDir Input directory
- * @param string $globPattern Glob pattern.
- * @param string|null $localPath Add files to this directory, or the root.
- * @param int|null $compressionMethod Compression method.
- * Use ZipFile::METHOD_STORED, ZipFile::METHOD_DEFLATED or ZipFile::METHOD_BZIP2.
- * If null, then auto choosing method.
- * @return ZipFileInterface
+ * @param string $inputDir Input directory
+ * @param string $globPattern glob pattern
+ * @param string|null $localPath add files to this directory, or the root
+ * @param int|null $compressionMethod Compression method.
+ * Use ZipFile::METHOD_STORED, ZipFile::METHOD_DEFLATED or
+ * ZipFile::METHOD_BZIP2. If null, then auto choosing method.
+ *
* @throws ZipException
+ *
+ * @return ZipFileInterface
* @sse https://en.wikipedia.org/wiki/Glob_(programming) Glob pattern syntax
*/
public function addFilesFromGlob($inputDir, $globPattern, $localPath = '/', $compressionMethod = null)
@@ -688,15 +775,17 @@ class ZipFile implements ZipFileInterface
/**
* Add files from glob pattern.
*
- * @param string $inputDir Input directory
- * @param string $globPattern Glob pattern.
- * @param string|null $localPath Add files to this directory, or the root.
- * @param bool $recursive Recursive search.
- * @param int|null $compressionMethod Compression method.
- * Use ZipFile::METHOD_STORED, ZipFile::METHOD_DEFLATED or ZipFile::METHOD_BZIP2.
- * If null, then auto choosing method.
- * @return ZipFileInterface
+ * @param string $inputDir Input directory
+ * @param string $globPattern glob pattern
+ * @param string|null $localPath add files to this directory, or the root
+ * @param bool $recursive recursive search
+ * @param int|null $compressionMethod Compression method.
+ * Use ZipFile::METHOD_STORED, ZipFile::METHOD_DEFLATED or
+ * ZipFile::METHOD_BZIP2. If null, then auto choosing method.
+ *
* @throws ZipException
+ *
+ * @return ZipFileInterface
* @sse https://en.wikipedia.org/wiki/Glob_(programming) Glob pattern syntax
*/
private function addGlob(
@@ -709,29 +798,34 @@ class ZipFile implements ZipFileInterface
if ($inputDir === null) {
throw new InvalidArgumentException('Input dir is null');
}
- $inputDir = (string)$inputDir;
- if (strlen($inputDir) === 0) {
+ $inputDir = (string) $inputDir;
+
+ if ($inputDir === '') {
throw new InvalidArgumentException('The input directory is not specified');
}
+
if (!is_dir($inputDir)) {
throw new InvalidArgumentException(sprintf('The "%s" directory does not exist.', $inputDir));
}
- $globPattern = (string)$globPattern;
+ $globPattern = (string) $globPattern;
+
if (empty($globPattern)) {
throw new InvalidArgumentException('The glob pattern is not specified');
}
- $inputDir = rtrim($inputDir, '/\\') . DIRECTORY_SEPARATOR;
+ $inputDir = rtrim($inputDir, '/\\') . \DIRECTORY_SEPARATOR;
$globPattern = $inputDir . $globPattern;
- $filesFound = FilesUtil::globFileSearch($globPattern, GLOB_BRACE, $recursive);
+ $filesFound = FilesUtil::globFileSearch($globPattern, \GLOB_BRACE, $recursive);
+
if ($filesFound === false || empty($filesFound)) {
return $this;
}
- if (!empty($localPath) && is_string($localPath)) {
+
+ if (!empty($localPath) && \is_string($localPath)) {
$localPath = trim($localPath, '/\\') . '/';
} else {
- $localPath = "/";
+ $localPath = '/';
}
/**
@@ -740,26 +834,30 @@ class ZipFile implements ZipFileInterface
foreach ($filesFound as $file) {
$filename = str_replace($inputDir, $localPath, $file);
$filename = ltrim($filename, '\\/');
+
if (is_dir($file) && FilesUtil::isEmptyDir($file)) {
$this->addEmptyDir($filename);
} elseif (is_file($file)) {
$this->addFile($file, $filename, $compressionMethod);
}
}
+
return $this;
}
/**
* Add files recursively from glob pattern.
*
- * @param string $inputDir Input directory
- * @param string $globPattern Glob pattern.
- * @param string|null $localPath Add files to this directory, or the root.
- * @param int|null $compressionMethod Compression method.
- * Use ZipFile::METHOD_STORED, ZipFile::METHOD_DEFLATED or ZipFile::METHOD_BZIP2.
- * If null, then auto choosing method.
- * @return ZipFileInterface
+ * @param string $inputDir Input directory
+ * @param string $globPattern glob pattern
+ * @param string|null $localPath add files to this directory, or the root
+ * @param int|null $compressionMethod Compression method.
+ * Use ZipFile::METHOD_STORED, ZipFile::METHOD_DEFLATED or
+ * ZipFile::METHOD_BZIP2. If null, then auto choosing method.
+ *
* @throws ZipException
+ *
+ * @return ZipFileInterface
* @sse https://en.wikipedia.org/wiki/Glob_(programming) Glob pattern syntax
*/
public function addFilesFromGlobRecursive($inputDir, $globPattern, $localPath = '/', $compressionMethod = null)
@@ -770,17 +868,20 @@ class ZipFile implements ZipFileInterface
/**
* Add files from regex pattern.
*
- * @param string $inputDir Search files in this directory.
- * @param string $regexPattern Regex pattern.
- * @param string|null $localPath Add files to this directory, or the root.
- * @param int|null $compressionMethod Compression method.
- * Use ZipFile::METHOD_STORED, ZipFile::METHOD_DEFLATED or ZipFile::METHOD_BZIP2.
- * If null, then auto choosing method.
- * @return ZipFileInterface
+ * @param string $inputDir search files in this directory
+ * @param string $regexPattern regex pattern
+ * @param string|null $localPath add files to this directory, or the root
+ * @param int|null $compressionMethod Compression method.
+ * Use ZipFile::METHOD_STORED, ZipFile::METHOD_DEFLATED or
+ * ZipFile::METHOD_BZIP2. If null, then auto choosing method.
+ *
* @throws ZipException
- * @internal param bool $recursive Recursive search.
+ *
+ * @return ZipFileInterface
+ *
+ * @internal param bool $recursive Recursive search
*/
- public function addFilesFromRegex($inputDir, $regexPattern, $localPath = "/", $compressionMethod = null)
+ public function addFilesFromRegex($inputDir, $regexPattern, $localPath = '/', $compressionMethod = null)
{
return $this->addRegex($inputDir, $regexPattern, $localPath, false, $compressionMethod);
}
@@ -788,46 +889,53 @@ class ZipFile implements ZipFileInterface
/**
* Add files from regex pattern.
*
- * @param string $inputDir Search files in this directory.
- * @param string $regexPattern Regex pattern.
- * @param string|null $localPath Add files to this directory, or the root.
- * @param bool $recursive Recursive search.
- * @param int|null $compressionMethod Compression method.
- * Use ZipFile::METHOD_STORED, ZipFile::METHOD_DEFLATED or ZipFile::METHOD_BZIP2.
- * If null, then auto choosing method.
- * @return ZipFileInterface
+ * @param string $inputDir search files in this directory
+ * @param string $regexPattern regex pattern
+ * @param string|null $localPath add files to this directory, or the root
+ * @param bool $recursive recursive search
+ * @param int|null $compressionMethod Compression method.
+ * Use ZipFile::METHOD_STORED, ZipFile::METHOD_DEFLATED or
+ * ZipFile::METHOD_BZIP2. If null, then auto choosing method.
+ *
* @throws ZipException
+ *
+ * @return ZipFileInterface
*/
private function addRegex(
$inputDir,
$regexPattern,
- $localPath = "/",
+ $localPath = '/',
$recursive = true,
$compressionMethod = null
) {
- $regexPattern = (string)$regexPattern;
+ $regexPattern = (string) $regexPattern;
+
if (empty($regexPattern)) {
throw new InvalidArgumentException('The regex pattern is not specified');
}
- $inputDir = (string)$inputDir;
- if (strlen($inputDir) === 0) {
+ $inputDir = (string) $inputDir;
+
+ if ($inputDir === '') {
throw new InvalidArgumentException('The input directory is not specified');
}
+
if (!is_dir($inputDir)) {
throw new InvalidArgumentException(sprintf('The "%s" directory does not exist.', $inputDir));
}
- $inputDir = rtrim($inputDir, '/\\') . DIRECTORY_SEPARATOR;
+ $inputDir = rtrim($inputDir, '/\\') . \DIRECTORY_SEPARATOR;
$files = FilesUtil::regexFileSearch($inputDir, $regexPattern, $recursive);
+
if (empty($files)) {
return $this;
}
- if (!empty($localPath) && is_string($localPath)) {
+
+ if (!empty($localPath) && \is_string($localPath)) {
$localPath = trim($localPath, '\\/') . '/';
} else {
- $localPath = "/";
+ $localPath = '/';
}
- $inputDir = rtrim($inputDir, '/\\') . DIRECTORY_SEPARATOR;
+ $inputDir = rtrim($inputDir, '/\\') . \DIRECTORY_SEPARATOR;
/**
* @var string $file
@@ -835,29 +943,34 @@ class ZipFile implements ZipFileInterface
foreach ($files as $file) {
$filename = str_replace($inputDir, $localPath, $file);
$filename = ltrim($filename, '\\/');
+
if (is_dir($file) && FilesUtil::isEmptyDir($file)) {
$this->addEmptyDir($filename);
} elseif (is_file($file)) {
$this->addFile($file, $filename, $compressionMethod);
}
}
+
return $this;
}
/**
* Add files recursively from regex pattern.
*
- * @param string $inputDir Search files in this directory.
- * @param string $regexPattern Regex pattern.
- * @param string|null $localPath Add files to this directory, or the root.
- * @param int|null $compressionMethod Compression method.
- * Use ZipFile::METHOD_STORED, ZipFile::METHOD_DEFLATED or ZipFile::METHOD_BZIP2.
- * If null, then auto choosing method.
- * @return ZipFileInterface
+ * @param string $inputDir search files in this directory
+ * @param string $regexPattern regex pattern
+ * @param string|null $localPath add files to this directory, or the root
+ * @param int|null $compressionMethod Compression method.
+ * Use ZipFile::METHOD_STORED, ZipFile::METHOD_DEFLATED or
+ * ZipFile::METHOD_BZIP2. If null, then auto choosing method.
+ *
* @throws ZipException
- * @internal param bool $recursive Recursive search.
+ *
+ * @return ZipFileInterface
+ *
+ * @internal param bool $recursive Recursive search
*/
- public function addFilesFromRegexRecursive($inputDir, $regexPattern, $localPath = "/", $compressionMethod = null)
+ public function addFilesFromRegexRecursive($inputDir, $regexPattern, $localPath = '/', $compressionMethod = null)
{
return $this->addRegex($inputDir, $regexPattern, $localPath, true, $compressionMethod);
}
@@ -867,7 +980,7 @@ class ZipFile implements ZipFileInterface
* Keys is local names.
* Values is contents.
*
- * @param array $mapData Associative array for added to zip.
+ * @param array $mapData associative array for added to zip
*/
public function addAll(array $mapData)
{
@@ -879,37 +992,45 @@ class ZipFile implements ZipFileInterface
/**
* Rename the entry.
*
- * @param string $oldName Old entry name.
- * @param string $newName New entry name.
- * @return ZipFileInterface
+ * @param string $oldName old entry name
+ * @param string $newName new entry name
+ *
* @throws ZipException
+ *
+ * @return ZipFileInterface
*/
public function rename($oldName, $newName)
{
if ($oldName === null || $newName === null) {
- throw new InvalidArgumentException("name is null");
+ throw new InvalidArgumentException('name is null');
}
- $oldName = ltrim((string)$oldName, '\\/');
- $newName = ltrim((string)$newName, '\\/');
+ $oldName = ltrim((string) $oldName, '\\/');
+ $newName = ltrim((string) $newName, '\\/');
+
if ($oldName !== $newName) {
$this->zipModel->renameEntry($oldName, $newName);
}
+
return $this;
}
/**
* Delete entry by name.
*
- * @param string $entryName Zip Entry name.
+ * @param string $entryName zip Entry name
+ *
+ * @throws ZipEntryNotFoundException if entry not found
+ *
* @return ZipFileInterface
- * @throws ZipEntryNotFoundException If entry not found.
*/
public function deleteFromName($entryName)
{
- $entryName = ltrim((string)$entryName, '\\/');
+ $entryName = ltrim((string) $entryName, '\\/');
+
if (!$this->zipModel->deleteEntry($entryName)) {
throw new ZipEntryNotFoundException($entryName);
}
+
return $this;
}
@@ -917,16 +1038,18 @@ class ZipFile implements ZipFileInterface
* Delete entries by glob pattern.
*
* @param string $globPattern Glob pattern
+ *
* @return ZipFileInterface
* @sse https://en.wikipedia.org/wiki/Glob_(programming) Glob pattern syntax
*/
public function deleteFromGlob($globPattern)
{
- if ($globPattern === null || !is_string($globPattern) || empty($globPattern)) {
- throw new InvalidArgumentException("The glob pattern is not specified");
+ if ($globPattern === null || !\is_string($globPattern) || empty($globPattern)) {
+ throw new InvalidArgumentException('The glob pattern is not specified');
}
$globPattern = '~' . FilesUtil::convertGlobToRegEx($globPattern) . '~si';
$this->deleteFromRegex($globPattern);
+
return $this;
}
@@ -934,24 +1057,28 @@ class ZipFile implements ZipFileInterface
* Delete entries by regex pattern.
*
* @param string $regexPattern Regex pattern
+ *
* @return ZipFileInterface
*/
public function deleteFromRegex($regexPattern)
{
- if ($regexPattern === null || !is_string($regexPattern) || empty($regexPattern)) {
- throw new InvalidArgumentException("The regex pattern is not specified");
+ if ($regexPattern === null || !\is_string($regexPattern) || empty($regexPattern)) {
+ throw new InvalidArgumentException('The regex pattern is not specified');
}
$this->matcher()->match($regexPattern)->delete();
+
return $this;
}
/**
- * Delete all entries
+ * Delete all entries.
+ *
* @return ZipFileInterface
*/
public function deleteAll()
{
$this->zipModel->deleteAll();
+
return $this;
}
@@ -959,7 +1086,9 @@ class ZipFile implements ZipFileInterface
* Set compression level for new entries.
*
* @param int $compressionLevel
+ *
* @return ZipFileInterface
+ *
* @see ZipFileInterface::LEVEL_DEFAULT_COMPRESSION
* @see ZipFileInterface::LEVEL_SUPER_FAST
* @see ZipFileInterface::LEVEL_FAST
@@ -970,20 +1099,28 @@ class ZipFile implements ZipFileInterface
if ($compressionLevel < self::LEVEL_DEFAULT_COMPRESSION ||
$compressionLevel > self::LEVEL_BEST_COMPRESSION
) {
- throw new InvalidArgumentException('Invalid compression level. Minimum level ' .
- self::LEVEL_DEFAULT_COMPRESSION . '. Maximum level ' . self::LEVEL_BEST_COMPRESSION);
+ throw new InvalidArgumentException(
+ 'Invalid compression level. Minimum level ' .
+ self::LEVEL_DEFAULT_COMPRESSION . '. Maximum level ' . self::LEVEL_BEST_COMPRESSION
+ );
}
- $this->matcher()->all()->invoke(function ($entry) use ($compressionLevel) {
- $this->setCompressionLevelEntry($entry, $compressionLevel);
- });
+ $this->matcher()->all()->invoke(
+ function ($entry) use ($compressionLevel) {
+ $this->setCompressionLevelEntry($entry, $compressionLevel);
+ }
+ );
+
return $this;
}
/**
* @param string $entryName
- * @param int $compressionLevel
- * @return ZipFileInterface
+ * @param int $compressionLevel
+ *
* @throws ZipException
+ *
+ * @return ZipFileInterface
+ *
* @see ZipFileInterface::LEVEL_DEFAULT_COMPRESSION
* @see ZipFileInterface::LEVEL_SUPER_FAST
* @see ZipFileInterface::LEVEL_FAST
@@ -995,38 +1132,48 @@ class ZipFile implements ZipFileInterface
if ($compressionLevel < ZipFileInterface::LEVEL_DEFAULT_COMPRESSION ||
$compressionLevel > ZipFileInterface::LEVEL_BEST_COMPRESSION
) {
- throw new InvalidArgumentException('Invalid compression level. Minimum level ' .
- self::LEVEL_DEFAULT_COMPRESSION . '. Maximum level ' . self::LEVEL_BEST_COMPRESSION);
+ throw new InvalidArgumentException(
+ 'Invalid compression level. Minimum level ' .
+ self::LEVEL_DEFAULT_COMPRESSION . '. Maximum level ' . self::LEVEL_BEST_COMPRESSION
+ );
}
$entry = $this->zipModel->getEntry($entryName);
+
if ($compressionLevel !== $entry->getCompressionLevel()) {
$entry = $this->zipModel->getEntryForChanges($entry);
$entry->setCompressionLevel($compressionLevel);
}
}
+
return $this;
}
/**
* @param string $entryName
- * @param int $compressionMethod
- * @return ZipFileInterface
+ * @param int $compressionMethod
+ *
* @throws ZipException
+ *
+ * @return ZipFileInterface
+ *
* @see ZipFileInterface::METHOD_STORED
* @see ZipFileInterface::METHOD_DEFLATED
* @see ZipFileInterface::METHOD_BZIP2
*/
public function setCompressionMethodEntry($entryName, $compressionMethod)
{
- if (!in_array($compressionMethod, self::$allowCompressionMethods, true)) {
+ if (!\in_array($compressionMethod, self::$allowCompressionMethods, true)) {
throw new ZipUnsupportMethodException('Unsupported method ' . $compressionMethod);
}
$entry = $this->zipModel->getEntry($entryName);
+
if ($compressionMethod !== $entry->getMethod()) {
$this->zipModel
->getEntryForChanges($entry)
- ->setMethod($compressionMethod);
+ ->setMethod($compressionMethod)
+ ;
}
+
return $this;
}
@@ -1034,12 +1181,15 @@ class ZipFile implements ZipFileInterface
* zipalign is optimization to Android application (APK) files.
*
* @param int|null $align
+ *
* @return ZipFileInterface
- * @link https://developer.android.com/studio/command-line/zipalign.html
+ *
+ * @see https://developer.android.com/studio/command-line/zipalign.html
*/
public function setZipAlign($align = null)
{
$this->zipModel->setZipAlign($align);
+
return $this;
}
@@ -1047,8 +1197,11 @@ class ZipFile implements ZipFileInterface
* Set password to all input encrypted entries.
*
* @param string $password Password
- * @return ZipFileInterface
+ *
* @throws ZipException
+ *
+ * @return ZipFileInterface
+ *
* @deprecated using ZipFileInterface::setReadPassword()
*/
public function withReadPassword($password)
@@ -1060,12 +1213,15 @@ class ZipFile implements ZipFileInterface
* Set password to all input encrypted entries.
*
* @param string $password Password
- * @return ZipFileInterface
+ *
* @throws ZipException
+ *
+ * @return ZipFileInterface
*/
public function setReadPassword($password)
{
$this->zipModel->setReadPassword($password);
+
return $this;
}
@@ -1073,24 +1229,30 @@ class ZipFile implements ZipFileInterface
* Set password to concrete input entry.
*
* @param string $entryName
- * @param string $password Password
- * @return ZipFileInterface
+ * @param string $password Password
+ *
* @throws ZipException
+ *
+ * @return ZipFileInterface
*/
public function setReadPasswordEntry($entryName, $password)
{
$this->zipModel->setReadPasswordEntry($entryName, $password);
+
return $this;
}
/**
* Set password for all entries for update.
*
- * @param string $password If password null then encryption clear
+ * @param string $password If password null then encryption clear
* @param int|null $encryptionMethod Encryption method
- * @return ZipFileInterface
- * @deprecated using ZipFileInterface::setPassword()
+ *
* @throws ZipException
+ *
+ * @return ZipFileInterface
+ *
+ * @deprecated using ZipFileInterface::setPassword()
*/
public function withNewPassword($password, $encryptionMethod = self::ENCRYPTION_METHOD_WINZIP_AES_256)
{
@@ -1100,46 +1262,53 @@ class ZipFile implements ZipFileInterface
/**
* Sets a new password for all files in the archive.
*
- * @param string $password
+ * @param string $password
* @param int|null $encryptionMethod Encryption method
- * @return ZipFileInterface
+ *
* @throws ZipException
+ *
+ * @return ZipFileInterface
*/
public function setPassword($password, $encryptionMethod = self::ENCRYPTION_METHOD_WINZIP_AES_256)
{
$this->zipModel->setWritePassword($password);
+
if ($encryptionMethod !== null) {
- if (!in_array($encryptionMethod, self::$allowEncryptionMethods, true)) {
+ if (!\in_array($encryptionMethod, self::$allowEncryptionMethods, true)) {
throw new ZipException('Invalid encryption method "' . $encryptionMethod . '"');
}
$this->zipModel->setEncryptionMethod($encryptionMethod);
}
+
return $this;
}
/**
* Sets a new password of an entry defined by its name.
*
- * @param string $entryName
- * @param string $password
+ * @param string $entryName
+ * @param string $password
* @param int|null $encryptionMethod
- * @return ZipFileInterface
+ *
* @throws ZipException
+ *
+ * @return ZipFileInterface
*/
public function setPasswordEntry($entryName, $password, $encryptionMethod = null)
{
- if ($encryptionMethod !== null) {
- if (!in_array($encryptionMethod, self::$allowEncryptionMethods, true)) {
- throw new ZipException('Invalid encryption method "' . $encryptionMethod . '"');
- }
+ if ($encryptionMethod !== null && !\in_array($encryptionMethod, self::$allowEncryptionMethods, true)) {
+ throw new ZipException('Invalid encryption method "' . $encryptionMethod . '"');
}
$this->matcher()->add($entryName)->setPassword($password, $encryptionMethod);
+
return $this;
}
/**
* Remove password for all entries for update.
+ *
* @return ZipFileInterface
+ *
* @deprecated using ZipFileInterface::disableEncryption()
*/
public function withoutPassword()
@@ -1149,42 +1318,51 @@ class ZipFile implements ZipFileInterface
/**
* Disable encryption for all entries that are already in the archive.
+ *
* @return ZipFileInterface
*/
public function disableEncryption()
{
$this->zipModel->removePassword();
+
return $this;
}
/**
* Disable encryption of an entry defined by its name.
+ *
* @param string $entryName
+ *
* @return ZipFileInterface
*/
public function disableEncryptionEntry($entryName)
{
$this->zipModel->removePasswordEntry($entryName);
+
return $this;
}
/**
- * Undo all changes done in the archive
+ * Undo all changes done in the archive.
+ *
* @return ZipFileInterface
*/
public function unchangeAll()
{
$this->zipModel->unchangeAll();
+
return $this;
}
/**
- * Undo change archive comment
+ * Undo change archive comment.
+ *
* @return ZipFileInterface
*/
public function unchangeArchiveComment()
{
$this->zipModel->unchangeArchiveComment();
+
return $this;
}
@@ -1192,11 +1370,13 @@ class ZipFile implements ZipFileInterface
* Revert all changes done to an entry with the given name.
*
* @param string|ZipEntry $entry Entry name or ZipEntry
+ *
* @return ZipFileInterface
*/
public function unchangeEntry($entry)
{
$this->zipModel->unchangeEntry($entry);
+
return $this;
}
@@ -1204,16 +1384,19 @@ class ZipFile implements ZipFileInterface
* Save as file.
*
* @param string $filename Output filename
- * @return ZipFileInterface
+ *
* @throws ZipException
+ *
+ * @return ZipFileInterface
*/
public function saveAsFile($filename)
{
- $filename = (string)$filename;
+ $filename = (string) $filename;
$tempFilename = $filename . '.temp' . uniqid('', true);
+
if (!($handle = @fopen($tempFilename, 'w+b'))) {
- throw new InvalidArgumentException("File " . $tempFilename . ' can not open from write.');
+ throw new InvalidArgumentException('File ' . $tempFilename . ' can not open from write.');
}
$this->saveAsStream($handle);
@@ -1221,8 +1404,10 @@ class ZipFile implements ZipFileInterface
if (is_file($tempFilename)) {
unlink($tempFilename);
}
+
throw new ZipException('Can not move ' . $tempFilename . ' to ' . $filename);
}
+
return $this;
}
@@ -1230,17 +1415,20 @@ class ZipFile implements ZipFileInterface
* Save as stream.
*
* @param resource $handle Output stream resource
- * @return ZipFileInterface
+ *
* @throws ZipException
+ *
+ * @return ZipFileInterface
*/
public function saveAsStream($handle)
{
- if (!is_resource($handle)) {
+ if (!\is_resource($handle)) {
throw new InvalidArgumentException('handle is not resource');
}
ftruncate($handle, 0);
$this->writeZipToStream($handle);
fclose($handle);
+
return $this;
}
@@ -1248,22 +1436,24 @@ class ZipFile implements ZipFileInterface
* Output .ZIP archive as attachment.
* Die after output.
*
- * @param string $outputFilename Output filename
- * @param string|null $mimeType Mime-Type
- * @param bool $attachment Http Header 'Content-Disposition' if true then attachment otherwise inline
+ * @param string $outputFilename Output filename
+ * @param string|null $mimeType Mime-Type
+ * @param bool $attachment Http Header 'Content-Disposition' if true then attachment otherwise inline
+ *
* @throws ZipException
*/
public function outputAsAttachment($outputFilename, $mimeType = null, $attachment = true)
{
- $outputFilename = (string)$outputFilename;
+ $outputFilename = (string) $outputFilename;
- if (empty($mimeType) || (!is_string($mimeType) && !empty($outputFilename))) {
- $ext = strtolower(pathinfo($outputFilename, PATHINFO_EXTENSION));
+ if (empty($mimeType) || (!\is_string($mimeType) && !empty($outputFilename))) {
+ $ext = strtolower(pathinfo($outputFilename, \PATHINFO_EXTENSION));
if (!empty($ext) && isset(self::$defaultMimeTypes[$ext])) {
$mimeType = self::$defaultMimeTypes[$ext];
}
}
+
if (empty($mimeType)) {
$mimeType = self::$defaultMimeTypes['zip'];
}
@@ -1272,62 +1462,71 @@ class ZipFile implements ZipFileInterface
$this->close();
$headerContentDisposition = 'Content-Disposition: ' . ($attachment ? 'attachment' : 'inline');
+
if (!empty($outputFilename)) {
$headerContentDisposition .= '; filename="' . basename($outputFilename) . '"';
}
header($headerContentDisposition);
- header("Content-Type: " . $mimeType);
- header("Content-Length: " . strlen($content));
+ header('Content-Type: ' . $mimeType);
+ header('Content-Length: ' . \strlen($content));
+
exit($content);
}
/**
* Output .ZIP archive as PSR-7 Response.
*
- * @param ResponseInterface $response Instance PSR-7 Response
- * @param string $outputFilename Output filename
- * @param string|null $mimeType Mime-Type
- * @param bool $attachment Http Header 'Content-Disposition' if true then attachment otherwise inline
- * @return ResponseInterface
+ * @param ResponseInterface $response Instance PSR-7 Response
+ * @param string $outputFilename Output filename
+ * @param string|null $mimeType Mime-Type
+ * @param bool $attachment Http Header 'Content-Disposition' if true then attachment otherwise inline
+ *
* @throws ZipException
+ *
+ * @return ResponseInterface
*/
public function outputAsResponse(ResponseInterface $response, $outputFilename, $mimeType = null, $attachment = true)
{
- $outputFilename = (string)$outputFilename;
+ $outputFilename = (string) $outputFilename;
- if (empty($mimeType) || (!is_string($mimeType) && !empty($outputFilename))) {
- $ext = strtolower(pathinfo($outputFilename, PATHINFO_EXTENSION));
+ if (empty($mimeType) || (!\is_string($mimeType) && !empty($outputFilename))) {
+ $ext = strtolower(pathinfo($outputFilename, \PATHINFO_EXTENSION));
if (!empty($ext) && isset(self::$defaultMimeTypes[$ext])) {
$mimeType = self::$defaultMimeTypes[$ext];
}
}
+
if (empty($mimeType)) {
$mimeType = self::$defaultMimeTypes['zip'];
}
if (!($handle = fopen('php://memory', 'w+b'))) {
- throw new InvalidArgumentException("Memory can not open from write.");
+ throw new InvalidArgumentException('Memory can not open from write.');
}
$this->writeZipToStream($handle);
rewind($handle);
$contentDispositionValue = ($attachment ? 'attachment' : 'inline');
+
if (!empty($outputFilename)) {
$contentDispositionValue .= '; filename="' . basename($outputFilename) . '"';
}
$stream = new ResponseStream($handle);
+
return $response
->withHeader('Content-Type', $mimeType)
->withHeader('Content-Disposition', $contentDispositionValue)
->withHeader('Content-Length', $stream->getSize())
- ->withBody($stream);
+ ->withBody($stream)
+ ;
}
/**
* @param resource $handle
+ *
* @throws ZipException
*/
protected function writeZipToStream($handle)
@@ -1340,18 +1539,21 @@ class ZipFile implements ZipFileInterface
/**
* Returns the zip archive as a string.
- * @return string
+ *
* @throws ZipException
+ *
+ * @return string
*/
public function outputAsString()
{
if (!($handle = fopen('php://memory', 'w+b'))) {
- throw new InvalidArgumentException("Memory can not open from write.");
+ throw new InvalidArgumentException('Memory can not open from write.');
}
$this->writeZipToStream($handle);
rewind($handle);
$content = stream_get_contents($handle);
fclose($handle);
+
return $content;
}
@@ -1376,8 +1578,10 @@ class ZipFile implements ZipFileInterface
/**
* Save and reopen zip archive.
- * @return ZipFileInterface
+ *
* @throws ZipException
+ *
+ * @return ZipFileInterface
*/
public function rewrite()
{
@@ -1387,24 +1591,29 @@ class ZipFile implements ZipFileInterface
$meta = stream_get_meta_data($this->inputStream->getStream());
$content = $this->outputAsString();
$this->close();
+
if ($meta['wrapper_type'] === 'plainfile') {
/**
* @var resource $uri
*/
$uri = $meta['uri'];
+
if (file_put_contents($uri, $content) === false) {
- throw new ZipException("Can not overwrite the zip file in the $uri file.");
+ throw new ZipException("Can not overwrite the zip file in the {$uri} file.");
}
+
if (!($handle = @fopen($uri, 'rb'))) {
- throw new ZipException("File $uri can't open.");
+ throw new ZipException("File {$uri} can't open.");
}
+
return $this->openFromStream($handle);
}
+
return $this->openFromString($content);
}
/**
- * Release all resources
+ * Release all resources.
*/
public function __destruct()
{
@@ -1412,11 +1621,15 @@ class ZipFile implements ZipFileInterface
}
/**
- * Offset to set
- * @link http://php.net/manual/en/arrayaccess.offsetset.php
- * @param string $entryName The offset to assign the value to.
- * @param mixed $contents The value to set.
+ * Offset to set.
+ *
+ * @see http://php.net/manual/en/arrayaccess.offsetset.php
+ *
+ * @param string $entryName the offset to assign the value to
+ * @param mixed $contents the value to set
+ *
* @throws ZipException
+ *
* @see ZipFile::addFromString
* @see ZipFile::addEmptyDir
* @see ZipFile::addFile
@@ -1427,31 +1640,39 @@ class ZipFile implements ZipFileInterface
if ($entryName === null) {
throw new InvalidArgumentException('entryName is null');
}
- $entryName = ltrim((string)$entryName, "\\/");
- if (strlen($entryName) === 0) {
+ $entryName = ltrim((string) $entryName, '\\/');
+
+ if ($entryName === '') {
throw new InvalidArgumentException('entryName is empty');
}
+
if ($contents instanceof \SplFileInfo) {
if ($contents instanceof \DirectoryIterator) {
$this->addFilesFromIterator($contents, $entryName);
+
return;
}
$this->addFile($contents->getPathname(), $entryName);
+
return;
}
+
if (StringUtil::endsWith($entryName, '/')) {
$this->addEmptyDir($entryName);
- } elseif (is_resource($contents)) {
+ } elseif (\is_resource($contents)) {
$this->addFromStream($contents, $entryName);
} else {
- $this->addFromString($entryName, (string)$contents);
+ $this->addFromString($entryName, (string) $contents);
}
}
/**
- * Offset to unset
- * @link http://php.net/manual/en/arrayaccess.offsetunset.php
- * @param string $entryName The offset to unset.
+ * Offset to unset.
+ *
+ * @see http://php.net/manual/en/arrayaccess.offsetunset.php
+ *
+ * @param string $entryName the offset to unset
+ *
* @throws ZipEntryNotFoundException
*/
public function offsetUnset($entryName)
@@ -1460,11 +1681,15 @@ class ZipFile implements ZipFileInterface
}
/**
- * Return the current element
- * @link http://php.net/manual/en/iterator.current.php
- * @return mixed Can return any type.
- * @since 5.0.0
+ * Return the current element.
+ *
+ * @see http://php.net/manual/en/iterator.current.php
+ *
* @throws ZipException
+ *
+ * @return mixed can return any type
+ *
+ * @since 5.0.0
*/
public function current()
{
@@ -1472,11 +1697,15 @@ class ZipFile implements ZipFileInterface
}
/**
- * Offset to retrieve
- * @link http://php.net/manual/en/arrayaccess.offsetget.php
- * @param string $entryName The offset to retrieve.
- * @return string|null
+ * Offset to retrieve.
+ *
+ * @see http://php.net/manual/en/arrayaccess.offsetget.php
+ *
+ * @param string $entryName the offset to retrieve
+ *
* @throws ZipException
+ *
+ * @return string|null
*/
public function offsetGet($entryName)
{
@@ -1484,9 +1713,12 @@ class ZipFile implements ZipFileInterface
}
/**
- * Return the key of the current element
- * @link http://php.net/manual/en/iterator.key.php
- * @return mixed scalar on success, or null on failure.
+ * Return the key of the current element.
+ *
+ * @see http://php.net/manual/en/iterator.key.php
+ *
+ * @return mixed scalar on success, or null on failure
+ *
* @since 5.0.0
*/
public function key()
@@ -1495,9 +1727,9 @@ class ZipFile implements ZipFileInterface
}
/**
- * Move forward to next element
- * @link http://php.net/manual/en/iterator.next.php
- * @return void Any returned value is ignored.
+ * Move forward to next element.
+ *
+ * @see http://php.net/manual/en/iterator.next.php
* @since 5.0.0
*/
public function next()
@@ -1506,10 +1738,13 @@ class ZipFile implements ZipFileInterface
}
/**
- * Checks if current position is valid
- * @link http://php.net/manual/en/iterator.valid.php
- * @return boolean The return value will be casted to boolean and then evaluated.
- * Returns true on success or false on failure.
+ * Checks if current position is valid.
+ *
+ * @see http://php.net/manual/en/iterator.valid.php
+ *
+ * @return bool The return value will be casted to boolean and then evaluated.
+ * Returns true on success or false on failure.
+ *
* @since 5.0.0
*/
public function valid()
@@ -1518,11 +1753,14 @@ class ZipFile implements ZipFileInterface
}
/**
- * Whether a offset exists
- * @link http://php.net/manual/en/arrayaccess.offsetexists.php
- * @param string $entryName An offset to check for.
- * @return boolean true on success or false on failure.
- * The return value will be casted to boolean if non-boolean was returned.
+ * Whether a offset exists.
+ *
+ * @see http://php.net/manual/en/arrayaccess.offsetexists.php
+ *
+ * @param string $entryName an offset to check for
+ *
+ * @return bool true on success or false on failure.
+ * The return value will be casted to boolean if non-boolean was returned.
*/
public function offsetExists($entryName)
{
@@ -1530,9 +1768,9 @@ class ZipFile implements ZipFileInterface
}
/**
- * Rewind the Iterator to the first element
- * @link http://php.net/manual/en/iterator.rewind.php
- * @return void Any returned value is ignored.
+ * Rewind the Iterator to the first element.
+ *
+ * @see http://php.net/manual/en/iterator.rewind.php
* @since 5.0.0
*/
public function rewind()
diff --git a/src/PhpZip/ZipFileInterface.php b/src/PhpZip/ZipFileInterface.php
index 2237283..b876cc4 100644
--- a/src/PhpZip/ZipFileInterface.php
+++ b/src/PhpZip/ZipFileInterface.php
@@ -18,6 +18,7 @@ use Psr\Http\Message\ResponseInterface;
* Support ZipAlign functional.
*
* @see https://pkware.cachefly.net/webdocs/casestudies/APPNOTE.TXT .ZIP File Format Specification
+ *
* @author Ne-Lexa alexey@nelexa.ru
* @license MIT
*/
@@ -25,67 +26,66 @@ interface ZipFileInterface extends \Countable, \ArrayAccess, \Iterator
{
/**
* Method for Stored (uncompressed) entries.
+ *
* @see ZipEntry::setMethod()
*/
const METHOD_STORED = 0;
+
/**
* Method for Deflated compressed entries.
+ *
* @see ZipEntry::setMethod()
*/
const METHOD_DEFLATED = 8;
+
/**
* Method for BZIP2 compressed entries.
* Require php extension bz2.
+ *
* @see ZipEntry::setMethod()
*/
const METHOD_BZIP2 = 12;
- /**
- * Default compression level.
- */
+ /** Default compression level. */
const LEVEL_DEFAULT_COMPRESSION = -1;
- /**
- * Compression level for fastest compression.
- */
+
+ /** Compression level for fastest compression. */
const LEVEL_FAST = 2;
- /**
- * Compression level for fastest compression.
- */
+
+ /** Compression level for fastest compression. */
const LEVEL_BEST_SPEED = 1;
+
const LEVEL_SUPER_FAST = self::LEVEL_BEST_SPEED;
- /**
- * Compression level for best compression.
- */
+
+ /** Compression level for best compression. */
const LEVEL_BEST_COMPRESSION = 9;
- /**
- * No specified method for set encryption method to Traditional PKWARE encryption.
- */
+ /** No specified method for set encryption method to Traditional PKWARE encryption. */
const ENCRYPTION_METHOD_TRADITIONAL = 0;
+
/**
* No specified method for set encryption method to WinZip AES encryption.
- * Default value 256 bit
+ * Default value 256 bit.
*/
const ENCRYPTION_METHOD_WINZIP_AES = self::ENCRYPTION_METHOD_WINZIP_AES_256;
- /**
- * No specified method for set encryption method to WinZip AES encryption 128 bit.
- */
+
+ /** No specified method for set encryption method to WinZip AES encryption 128 bit. */
const ENCRYPTION_METHOD_WINZIP_AES_128 = 2;
- /**
- * No specified method for set encryption method to WinZip AES encryption 194 bit.
- */
+
+ /** No specified method for set encryption method to WinZip AES encryption 194 bit. */
const ENCRYPTION_METHOD_WINZIP_AES_192 = 3;
- /**
- * No specified method for set encryption method to WinZip AES encryption 256 bit.
- */
+
+ /** No specified method for set encryption method to WinZip AES encryption 256 bit. */
const ENCRYPTION_METHOD_WINZIP_AES_256 = 1;
/**
- * Open zip archive from file
+ * Open zip archive from file.
*
* @param string $filename
+ *
+ * @throws ZipException if can't open file
+ *
* @return ZipFileInterface
- * @throws ZipException if can't open file.
*/
public function openFile($filename);
@@ -93,35 +93,39 @@ interface ZipFileInterface extends \Countable, \ArrayAccess, \Iterator
* Open zip archive from raw string data.
*
* @param string $data
+ *
+ * @throws ZipException if can't open temp stream
+ *
* @return ZipFileInterface
- * @throws ZipException if can't open temp stream.
*/
public function openFromString($data);
/**
- * Open zip archive from stream resource
+ * Open zip archive from stream resource.
*
* @param resource $handle
+ *
* @return ZipFileInterface
*/
public function openFromStream($handle);
/**
- * @return string[] Returns the list files.
+ * @return string[] returns the list files
*/
public function getListFiles();
/**
* Returns the file comment.
*
- * @return string The file comment.
+ * @return string the file comment
*/
public function getArchiveComment();
/**
* Set archive comment.
*
- * @param null|string $comment
+ * @param string|null $comment
+ *
* @return ZipFileInterface
*/
public function setArchiveComment($comment = null);
@@ -132,8 +136,10 @@ interface ZipFileInterface extends \Countable, \ArrayAccess, \Iterator
* (i.e. end with '/').
*
* @param string $entryName
- * @return bool
+ *
* @throws ZipEntryNotFoundException
+ *
+ * @return bool
*/
public function isDirectory($entryName);
@@ -141,18 +147,22 @@ interface ZipFileInterface extends \Countable, \ArrayAccess, \Iterator
* Returns entry comment.
*
* @param string $entryName
- * @return string
+ *
* @throws ZipEntryNotFoundException
+ *
+ * @return string
*/
public function getEntryComment($entryName);
/**
* Set entry comment.
*
- * @param string $entryName
+ * @param string $entryName
* @param string|null $comment
- * @return ZipFileInterface
+ *
* @throws ZipEntryNotFoundException
+ *
+ * @return ZipFileInterface
*/
public function setEntryComment($entryName, $comment = null);
@@ -160,6 +170,7 @@ interface ZipFileInterface extends \Countable, \ArrayAccess, \Iterator
* Returns the entry contents.
*
* @param string $entryName
+ *
* @return string
*/
public function getEntryContents($entryName);
@@ -168,6 +179,7 @@ interface ZipFileInterface extends \Countable, \ArrayAccess, \Iterator
* Checks if there is an entry in the archive.
*
* @param string $entryName
+ *
* @return bool
*/
public function hasEntry($entryName);
@@ -176,8 +188,10 @@ interface ZipFileInterface extends \Countable, \ArrayAccess, \Iterator
* Get info by entry.
*
* @param string|ZipEntry $entryName
- * @return ZipInfo
+ *
* @throws ZipEntryNotFoundException
+ *
+ * @return ZipInfo
*/
public function getEntryInfo($entryName);
@@ -194,27 +208,31 @@ interface ZipFileInterface extends \Countable, \ArrayAccess, \Iterator
public function matcher();
/**
- * Extract the archive contents
+ * Extract the archive contents.
*
* Extract the complete archive or the given files to the specified destination.
*
- * @param string $destination Location where to extract the files.
- * @param array|string|null $entries The entries to extract. It accepts either
- * a single entry name or an array of names.
- * @return ZipFileInterface
+ * @param string $destination location where to extract the files
+ * @param array|string|null $entries The entries to extract. It accepts either
+ * a single entry name or an array of names.
+ *
* @throws ZipException
+ *
+ * @return ZipFileInterface
*/
public function extractTo($destination, $entries = null);
/**
* Add entry from the string.
*
- * @param string $localName Zip entry name.
- * @param string $contents String contents.
+ * @param string $localName zip entry name
+ * @param string $contents string contents
* @param int|null $compressionMethod Compression method.
- * Use ZipFile::METHOD_STORED, ZipFile::METHOD_DEFLATED or ZipFile::METHOD_BZIP2.
- * If null, then auto choosing method.
+ * Use ZipFile::METHOD_STORED, ZipFile::METHOD_DEFLATED or ZipFile::METHOD_BZIP2.
+ * If null, then auto choosing method.
+ *
* @return ZipFileInterface
+ *
* @see ZipFileInterface::METHOD_STORED
* @see ZipFileInterface::METHOD_DEFLATED
* @see ZipFileInterface::METHOD_BZIP2
@@ -224,12 +242,14 @@ interface ZipFileInterface extends \Countable, \ArrayAccess, \Iterator
/**
* Add entry from the file.
*
- * @param string $filename Destination file.
- * @param string|null $localName Zip Entry name.
- * @param int|null $compressionMethod Compression method.
- * Use ZipFile::METHOD_STORED, ZipFile::METHOD_DEFLATED or ZipFile::METHOD_BZIP2.
- * If null, then auto choosing method.
+ * @param string $filename destination file
+ * @param string|null $localName zip Entry name
+ * @param int|null $compressionMethod Compression method.
+ * Use ZipFile::METHOD_STORED, ZipFile::METHOD_DEFLATED or
+ * ZipFile::METHOD_BZIP2. If null, then auto choosing method.
+ *
* @return ZipFileInterface
+ *
* @see ZipFileInterface::METHOD_STORED
* @see ZipFileInterface::METHOD_DEFLATED
* @see ZipFileInterface::METHOD_BZIP2
@@ -239,12 +259,14 @@ interface ZipFileInterface extends \Countable, \ArrayAccess, \Iterator
/**
* Add entry from the stream.
*
- * @param resource $stream Stream resource.
- * @param string $localName Zip Entry name.
+ * @param resource $stream stream resource
+ * @param string $localName zip Entry name
* @param int|null $compressionMethod Compression method.
- * Use ZipFile::METHOD_STORED, ZipFile::METHOD_DEFLATED or ZipFile::METHOD_BZIP2.
- * If null, then auto choosing method.
+ * Use ZipFile::METHOD_STORED, ZipFile::METHOD_DEFLATED or ZipFile::METHOD_BZIP2.
+ * If null, then auto choosing method.
+ *
* @return ZipFileInterface
+ *
* @see ZipFileInterface::METHOD_STORED
* @see ZipFileInterface::METHOD_DEFLATED
* @see ZipFileInterface::METHOD_BZIP2
@@ -255,6 +277,7 @@ interface ZipFileInterface extends \Countable, \ArrayAccess, \Iterator
* Add an empty directory in the zip archive.
*
* @param string $dirName
+ *
* @return ZipFileInterface
*/
public function addEmptyDir($dirName);
@@ -262,39 +285,44 @@ interface ZipFileInterface extends \Countable, \ArrayAccess, \Iterator
/**
* Add directory not recursively to the zip archive.
*
- * @param string $inputDir Input directory
- * @param string $localPath Add files to this directory, or the root.
+ * @param string $inputDir Input directory
+ * @param string $localPath add files to this directory, or the root
* @param int|null $compressionMethod Compression method.
- * Use ZipFile::METHOD_STORED, ZipFile::METHOD_DEFLATED or ZipFile::METHOD_BZIP2.
- * If null, then auto choosing method.
+ * Use ZipFile::METHOD_STORED, ZipFile::METHOD_DEFLATED or ZipFile::METHOD_BZIP2.
+ * If null, then auto choosing method.
+ *
* @return ZipFileInterface
*/
- public function addDir($inputDir, $localPath = "/", $compressionMethod = null);
+ public function addDir($inputDir, $localPath = '/', $compressionMethod = null);
/**
* Add recursive directory to the zip archive.
*
- * @param string $inputDir Input directory
- * @param string $localPath Add files to this directory, or the root.
+ * @param string $inputDir Input directory
+ * @param string $localPath add files to this directory, or the root
* @param int|null $compressionMethod Compression method.
- * Use ZipFile::METHOD_STORED, ZipFile::METHOD_DEFLATED or ZipFile::METHOD_BZIP2.
- * If null, then auto choosing method.
+ * Use ZipFile::METHOD_STORED, ZipFile::METHOD_DEFLATED or ZipFile::METHOD_BZIP2.
+ * If null, then auto choosing method.
+ *
* @return ZipFileInterface
+ *
* @see ZipFileInterface::METHOD_STORED
* @see ZipFileInterface::METHOD_DEFLATED
* @see ZipFileInterface::METHOD_BZIP2
*/
- public function addDirRecursive($inputDir, $localPath = "/", $compressionMethod = null);
+ public function addDirRecursive($inputDir, $localPath = '/', $compressionMethod = null);
/**
* Add directories from directory iterator.
*
- * @param \Iterator $iterator Directory iterator.
- * @param string $localPath Add files to this directory, or the root.
- * @param int|null $compressionMethod Compression method.
- * Use ZipFile::METHOD_STORED, ZipFile::METHOD_DEFLATED or ZipFile::METHOD_BZIP2.
- * If null, then auto choosing method.
+ * @param \Iterator $iterator directory iterator
+ * @param string $localPath add files to this directory, or the root
+ * @param int|null $compressionMethod Compression method.
+ * Use ZipFile::METHOD_STORED, ZipFile::METHOD_DEFLATED or
+ * ZipFile::METHOD_BZIP2. If null, then auto choosing method.
+ *
* @return ZipFileInterface
+ *
* @see ZipFileInterface::METHOD_STORED
* @see ZipFileInterface::METHOD_DEFLATED
* @see ZipFileInterface::METHOD_BZIP2
@@ -304,12 +332,13 @@ interface ZipFileInterface extends \Countable, \ArrayAccess, \Iterator
/**
* Add files from glob pattern.
*
- * @param string $inputDir Input directory
- * @param string $globPattern Glob pattern.
- * @param string|null $localPath Add files to this directory, or the root.
- * @param int|null $compressionMethod Compression method.
- * Use ZipFile::METHOD_STORED, ZipFile::METHOD_DEFLATED or ZipFile::METHOD_BZIP2.
- * If null, then auto choosing method.
+ * @param string $inputDir Input directory
+ * @param string $globPattern glob pattern
+ * @param string|null $localPath add files to this directory, or the root
+ * @param int|null $compressionMethod Compression method.
+ * Use ZipFile::METHOD_STORED, ZipFile::METHOD_DEFLATED or
+ * ZipFile::METHOD_BZIP2. If null, then auto choosing method.
+ *
* @return ZipFileInterface
* @sse https://en.wikipedia.org/wiki/Glob_(programming) Glob pattern syntax
*/
@@ -318,12 +347,13 @@ interface ZipFileInterface extends \Countable, \ArrayAccess, \Iterator
/**
* Add files recursively from glob pattern.
*
- * @param string $inputDir Input directory
- * @param string $globPattern Glob pattern.
- * @param string|null $localPath Add files to this directory, or the root.
- * @param int|null $compressionMethod Compression method.
- * Use ZipFile::METHOD_STORED, ZipFile::METHOD_DEFLATED or ZipFile::METHOD_BZIP2.
- * If null, then auto choosing method.
+ * @param string $inputDir Input directory
+ * @param string $globPattern glob pattern
+ * @param string|null $localPath add files to this directory, or the root
+ * @param int|null $compressionMethod Compression method.
+ * Use ZipFile::METHOD_STORED, ZipFile::METHOD_DEFLATED or
+ * ZipFile::METHOD_BZIP2. If null, then auto choosing method.
+ *
* @return ZipFileInterface
* @sse https://en.wikipedia.org/wiki/Glob_(programming) Glob pattern syntax
*/
@@ -332,56 +362,64 @@ interface ZipFileInterface extends \Countable, \ArrayAccess, \Iterator
/**
* Add files from regex pattern.
*
- * @param string $inputDir Search files in this directory.
- * @param string $regexPattern Regex pattern.
- * @param string|null $localPath Add files to this directory, or the root.
- * @param int|null $compressionMethod Compression method.
- * Use ZipFile::METHOD_STORED, ZipFile::METHOD_DEFLATED or ZipFile::METHOD_BZIP2.
- * If null, then auto choosing method.
+ * @param string $inputDir search files in this directory
+ * @param string $regexPattern regex pattern
+ * @param string|null $localPath add files to this directory, or the root
+ * @param int|null $compressionMethod Compression method.
+ * Use ZipFile::METHOD_STORED, ZipFile::METHOD_DEFLATED or
+ * ZipFile::METHOD_BZIP2. If null, then auto choosing method.
+ *
* @return ZipFileInterface
- * @internal param bool $recursive Recursive search.
+ *
+ * @internal param bool $recursive Recursive search
*/
- public function addFilesFromRegex($inputDir, $regexPattern, $localPath = "/", $compressionMethod = null);
+ public function addFilesFromRegex($inputDir, $regexPattern, $localPath = '/', $compressionMethod = null);
/**
* Add files recursively from regex pattern.
*
- * @param string $inputDir Search files in this directory.
- * @param string $regexPattern Regex pattern.
- * @param string|null $localPath Add files to this directory, or the root.
- * @param int|null $compressionMethod Compression method.
- * Use ZipFile::METHOD_STORED, ZipFile::METHOD_DEFLATED or ZipFile::METHOD_BZIP2.
- * If null, then auto choosing method.
+ * @param string $inputDir search files in this directory
+ * @param string $regexPattern regex pattern
+ * @param string|null $localPath add files to this directory, or the root
+ * @param int|null $compressionMethod Compression method.
+ * Use ZipFile::METHOD_STORED, ZipFile::METHOD_DEFLATED or
+ * ZipFile::METHOD_BZIP2. If null, then auto choosing method.
+ *
* @return ZipFileInterface
- * @internal param bool $recursive Recursive search.
+ *
+ * @internal param bool $recursive Recursive search
*/
- public function addFilesFromRegexRecursive($inputDir, $regexPattern, $localPath = "/", $compressionMethod = null);
+ public function addFilesFromRegexRecursive($inputDir, $regexPattern, $localPath = '/', $compressionMethod = null);
/**
* Add array data to archive.
* Keys is local names.
* Values is contents.
*
- * @param array $mapData Associative array for added to zip.
+ * @param array $mapData associative array for added to zip
*/
public function addAll(array $mapData);
/**
* Rename the entry.
*
- * @param string $oldName Old entry name.
- * @param string $newName New entry name.
- * @return ZipFileInterface
+ * @param string $oldName old entry name
+ * @param string $newName new entry name
+ *
* @throws ZipEntryNotFoundException
+ *
+ * @return ZipFileInterface
*/
public function rename($oldName, $newName);
/**
* Delete entry by name.
*
- * @param string $entryName Zip Entry name.
+ * @param string $entryName zip Entry name
+ *
+ * @throws ZipEntryNotFoundException if entry not found
+ *
* @return ZipFileInterface
- * @throws ZipEntryNotFoundException If entry not found.
*/
public function deleteFromName($entryName);
@@ -389,6 +427,7 @@ interface ZipFileInterface extends \Countable, \ArrayAccess, \Iterator
* Delete entries by glob pattern.
*
* @param string $globPattern Glob pattern
+ *
* @return ZipFileInterface
* @sse https://en.wikipedia.org/wiki/Glob_(programming) Glob pattern syntax
*/
@@ -398,12 +437,14 @@ interface ZipFileInterface extends \Countable, \ArrayAccess, \Iterator
* Delete entries by regex pattern.
*
* @param string $regexPattern Regex pattern
+ *
* @return ZipFileInterface
*/
public function deleteFromRegex($regexPattern);
/**
- * Delete all entries
+ * Delete all entries.
+ *
* @return ZipFileInterface
*/
public function deleteAll();
@@ -412,19 +453,24 @@ interface ZipFileInterface extends \Countable, \ArrayAccess, \Iterator
* Set compression level for new entries.
*
* @param int $compressionLevel
- * @see ZipFileInterface::LEVEL_DEFAULT_COMPRESSION
+ *
+ * @return ZipFileInterface
+ *
* @see ZipFileInterface::LEVEL_SUPER_FAST
* @see ZipFileInterface::LEVEL_FAST
* @see ZipFileInterface::LEVEL_BEST_COMPRESSION
- * @return ZipFileInterface
+ * @see ZipFileInterface::LEVEL_DEFAULT_COMPRESSION
*/
public function setCompressionLevel($compressionLevel = self::LEVEL_DEFAULT_COMPRESSION);
/**
* @param string $entryName
- * @param int $compressionLevel
- * @return ZipFileInterface
+ * @param int $compressionLevel
+ *
* @throws ZipException
+ *
+ * @return ZipFileInterface
+ *
* @see ZipFileInterface::LEVEL_DEFAULT_COMPRESSION
* @see ZipFileInterface::LEVEL_SUPER_FAST
* @see ZipFileInterface::LEVEL_FAST
@@ -434,9 +480,12 @@ interface ZipFileInterface extends \Countable, \ArrayAccess, \Iterator
/**
* @param string $entryName
- * @param int $compressionMethod
- * @return ZipFileInterface
+ * @param int $compressionMethod
+ *
* @throws ZipException
+ *
+ * @return ZipFileInterface
+ *
* @see ZipFileInterface::METHOD_STORED
* @see ZipFileInterface::METHOD_DEFLATED
* @see ZipFileInterface::METHOD_BZIP2
@@ -447,8 +496,10 @@ interface ZipFileInterface extends \Countable, \ArrayAccess, \Iterator
* zipalign is optimization to Android application (APK) files.
*
* @param int|null $align
+ *
* @return ZipFileInterface
- * @link https://developer.android.com/studio/command-line/zipalign.html
+ *
+ * @see https://developer.android.com/studio/command-line/zipalign.html
*/
public function setZipAlign($align = null);
@@ -456,7 +507,9 @@ interface ZipFileInterface extends \Countable, \ArrayAccess, \Iterator
* Set password to all input encrypted entries.
*
* @param string $password Password
+ *
* @return ZipFileInterface
+ *
* @deprecated using ZipFileInterface::setReadPassword()
*/
public function withReadPassword($password);
@@ -465,6 +518,7 @@ interface ZipFileInterface extends \Countable, \ArrayAccess, \Iterator
* Set password to all input encrypted entries.
*
* @param string $password Password
+ *
* @return ZipFileInterface
*/
public function setReadPassword($password);
@@ -473,7 +527,8 @@ interface ZipFileInterface extends \Countable, \ArrayAccess, \Iterator
* Set password to concrete input entry.
*
* @param string $entryName
- * @param string $password Password
+ * @param string $password Password
+ *
* @return ZipFileInterface
*/
public function setReadPasswordEntry($entryName, $password);
@@ -481,9 +536,11 @@ interface ZipFileInterface extends \Countable, \ArrayAccess, \Iterator
/**
* Set password for all entries for update.
*
- * @param string $password If password null then encryption clear
+ * @param string $password If password null then encryption clear
* @param int|null $encryptionMethod Encryption method
+ *
* @return ZipFileInterface
+ *
* @deprecated using ZipFileInterface::setPassword()
*/
public function withNewPassword($password, $encryptionMethod = self::ENCRYPTION_METHOD_WINZIP_AES_256);
@@ -491,8 +548,9 @@ interface ZipFileInterface extends \Countable, \ArrayAccess, \Iterator
/**
* Sets a new password for all files in the archive.
*
- * @param string $password
+ * @param string $password
* @param int|null $encryptionMethod Encryption method
+ *
* @return ZipFileInterface
*/
public function setPassword($password, $encryptionMethod = self::ENCRYPTION_METHOD_WINZIP_AES_256);
@@ -500,41 +558,49 @@ interface ZipFileInterface extends \Countable, \ArrayAccess, \Iterator
/**
* Sets a new password of an entry defined by its name.
*
- * @param string $entryName
- * @param string $password
+ * @param string $entryName
+ * @param string $password
* @param int|null $encryptionMethod
+ *
* @return ZipFileInterface
*/
public function setPasswordEntry($entryName, $password, $encryptionMethod = null);
/**
* Remove password for all entries for update.
+ *
* @return ZipFileInterface
+ *
* @deprecated using ZipFileInterface::disableEncryption()
*/
public function withoutPassword();
/**
* Disable encryption for all entries that are already in the archive.
+ *
* @return ZipFileInterface
*/
public function disableEncryption();
/**
* Disable encryption of an entry defined by its name.
+ *
* @param string $entryName
+ *
* @return ZipFileInterface
*/
public function disableEncryptionEntry($entryName);
/**
- * Undo all changes done in the archive
+ * Undo all changes done in the archive.
+ *
* @return ZipFileInterface
*/
public function unchangeAll();
/**
- * Undo change archive comment
+ * Undo change archive comment.
+ *
* @return ZipFileInterface
*/
public function unchangeArchiveComment();
@@ -543,6 +609,7 @@ interface ZipFileInterface extends \Countable, \ArrayAccess, \Iterator
* Revert all changes done to an entry with the given name.
*
* @param string|ZipEntry $entry Entry name or ZipEntry
+ *
* @return ZipFileInterface
*/
public function unchangeEntry($entry);
@@ -551,8 +618,10 @@ interface ZipFileInterface extends \Countable, \ArrayAccess, \Iterator
* Save as file.
*
* @param string $filename Output filename
- * @return ZipFileInterface
+ *
* @throws ZipException
+ *
+ * @return ZipFileInterface
*/
public function saveAsFile($filename);
@@ -560,8 +629,10 @@ interface ZipFileInterface extends \Countable, \ArrayAccess, \Iterator
* Save as stream.
*
* @param resource $handle Output stream resource
- * @return ZipFileInterface
+ *
* @throws ZipException
+ *
+ * @return ZipFileInterface
*/
public function saveAsStream($handle);
@@ -569,33 +640,42 @@ interface ZipFileInterface extends \Countable, \ArrayAccess, \Iterator
* Output .ZIP archive as attachment.
* Die after output.
*
- * @param string $outputFilename Output filename
- * @param string|null $mimeType Mime-Type
- * @param bool $attachment Http Header 'Content-Disposition' if true then attachment otherwise inline
+ * @param string $outputFilename Output filename
+ * @param string|null $mimeType Mime-Type
+ * @param bool $attachment Http Header 'Content-Disposition' if true then attachment otherwise inline
*/
public function outputAsAttachment($outputFilename, $mimeType = null, $attachment = true);
/**
* Output .ZIP archive as PSR-7 Response.
*
- * @param ResponseInterface $response Instance PSR-7 Response
- * @param string $outputFilename Output filename
- * @param string|null $mimeType Mime-Type
- * @param bool $attachment Http Header 'Content-Disposition' if true then attachment otherwise inline
+ * @param ResponseInterface $response Instance PSR-7 Response
+ * @param string $outputFilename Output filename
+ * @param string|null $mimeType Mime-Type
+ * @param bool $attachment Http Header 'Content-Disposition' if true then attachment otherwise inline
+ *
* @return ResponseInterface
*/
- public function outputAsResponse(ResponseInterface $response, $outputFilename, $mimeType = null, $attachment = true);
+ public function outputAsResponse(
+ ResponseInterface $response,
+ $outputFilename,
+ $mimeType = null,
+ $attachment = true
+ );
/**
* Returns the zip archive as a string.
+ *
* @return string
*/
public function outputAsString();
/**
* Save and reopen zip archive.
- * @return ZipFileInterface
+ *
* @throws ZipException
+ *
+ * @return ZipFileInterface
*/
public function rewrite();
diff --git a/tests/PhpZip/Internal/DummyFileSystemStream.php b/tests/PhpZip/Internal/DummyFileSystemStream.php
new file mode 100644
index 0000000..1e8fc92
--- /dev/null
+++ b/tests/PhpZip/Internal/DummyFileSystemStream.php
@@ -0,0 +1,57 @@
+stream_open($path, $mode, $options)" . PHP_EOL;
+
+ $parsedUrl = parse_url($path);
+ $path = $parsedUrl['path'];
+ $this->fp = fopen($path, $mode);
+
+ return true;
+ }
+
+ public function stream_read($count)
+ {
+// echo "DummyFileSystemStream->stream_read($count)" . PHP_EOL;
+ $position = ftell($this->fp);
+
+// echo "Loading chunk " . $position . " to " . ($position + $count - 1) . PHP_EOL;
+ return fread($this->fp, $count);
+// echo "String length: " . strlen($ret) . PHP_EOL;
+ }
+
+ public function stream_tell()
+ {
+// echo "DummyFileSystemStream->stream_tell()" . PHP_EOL;
+ return ftell($this->fp);
+ }
+
+ public function stream_eof()
+ {
+// echo "DummyFileSystemStream->stream_eof()" . PHP_EOL;
+ return feof($this->fp);
+ }
+
+ public function stream_seek($offset, $whence)
+ {
+// echo "DummyFileSystemStream->stream_seek($offset, $whence)" . PHP_EOL;
+ fseek($this->fp, $offset, $whence);
+ }
+
+ public function stream_stat()
+ {
+// echo "DummyFileSystemStream->stream_stat()" . PHP_EOL;
+ return fstat($this->fp);
+ }
+}
diff --git a/tests/PhpZip/Internal/ZipFileExtended.php b/tests/PhpZip/Internal/ZipFileExtended.php
new file mode 100644
index 0000000..5e00777
--- /dev/null
+++ b/tests/PhpZip/Internal/ZipFileExtended.php
@@ -0,0 +1,18 @@
+setZipAlign(4);
+ $this->deleteFromRegex('~^META\-INF/~i');
+ }
+}
diff --git a/tests/PhpZip/Issue24Test.php b/tests/PhpZip/Issue24Test.php
index e3ed10c..7b9487e 100644
--- a/tests/PhpZip/Issue24Test.php
+++ b/tests/PhpZip/Issue24Test.php
@@ -5,6 +5,12 @@ namespace PhpZip;
use PhpZip\Exception\ZipException;
use PhpZip\Util\CryptoUtil;
+/**
+ * @internal
+ *
+ * @small
+ * @covers
+ */
class Issue24Test extends ZipTestCase
{
/**
@@ -12,7 +18,7 @@ class Issue24Test extends ZipTestCase
*/
public static function setUpBeforeClass()
{
- stream_wrapper_register("dummyfs", DummyFileSystemStream::class);
+ stream_wrapper_register('dummyfs', Internal\DummyFileSystemStream::class);
}
/**
@@ -32,73 +38,13 @@ class Issue24Test extends ZipTestCase
$zip->saveAsFile($this->outputFilename);
$zip->close();
- $this->assertCorrectZipArchive($this->outputFilename);
+ static::assertCorrectZipArchive($this->outputFilename);
$stream = fopen('dummyfs://localhost/' . $this->outputFilename, 'rb');
- $this->assertNotFalse($stream);
+ static::assertNotFalse($stream);
$zip->openFromStream($stream);
- $this->assertEquals($zip->getListFiles(), ['file.txt']);
- $this->assertEquals($zip['file.txt'], $fileContents);
+ static::assertSame($zip->getListFiles(), ['file.txt']);
+ static::assertSame($zip['file.txt'], $fileContents);
$zip->close();
}
}
-
-/**
- * Try to load using dummy stream
- */
-class DummyFileSystemStream
-{
- /**
- * @var resource
- */
- private $fp;
-
- public function stream_open($path, $mode, $options, &$opened_path)
- {
-// echo "DummyFileSystemStream->stream_open($path, $mode, $options)" . PHP_EOL;
-
- $parsedUrl = parse_url($path);
- $path = $parsedUrl['path'];
- $this->fp = fopen($path, $mode);
-
- return true;
- }
-
- public function stream_read($count)
- {
-// echo "DummyFileSystemStream->stream_read($count)" . PHP_EOL;
- $position = ftell($this->fp);
-
-// echo "Loading chunk " . $position . " to " . ($position + $count - 1) . PHP_EOL;
- $ret = fread($this->fp, $count);
-
-// echo "String length: " . strlen($ret) . PHP_EOL;
-
- return $ret;
- }
-
- public function stream_tell()
- {
-// echo "DummyFileSystemStream->stream_tell()" . PHP_EOL;
- return ftell($this->fp);
- }
-
- public function stream_eof()
- {
-// echo "DummyFileSystemStream->stream_eof()" . PHP_EOL;
- $isfeof = feof($this->fp);
- return $isfeof;
- }
-
- public function stream_seek($offset, $whence)
- {
-// echo "DummyFileSystemStream->stream_seek($offset, $whence)" . PHP_EOL;
- fseek($this->fp, $offset, $whence);
- }
-
- public function stream_stat()
- {
-// echo "DummyFileSystemStream->stream_stat()" . PHP_EOL;
- return fstat($this->fp);
- }
-}
diff --git a/tests/PhpZip/PhpZipExtResourceTest.php b/tests/PhpZip/PhpZipExtResourceTest.php
index 0c4dba7..98cb736 100644
--- a/tests/PhpZip/PhpZipExtResourceTest.php
+++ b/tests/PhpZip/PhpZipExtResourceTest.php
@@ -2,16 +2,25 @@
namespace PhpZip;
+use PhpZip\Exception\Crc32Exception;
+use PhpZip\Exception\ZipAuthenticationException;
use PhpZip\Exception\ZipException;
/**
* Some tests from the official extension of php-zip.
+ *
+ * @internal
+ *
+ * @small
+ * @covers
*/
class PhpZipExtResourceTest extends ZipTestCase
{
/**
- * Bug #7214 (zip_entry_read() binary safe)
+ * Bug #7214 (zip_entry_read() binary safe).
+ *
* @see https://github.com/php/php-src/blob/master/ext/zip/tests/bug7214.phpt
+ *
* @throws ZipException
*/
public function testBinaryNull()
@@ -20,18 +29,21 @@ class PhpZipExtResourceTest extends ZipTestCase
$zipFile = new ZipFile();
$zipFile->openFile($filename);
+
foreach ($zipFile as $name => $contents) {
$info = $zipFile->getEntryInfo($name);
- $this->assertEquals(strlen($contents), $info->getSize());
+ static::assertSame(\strlen($contents), $info->getSize());
}
$zipFile->close();
- $this->assertCorrectZipArchive($filename);
+ static::assertCorrectZipArchive($filename);
}
/**
- * Bug #8009 (cannot add again same entry to an archive)
+ * Bug #8009 (cannot add again same entry to an archive).
+ *
* @see https://github.com/php/php-src/blob/master/ext/zip/tests/bug8009.phpt
+ *
* @throws ZipException
*/
public function testBug8009()
@@ -44,36 +56,42 @@ class PhpZipExtResourceTest extends ZipTestCase
$zipFile->saveAsFile($this->outputFilename);
$zipFile->close();
- $this->assertCorrectZipArchive($this->outputFilename);
+ static::assertCorrectZipArchive($this->outputFilename);
$zipFile->openFile($this->outputFilename);
- $this->assertCount(2, $zipFile);
- $this->assertTrue(isset($zipFile['1.txt']));
- $this->assertTrue(isset($zipFile['2.txt']));
- $this->assertEquals($zipFile['2.txt'], $zipFile['1.txt']);
+ static::assertCount(2, $zipFile);
+ static::assertTrue(isset($zipFile['1.txt']));
+ static::assertTrue(isset($zipFile['2.txt']));
+ static::assertSame($zipFile['2.txt'], $zipFile['1.txt']);
$zipFile->close();
}
/**
- * Bug #40228 (extractTo does not create recursive empty path)
+ * Bug #40228 (extractTo does not create recursive empty path).
+ *
* @see https://github.com/php/php-src/blob/master/ext/zip/tests/bug40228.phpt
* @see https://github.com/php/php-src/blob/master/ext/zip/tests/bug40228-mb.phpt
* @dataProvider provideBug40228
+ *
* @param string $filename
+ *
* @throws ZipException
*/
public function testBug40228($filename)
{
- $this->assertTrue(mkdir($this->outputDirname, 0755, true));
+ static::assertTrue(mkdir($this->outputDirname, 0755, true));
$zipFile = new ZipFile();
$zipFile->openFile($filename);
$zipFile->extractTo($this->outputDirname);
$zipFile->close();
- $this->assertTrue(is_dir($this->outputDirname . '/test/empty'));
+ static::assertTrue(is_dir($this->outputDirname . '/test/empty'));
}
+ /**
+ * @return array
+ */
public function provideBug40228()
{
return [
@@ -82,14 +100,16 @@ class PhpZipExtResourceTest extends ZipTestCase
}
/**
- * Bug #49072 (feof never returns true for damaged file in zip)
+ * Bug #49072 (feof never returns true for damaged file in zip).
+ *
* @see https://github.com/php/php-src/blob/master/ext/zip/tests/bug49072.phpt
- * @expectedException \PhpZip\Exception\Crc32Exception
- * @expectedExceptionMessage file1
+ *
* @throws ZipException
*/
public function testBug49072()
{
+ $this->setExpectedException(Crc32Exception::class, 'file1');
+
$filename = __DIR__ . '/php-zip-ext-test-resources/bug49072.zip';
$zipFile = new ZipFile();
@@ -98,34 +118,40 @@ class PhpZipExtResourceTest extends ZipTestCase
}
/**
- * Bug #70752 (Depacking with wrong password leaves 0 length files)
+ * Bug #70752 (Depacking with wrong password leaves 0 length files).
+ *
* @see https://github.com/php/php-src/blob/master/ext/zip/tests/bug70752.phpt
- * @expectedException \PhpZip\Exception\ZipAuthenticationException
- * @expectedExceptionMessage nvalid password for zip entry "bug70752.txt"
+ *
* @throws ZipException
*/
public function testBug70752()
{
+ $this->setExpectedException(ZipAuthenticationException::class, 'nvalid password for zip entry "bug70752.txt"');
+
$filename = __DIR__ . '/php-zip-ext-test-resources/bug70752.zip';
- $this->assertTrue(mkdir($this->outputDirname, 0755, true));
+ static::assertTrue(mkdir($this->outputDirname, 0755, true));
$zipFile = new ZipFile();
+
try {
$zipFile->openFile($filename);
$zipFile->setReadPassword('bar');
$zipFile->extractTo($this->outputDirname);
- $this->markTestIncomplete('failed test');
+ static::markTestIncomplete('failed test');
} catch (ZipException $exception) {
- $this->assertFalse(file_exists($this->outputDirname . '/bug70752.txt'));
+ static::assertFileNotExists($this->outputDirname . '/bug70752.txt');
$zipFile->close();
+
throw $exception;
}
}
/**
- * Bug #12414 ( extracting files from damaged archives)
+ * Bug #12414 ( extracting files from damaged archives).
+ *
* @see https://github.com/php/php-src/blob/master/ext/zip/tests/pecl12414.phpt
+ *
* @throws ZipException
*/
public function testPecl12414()
@@ -138,10 +164,10 @@ class PhpZipExtResourceTest extends ZipTestCase
$zipFile->openFile($filename);
$info = $zipFile->getEntryInfo($entryName);
- $this->assertTrue($info->getSize() > 0);
+ static::assertTrue($info->getSize() > 0);
$contents = $zipFile[$entryName];
- $this->assertEquals(strlen($contents), $info->getSize());
+ static::assertSame(\strlen($contents), $info->getSize());
$zipFile->close();
}
diff --git a/tests/PhpZip/Zip64Test.php b/tests/PhpZip/Zip64Test.php
new file mode 100644
index 0000000..a11eb18
--- /dev/null
+++ b/tests/PhpZip/Zip64Test.php
@@ -0,0 +1,45 @@
+ 65535 files in archive and open and extract to /dev/null.
+ *
+ * @throws ZipException
+ */
+ public function testCreateAndOpenZip64Ext()
+ {
+ $countFiles = 0xffff + 1;
+
+ $zipFile = new ZipFile();
+ for ($i = 0; $i < $countFiles; $i++) {
+ $zipFile[$i . '.txt'] = (string) $i;
+ }
+ $zipFile->saveAsFile($this->outputFilename);
+ $zipFile->close();
+
+ static::assertCorrectZipArchive($this->outputFilename);
+
+ $zipFile->openFile($this->outputFilename);
+ static::assertSame($zipFile->count(), $countFiles);
+ $i = 0;
+
+ foreach ($zipFile as $entry => $content) {
+ static::assertSame($entry, $i . '.txt');
+ static::assertSame($content, (string) $i);
+ $i++;
+ }
+ $zipFile->close();
+ }
+}
diff --git a/tests/PhpZip/ZipAlignTest.php b/tests/PhpZip/ZipAlignTest.php
index 161cc33..24b09d8 100644
--- a/tests/PhpZip/ZipAlignTest.php
+++ b/tests/PhpZip/ZipAlignTest.php
@@ -6,7 +6,12 @@ use PhpZip\Exception\ZipException;
use PhpZip\Util\CryptoUtil;
/**
- * Test ZipAlign
+ * Test ZipAlign.
+ *
+ * @internal
+ *
+ * @small
+ * @covers
*/
class ZipAlignTest extends ZipTestCase
{
@@ -17,10 +22,11 @@ class ZipAlignTest extends ZipTestCase
{
$filename = __DIR__ . '/resources/apk.zip';
- $this->assertCorrectZipArchive($filename);
- $result = $this->assertVerifyZipAlign($filename);
- if (null !== $result) {
- $this->assertTrue($result);
+ static::assertCorrectZipArchive($filename);
+ $result = static::assertVerifyZipAlign($filename);
+
+ if ($result !== null) {
+ static::assertTrue($result);
}
$zipFile = new ZipFile();
@@ -29,15 +35,17 @@ class ZipAlignTest extends ZipTestCase
$zipFile->saveAsFile($this->outputFilename);
$zipFile->close();
- $this->assertCorrectZipArchive($this->outputFilename);
- $result = $this->assertVerifyZipAlign($this->outputFilename, true);
- if (null !== $result) {
- $this->assertTrue($result);
+ static::assertCorrectZipArchive($this->outputFilename);
+ $result = static::assertVerifyZipAlign($this->outputFilename, true);
+
+ if ($result !== null) {
+ static::assertTrue($result);
}
}
/**
* Test zip alignment.
+ *
* @throws ZipException
*/
public function testZipAlignSourceZip()
@@ -53,28 +61,29 @@ class ZipAlignTest extends ZipTestCase
$zipFile->saveAsFile($this->outputFilename);
$zipFile->close();
- $this->assertCorrectZipArchive($this->outputFilename);
+ static::assertCorrectZipArchive($this->outputFilename);
+
+ $result = static::assertVerifyZipAlign($this->outputFilename);
- $result = $this->assertVerifyZipAlign($this->outputFilename);
if ($result === null) {
return;
} // zip align not installed
// check not zip align
- $this->assertFalse($result);
+ static::assertFalse($result);
$zipFile->openFile($this->outputFilename);
$zipFile->setZipAlign(4);
$zipFile->saveAsFile($this->outputFilename);
$zipFile->close();
- $this->assertCorrectZipArchive($this->outputFilename);
+ static::assertCorrectZipArchive($this->outputFilename);
- $result = $this->assertVerifyZipAlign($this->outputFilename, true);
- $this->assertNotNull($result);
+ $result = static::assertVerifyZipAlign($this->outputFilename, true);
+ static::assertNotNull($result);
// check zip align
- $this->assertTrue($result);
+ static::assertTrue($result);
}
/**
@@ -94,14 +103,15 @@ class ZipAlignTest extends ZipTestCase
$zipFile->saveAsFile($this->outputFilename);
$zipFile->close();
- $this->assertCorrectZipArchive($this->outputFilename);
+ static::assertCorrectZipArchive($this->outputFilename);
+
+ $result = static::assertVerifyZipAlign($this->outputFilename);
- $result = $this->assertVerifyZipAlign($this->outputFilename);
if ($result === null) {
return;
} // zip align not installed
// check not zip align
- $this->assertTrue($result);
+ static::assertTrue($result);
}
/**
@@ -120,20 +130,21 @@ class ZipAlignTest extends ZipTestCase
$zipFile->saveAsFile($this->outputFilename);
$zipFile->close();
- $this->assertCorrectZipArchive($this->outputFilename);
+ static::assertCorrectZipArchive($this->outputFilename);
+
+ $result = static::assertVerifyZipAlign($this->outputFilename);
- $result = $this->assertVerifyZipAlign($this->outputFilename);
if ($result === null) {
return;
} // zip align not installed
// check not zip align
- $this->assertFalse($result);
+ static::assertFalse($result);
$zipFile->openFile($this->outputFilename);
- $zipFile->deleteFromRegex("~entry2[\d]+\.txt$~s");
+ $zipFile->deleteFromRegex('~entry2[\\d]+\\.txt$~s');
for ($i = 0; $i < 100; $i++) {
- $isStored = (bool)mt_rand(0, 1);
+ $isStored = (bool) mt_rand(0, 1);
$zipFile->addFromString(
'entry_new_' . ($isStored ? 'stored' : 'deflated') . '_' . $i . '.txt',
@@ -147,12 +158,12 @@ class ZipAlignTest extends ZipTestCase
$zipFile->saveAsFile($this->outputFilename);
$zipFile->close();
- $this->assertCorrectZipArchive($this->outputFilename);
+ static::assertCorrectZipArchive($this->outputFilename);
- $result = $this->assertVerifyZipAlign($this->outputFilename, true);
- $this->assertNotNull($result);
+ $result = static::assertVerifyZipAlign($this->outputFilename, true);
+ static::assertNotNull($result);
// check zip align
- $this->assertTrue($result);
+ static::assertTrue($result);
}
}
diff --git a/tests/PhpZip/ZipEventTest.php b/tests/PhpZip/ZipEventTest.php
index 02e2c7b..fef6bc2 100644
--- a/tests/PhpZip/ZipEventTest.php
+++ b/tests/PhpZip/ZipEventTest.php
@@ -4,16 +4,12 @@ namespace PhpZip;
use PhpZip\Exception\ZipException;
-class ZipFileExtended extends ZipFile
-{
- protected function onBeforeSave()
- {
- parent::onBeforeSave();
- $this->setZipAlign(4);
- $this->deleteFromRegex('~^META\-INF/~i');
- }
-}
-
+/**
+ * @internal
+ *
+ * @small
+ * @covers
+ */
class ZipEventTest extends ZipTestCase
{
/**
@@ -21,27 +17,28 @@ class ZipEventTest extends ZipTestCase
*/
public function testBeforeSave()
{
- $zipFile = new ZipFileExtended();
+ $zipFile = new Internal\ZipFileExtended();
$zipFile->openFile(__DIR__ . '/resources/apk.zip');
- $this->assertTrue(isset($zipFile['META-INF/MANIFEST.MF']));
- $this->assertTrue(isset($zipFile['META-INF/CERT.SF']));
- $this->assertTrue(isset($zipFile['META-INF/CERT.RSA']));
+ static::assertTrue(isset($zipFile['META-INF/MANIFEST.MF']));
+ static::assertTrue(isset($zipFile['META-INF/CERT.SF']));
+ static::assertTrue(isset($zipFile['META-INF/CERT.RSA']));
$zipFile->saveAsFile($this->outputFilename);
- $this->assertFalse(isset($zipFile['META-INF/MANIFEST.MF']));
- $this->assertFalse(isset($zipFile['META-INF/CERT.SF']));
- $this->assertFalse(isset($zipFile['META-INF/CERT.RSA']));
+ static::assertFalse(isset($zipFile['META-INF/MANIFEST.MF']));
+ static::assertFalse(isset($zipFile['META-INF/CERT.SF']));
+ static::assertFalse(isset($zipFile['META-INF/CERT.RSA']));
$zipFile->close();
- $this->assertCorrectZipArchive($this->outputFilename);
- $result = $this->assertVerifyZipAlign($this->outputFilename);
- if (null !== $result) {
- $this->assertTrue($result);
+ static::assertCorrectZipArchive($this->outputFilename);
+ $result = static::assertVerifyZipAlign($this->outputFilename);
+
+ if ($result !== null) {
+ static::assertTrue($result);
}
$zipFile->openFile($this->outputFilename);
- $this->assertFalse(isset($zipFile['META-INF/MANIFEST.MF']));
- $this->assertFalse(isset($zipFile['META-INF/CERT.SF']));
- $this->assertFalse(isset($zipFile['META-INF/CERT.RSA']));
+ static::assertFalse(isset($zipFile['META-INF/MANIFEST.MF']));
+ static::assertFalse(isset($zipFile['META-INF/CERT.SF']));
+ static::assertFalse(isset($zipFile['META-INF/CERT.RSA']));
$zipFile->close();
}
}
diff --git a/tests/PhpZip/ZipFileAddDirTest.php b/tests/PhpZip/ZipFileAddDirTest.php
index 3b13553..b8a1143 100644
--- a/tests/PhpZip/ZipFileAddDirTest.php
+++ b/tests/PhpZip/ZipFileAddDirTest.php
@@ -8,6 +8,11 @@ use PhpZip\Util\Iterator\IgnoreFilesRecursiveFilterIterator;
/**
* Test add directory to zip archive.
+ *
+ * @internal
+ *
+ * @small
+ * @covers
*/
class ZipFileAddDirTest extends ZipTestCase
{
@@ -28,7 +33,7 @@ class ZipFileAddDirTest extends ZipTestCase
];
/**
- * Before test
+ * Before test.
*/
protected function setUp()
{
@@ -40,12 +45,14 @@ class ZipFileAddDirTest extends ZipTestCase
{
foreach (self::$files as $name => $content) {
$fullName = $this->outputDirname . '/' . $name;
+
if ($content === null) {
if (!is_dir($fullName)) {
mkdir($fullName, 0755, true);
}
} else {
- $dirname = dirname($fullName);
+ $dirname = \dirname($fullName);
+
if (!is_dir($dirname)) {
mkdir($dirname, 0755, true);
}
@@ -54,23 +61,33 @@ class ZipFileAddDirTest extends ZipTestCase
}
}
- protected static function assertFilesResult(ZipFileInterface $zipFile, array $actualResultFiles = [], $localPath = '/')
- {
+ /**
+ * @param ZipFileInterface $zipFile
+ * @param array $actualResultFiles
+ * @param string $localPath
+ */
+ protected static function assertFilesResult(
+ ZipFileInterface $zipFile,
+ array $actualResultFiles = [],
+ $localPath = '/'
+ ) {
$localPath = rtrim($localPath, '/');
- $localPath = empty($localPath) ? "" : $localPath . '/';
- self::assertEquals(sizeof($zipFile), sizeof($actualResultFiles));
+ $localPath = empty($localPath) ? '' : $localPath . '/';
+ static::assertCount(\count($zipFile), $actualResultFiles);
$actualResultFiles = array_flip($actualResultFiles);
+
foreach (self::$files as $file => $content) {
$zipEntryName = $localPath . $file;
+
if (isset($actualResultFiles[$file])) {
- self::assertTrue(isset($zipFile[$zipEntryName]));
- self::assertEquals($zipFile[$zipEntryName], $content);
+ static::assertTrue(isset($zipFile[$zipEntryName]));
+ static::assertSame($zipFile[$zipEntryName], $content);
unset($actualResultFiles[$file]);
} else {
- self::assertFalse(isset($zipFile[$zipEntryName]));
+ static::assertFalse(isset($zipFile[$zipEntryName]));
}
}
- self::assertEmpty($actualResultFiles);
+ static::assertEmpty($actualResultFiles);
}
/**
@@ -85,15 +102,19 @@ class ZipFileAddDirTest extends ZipTestCase
$zipFile->saveAsFile($this->outputFilename);
$zipFile->close();
- $this->assertCorrectZipArchive($this->outputFilename);
+ static::assertCorrectZipArchive($this->outputFilename);
$zipFile->openFile($this->outputFilename);
- $this->assertFilesResult($zipFile, [
- '.hidden',
- 'text file.txt',
- 'Текстовый документ.txt',
- 'empty dir/',
- ], $localPath);
+ static::assertFilesResult(
+ $zipFile,
+ [
+ '.hidden',
+ 'text file.txt',
+ 'Текстовый документ.txt',
+ 'empty dir/',
+ ],
+ $localPath
+ );
$zipFile->close();
}
@@ -107,15 +128,18 @@ class ZipFileAddDirTest extends ZipTestCase
$zipFile->saveAsFile($this->outputFilename);
$zipFile->close();
- $this->assertCorrectZipArchive($this->outputFilename);
+ static::assertCorrectZipArchive($this->outputFilename);
$zipFile->openFile($this->outputFilename);
- $this->assertFilesResult($zipFile, [
- '.hidden',
- 'text file.txt',
- 'Текстовый документ.txt',
- 'empty dir/',
- ]);
+ static::assertFilesResult(
+ $zipFile,
+ [
+ '.hidden',
+ 'text file.txt',
+ 'Текстовый документ.txt',
+ 'empty dir/',
+ ]
+ );
$zipFile->close();
}
@@ -133,15 +157,19 @@ class ZipFileAddDirTest extends ZipTestCase
$zipFile->saveAsFile($this->outputFilename);
$zipFile->close();
- $this->assertCorrectZipArchive($this->outputFilename);
+ static::assertCorrectZipArchive($this->outputFilename);
$zipFile->openFile($this->outputFilename);
- $this->assertFilesResult($zipFile, [
- '.hidden',
- 'text file.txt',
- 'Текстовый документ.txt',
- 'empty dir/',
- ], $localPath);
+ static::assertFilesResult(
+ $zipFile,
+ [
+ '.hidden',
+ 'text file.txt',
+ 'Текстовый документ.txt',
+ 'empty dir/',
+ ],
+ $localPath
+ );
$zipFile->close();
}
@@ -159,15 +187,18 @@ class ZipFileAddDirTest extends ZipTestCase
$zipFile->saveAsFile($this->outputFilename);
$zipFile->close();
- $this->assertCorrectZipArchive($this->outputFilename);
+ static::assertCorrectZipArchive($this->outputFilename);
$zipFile->openFile($this->outputFilename);
- $this->assertFilesResult($zipFile, [
- '.hidden',
- 'text file.txt',
- 'Текстовый документ.txt',
- 'empty dir/',
- ]);
+ static::assertFilesResult(
+ $zipFile,
+ [
+ '.hidden',
+ 'text file.txt',
+ 'Текстовый документ.txt',
+ 'empty dir/',
+ ]
+ );
$zipFile->close();
}
@@ -185,10 +216,10 @@ class ZipFileAddDirTest extends ZipTestCase
$zipFile->saveAsFile($this->outputFilename);
$zipFile->close();
- $this->assertCorrectZipArchive($this->outputFilename);
+ static::assertCorrectZipArchive($this->outputFilename);
$zipFile->openFile($this->outputFilename);
- $this->assertFilesResult($zipFile, array_keys(self::$files), $localPath);
+ static::assertFilesResult($zipFile, array_keys(self::$files), $localPath);
$zipFile->close();
}
@@ -204,10 +235,10 @@ class ZipFileAddDirTest extends ZipTestCase
$zipFile->saveAsFile($this->outputFilename);
$zipFile->close();
- $this->assertCorrectZipArchive($this->outputFilename);
+ static::assertCorrectZipArchive($this->outputFilename);
$zipFile->openFile($this->outputFilename);
- $this->assertFilesResult($zipFile, array_keys(self::$files), $localPath);
+ static::assertFilesResult($zipFile, array_keys(self::$files), $localPath);
$zipFile->close();
}
@@ -221,10 +252,10 @@ class ZipFileAddDirTest extends ZipTestCase
$zipFile->saveAsFile($this->outputFilename);
$zipFile->close();
- $this->assertCorrectZipArchive($this->outputFilename);
+ static::assertCorrectZipArchive($this->outputFilename);
$zipFile->openFile($this->outputFilename);
- $this->assertFilesResult($zipFile, array_keys(self::$files));
+ static::assertFilesResult($zipFile, array_keys(self::$files));
$zipFile->close();
}
@@ -236,7 +267,7 @@ class ZipFileAddDirTest extends ZipTestCase
$localPath = 'to/project';
$ignoreFiles = [
'Текстовый документ.txt',
- 'empty dir/'
+ 'empty dir/',
];
$directoryIterator = new \DirectoryIterator($this->outputDirname);
@@ -247,13 +278,17 @@ class ZipFileAddDirTest extends ZipTestCase
$zipFile->saveAsFile($this->outputFilename);
$zipFile->close();
- $this->assertCorrectZipArchive($this->outputFilename);
+ static::assertCorrectZipArchive($this->outputFilename);
$zipFile->openFile($this->outputFilename);
- $this->assertFilesResult($zipFile, [
- '.hidden',
- 'text file.txt',
- ], $localPath);
+ static::assertFilesResult(
+ $zipFile,
+ [
+ '.hidden',
+ 'text file.txt',
+ ],
+ $localPath
+ );
$zipFile->close();
}
@@ -278,24 +313,29 @@ class ZipFileAddDirTest extends ZipTestCase
$zipFile->saveAsFile($this->outputFilename);
$zipFile->close();
- $this->assertCorrectZipArchive($this->outputFilename);
+ static::assertCorrectZipArchive($this->outputFilename);
$zipFile->openFile($this->outputFilename);
- $this->assertFilesResult($zipFile, [
- 'text file.txt',
- 'Текстовый документ.txt',
- 'empty dir/',
- 'catalog/New File',
- 'catalog/New File 2',
- 'catalog/Empty Dir/',
- 'category/Pictures/128x160/Car/01.jpg',
- 'category/Pictures/128x160/Car/02.jpg',
- ], $localPath);
+ static::assertFilesResult(
+ $zipFile,
+ [
+ 'text file.txt',
+ 'Текстовый документ.txt',
+ 'empty dir/',
+ 'catalog/New File',
+ 'catalog/New File 2',
+ 'catalog/Empty Dir/',
+ 'category/Pictures/128x160/Car/01.jpg',
+ 'category/Pictures/128x160/Car/02.jpg',
+ ],
+ $localPath
+ );
$zipFile->close();
}
/**
- * Create archive and add files from glob pattern
+ * Create archive and add files from glob pattern.
+ *
* @throws ZipException
*/
public function testAddFilesFromGlob()
@@ -307,18 +347,23 @@ class ZipFileAddDirTest extends ZipTestCase
$zipFile->saveAsFile($this->outputFilename);
$zipFile->close();
- $this->assertCorrectZipArchive($this->outputFilename);
+ static::assertCorrectZipArchive($this->outputFilename);
$zipFile->openFile($this->outputFilename);
- $this->assertFilesResult($zipFile, [
- 'text file.txt',
- 'Текстовый документ.txt',
- ], $localPath);
+ static::assertFilesResult(
+ $zipFile,
+ [
+ 'text file.txt',
+ 'Текстовый документ.txt',
+ ],
+ $localPath
+ );
$zipFile->close();
}
/**
- * Create archive and add recursively files from glob pattern
+ * Create archive and add recursively files from glob pattern.
+ *
* @throws ZipException
*/
public function testAddFilesFromGlobRecursive()
@@ -330,23 +375,28 @@ class ZipFileAddDirTest extends ZipTestCase
$zipFile->saveAsFile($this->outputFilename);
$zipFile->close();
- $this->assertCorrectZipArchive($this->outputFilename);
+ static::assertCorrectZipArchive($this->outputFilename);
$zipFile->openFile($this->outputFilename);
- $this->assertFilesResult($zipFile, [
- 'text file.txt',
- 'Текстовый документ.txt',
- 'category/list.txt',
- 'category/Pictures/128x160/Car/01.jpg',
- 'category/Pictures/128x160/Car/02.jpg',
- 'category/Pictures/240x320/Car/01.jpg',
- 'category/Pictures/240x320/Car/02.jpg',
- ], $localPath);
+ static::assertFilesResult(
+ $zipFile,
+ [
+ 'text file.txt',
+ 'Текстовый документ.txt',
+ 'category/list.txt',
+ 'category/Pictures/128x160/Car/01.jpg',
+ 'category/Pictures/128x160/Car/02.jpg',
+ 'category/Pictures/240x320/Car/01.jpg',
+ 'category/Pictures/240x320/Car/02.jpg',
+ ],
+ $localPath
+ );
$zipFile->close();
}
/**
- * Create archive and add files from regex pattern
+ * Create archive and add files from regex pattern.
+ *
* @throws ZipException
*/
public function testAddFilesFromRegex()
@@ -358,18 +408,23 @@ class ZipFileAddDirTest extends ZipTestCase
$zipFile->saveAsFile($this->outputFilename);
$zipFile->close();
- $this->assertCorrectZipArchive($this->outputFilename);
+ static::assertCorrectZipArchive($this->outputFilename);
$zipFile->openFile($this->outputFilename);
- $this->assertFilesResult($zipFile, [
- 'text file.txt',
- 'Текстовый документ.txt',
- ], $localPath);
+ static::assertFilesResult(
+ $zipFile,
+ [
+ 'text file.txt',
+ 'Текстовый документ.txt',
+ ],
+ $localPath
+ );
$zipFile->close();
}
/**
- * Create archive and add files recursively from regex pattern
+ * Create archive and add files recursively from regex pattern.
+ *
* @throws ZipException
*/
public function testAddFilesFromRegexRecursive()
@@ -381,18 +436,22 @@ class ZipFileAddDirTest extends ZipTestCase
$zipFile->saveAsFile($this->outputFilename);
$zipFile->close();
- $this->assertCorrectZipArchive($this->outputFilename);
+ static::assertCorrectZipArchive($this->outputFilename);
$zipFile->openFile($this->outputFilename);
- $this->assertFilesResult($zipFile, [
- 'text file.txt',
- 'Текстовый документ.txt',
- 'category/list.txt',
- 'category/Pictures/128x160/Car/01.jpg',
- 'category/Pictures/128x160/Car/02.jpg',
- 'category/Pictures/240x320/Car/01.jpg',
- 'category/Pictures/240x320/Car/02.jpg',
- ], $localPath);
+ static::assertFilesResult(
+ $zipFile,
+ [
+ 'text file.txt',
+ 'Текстовый документ.txt',
+ 'category/list.txt',
+ 'category/Pictures/128x160/Car/01.jpg',
+ 'category/Pictures/128x160/Car/02.jpg',
+ 'category/Pictures/240x320/Car/01.jpg',
+ 'category/Pictures/240x320/Car/02.jpg',
+ ],
+ $localPath
+ );
$zipFile->close();
}
@@ -409,10 +468,10 @@ class ZipFileAddDirTest extends ZipTestCase
$zipFile->saveAsFile($this->outputFilename);
$zipFile->close();
- $this->assertCorrectZipArchive($this->outputFilename);
+ static::assertCorrectZipArchive($this->outputFilename);
$zipFile->openFile($this->outputFilename);
- $this->assertFilesResult($zipFile, array_keys(self::$files), $localPath);
+ static::assertFilesResult($zipFile, array_keys(self::$files), $localPath);
$zipFile->close();
}
}
diff --git a/tests/PhpZip/ZipFileTest.php b/tests/PhpZip/ZipFileTest.php
index 96c291e..cb0163f 100644
--- a/tests/PhpZip/ZipFileTest.php
+++ b/tests/PhpZip/ZipFileTest.php
@@ -2,8 +2,10 @@
namespace PhpZip;
+use PhpZip\Exception\InvalidArgumentException;
use PhpZip\Exception\ZipEntryNotFoundException;
use PhpZip\Exception\ZipException;
+use PhpZip\Exception\ZipUnsupportMethodException;
use PhpZip\Model\ZipEntry;
use PhpZip\Model\ZipInfo;
use PhpZip\Util\CryptoUtil;
@@ -12,89 +14,104 @@ use Psr\Http\Message\ResponseInterface;
use Zend\Diactoros\Response;
/**
- * ZipFile test
+ * ZipFile test.
+ *
+ * @internal
+ *
+ * @small
+ * @covers
*/
class ZipFileTest extends ZipTestCase
{
-
/**
- * @expectedException \PhpZip\Exception\ZipException
- * @expectedExceptionMessage does not exist
+ * @throws ZipException
*/
public function testOpenFileCantExists()
{
+ $this->setExpectedException(ZipException::class, 'does not exist');
+
$zipFile = new ZipFile();
- $zipFile->openFile(uniqid());
+ $zipFile->openFile(uniqid('', true));
}
/**
- * @expectedException \PhpZip\Exception\ZipException
- * @expectedExceptionMessage can't open
+ * @throws ZipException
*/
public function testOpenFileCantOpen()
{
+ $this->setExpectedException(ZipException::class, 'can\'t open');
+
/** @noinspection PhpComposerExtensionStubsInspection */
if (posix_getuid() === 0) {
- $this->markTestSkipped('Skip the test for a user with root privileges');
+ static::markTestSkipped('Skip the test for a user with root privileges');
}
- $this->assertNotFalse(file_put_contents($this->outputFilename, 'content'));
- $this->assertTrue(chmod($this->outputFilename, 0222));
+ static::assertNotFalse(file_put_contents($this->outputFilename, 'content'));
+ static::assertTrue(chmod($this->outputFilename, 0222));
$zipFile = new ZipFile();
$zipFile->openFile($this->outputFilename);
}
/**
- * @expectedException \PhpZip\Exception\ZipException
- * @expectedExceptionMessage Invalid zip file
+ * @throws ZipException
*/
public function testOpenFileEmptyFile()
{
- $this->assertNotFalse(touch($this->outputFilename));
+ $this->setExpectedException(ZipException::class, 'Invalid zip file');
+
+ static::assertNotFalse(touch($this->outputFilename));
$zipFile = new ZipFile();
$zipFile->openFile($this->outputFilename);
}
/**
- * @expectedException \PhpZip\Exception\ZipException
- * @expectedExceptionMessage Expected Local File Header or (ZIP64) End Of Central Directory Record
+ * @throws ZipException
*/
public function testOpenFileInvalidZip()
{
- $this->assertNotFalse(file_put_contents($this->outputFilename, CryptoUtil::randomBytes(255)));
+ $this->setExpectedException(
+ ZipException::class,
+ 'Expected Local File Header or (ZIP64) End Of Central Directory Record'
+ );
+
+ static::assertNotFalse(file_put_contents($this->outputFilename, CryptoUtil::randomBytes(255)));
$zipFile = new ZipFile();
$zipFile->openFile($this->outputFilename);
}
/**
- * @expectedException \PhpZip\Exception\InvalidArgumentException
- * @expectedExceptionMessage Empty string passed
* @throws ZipException
*/
public function testOpenFromStringNullString()
{
+ $this->setExpectedException(InvalidArgumentException::class, 'Empty string passed');
+
$zipFile = new ZipFile();
$zipFile->openFromString(null);
}
/**
- * @expectedException \PhpZip\Exception\InvalidArgumentException
- * @expectedExceptionMessage Empty string passed
* @throws ZipException
*/
public function testOpenFromStringEmptyString()
{
+ $this->setExpectedException(InvalidArgumentException::class, 'Empty string passed');
+
$zipFile = new ZipFile();
- $zipFile->openFromString("");
+ $zipFile->openFromString('');
}
/**
- * @expectedException \PhpZip\Exception\ZipException
- * @expectedExceptionMessage Expected Local File Header or (ZIP64) End Of Central Directory Record
+ * @throws ZipException
*/
public function testOpenFromStringInvalidZip()
{
+ $this->setExpectedException(
+ ZipException::class,
+ 'Expected Local File Header or (ZIP64) End Of Central Directory Record'
+ );
+
$zipFile = new ZipFile();
$zipFile->openFromString(CryptoUtil::randomBytes(255));
}
@@ -111,73 +128,77 @@ class ZipFileTest extends ZipTestCase
$zipFile->close();
$zipFile->openFromString($zipContents);
- $this->assertEquals($zipFile->count(), 2);
- $this->assertTrue(isset($zipFile['file']));
- $this->assertTrue(isset($zipFile['file2']));
- $this->assertEquals($zipFile['file'], 'content');
- $this->assertEquals($zipFile['file2'], 'content 2');
+ static::assertSame($zipFile->count(), 2);
+ static::assertTrue(isset($zipFile['file']));
+ static::assertTrue(isset($zipFile['file2']));
+ static::assertSame($zipFile['file'], 'content');
+ static::assertSame($zipFile['file2'], 'content 2');
$zipFile->close();
}
/**
- * @expectedException \PhpZip\Exception\InvalidArgumentException
- * @expectedExceptionMessage Invalid stream resource
* @throws ZipException
*/
public function testOpenFromStreamNullStream()
{
+ $this->setExpectedException(InvalidArgumentException::class, 'Invalid stream resource');
+
$zipFile = new ZipFile();
$zipFile->openFromStream(null);
}
/**
- * @expectedException \PhpZip\Exception\InvalidArgumentException
- * @expectedExceptionMessage Invalid stream resource
* @throws ZipException
*/
public function testOpenFromStreamInvalidResourceType()
{
+ $this->setExpectedException(InvalidArgumentException::class, 'Invalid stream resource');
+
$zipFile = new ZipFile();
/** @noinspection PhpParamsInspection */
- $zipFile->openFromStream("stream resource");
+ $zipFile->openFromStream('stream resource');
}
/**
- * @expectedException \PhpZip\Exception\InvalidArgumentException
- * @expectedExceptionMessage Invalid resource type - gd.
* @throws ZipException
*/
public function testOpenFromStreamInvalidResourceType2()
{
+ $this->setExpectedException(InvalidArgumentException::class, 'Invalid resource type - gd.');
+
$zipFile = new ZipFile();
- if (!extension_loaded("gd")) {
- $this->markTestSkipped('not extension gd');
+
+ if (!\extension_loaded('gd')) {
+ static::markTestSkipped('not extension gd');
}
/** @noinspection PhpComposerExtensionStubsInspection */
$zipFile->openFromStream(imagecreate(1, 1));
}
/**
- * @expectedException \PhpZip\Exception\InvalidArgumentException
- * @expectedExceptionMessage Invalid stream type - dir.
* @throws ZipException
*/
public function testOpenFromStreamInvalidResourceType3()
{
+ $this->setExpectedException(InvalidArgumentException::class, 'Invalid stream type - dir.');
+
$zipFile = new ZipFile();
$zipFile->openFromStream(opendir(__DIR__));
}
/**
- * @expectedException \PhpZip\Exception\InvalidArgumentException
- * @expectedExceptionMessage Resource cannot seekable stream.
* @throws ZipException
+ * @noinspection PhpUsageOfSilenceOperatorInspection
+ * @noinspection NestedPositiveIfStatementsInspection
*/
public function testOpenFromStreamNoSeekable()
{
- if (!$fp = @fopen("http://localhost", 'r')) {
- if (!$fp = @fopen("http://example.org", 'r')) {
- $this->markTestSkipped('not connected to localhost or remote host');
+ $this->setExpectedException(InvalidArgumentException::class, 'Resource cannot seekable stream.');
+
+ if (!$fp = @fopen('http://localhost', 'rb')) {
+ if (!$fp = @fopen('http://example.org', 'rb')) {
+ static::markTestSkipped('not connected to localhost or remote host');
+
return;
}
}
@@ -187,22 +208,27 @@ class ZipFileTest extends ZipTestCase
}
/**
- * @expectedException \PhpZip\Exception\ZipException
- * @expectedExceptionMessage Invalid zip file
+ * @throws ZipException
*/
public function testOpenFromStreamEmptyContents()
{
+ $this->setExpectedException(ZipException::class, 'Invalid zip file');
+
$fp = fopen($this->outputFilename, 'w+b');
$zipFile = new ZipFile();
$zipFile->openFromStream($fp);
}
/**
- * @expectedException \PhpZip\Exception\ZipException
- * @expectedExceptionMessage Expected Local File Header or (ZIP64) End Of Central Directory Record
+ * @throws ZipException
*/
public function testOpenFromStreamInvalidZip()
{
+ $this->setExpectedException(
+ ZipException::class,
+ 'Expected Local File Header or (ZIP64) End Of Central Directory Record'
+ );
+
$fp = fopen($this->outputFilename, 'w+b');
fwrite($fp, CryptoUtil::randomBytes(255));
$zipFile = new ZipFile();
@@ -218,18 +244,20 @@ class ZipFileTest extends ZipTestCase
$zipFile
->addFromString('file', 'content')
->saveAsFile($this->outputFilename)
- ->close();
+ ->close()
+ ;
$handle = fopen($this->outputFilename, 'rb');
$zipFile->openFromStream($handle);
- $this->assertEquals($zipFile->count(), 1);
- $this->assertTrue(isset($zipFile['file']));
- $this->assertEquals($zipFile['file'], 'content');
+ static::assertSame($zipFile->count(), 1);
+ static::assertTrue(isset($zipFile['file']));
+ static::assertSame($zipFile['file'], 'content');
$zipFile->close();
}
/**
* Test create, open and extract empty archive.
+ *
* @throws ZipException
*/
public function testEmptyArchive()
@@ -237,56 +265,61 @@ class ZipFileTest extends ZipTestCase
$zipFile = new ZipFile();
$zipFile
->saveAsFile($this->outputFilename)
- ->close();
+ ->close()
+ ;
- $this->assertCorrectEmptyZip($this->outputFilename);
- $this->assertTrue(mkdir($this->outputDirname, 0755, true));
+ static::assertCorrectEmptyZip($this->outputFilename);
+ static::assertTrue(mkdir($this->outputDirname, 0755, true));
$zipFile->openFile($this->outputFilename);
- $this->assertEquals($zipFile->count(), 0);
+ static::assertSame($zipFile->count(), 0);
$zipFile
->extractTo($this->outputDirname)
- ->close();
+ ->close()
+ ;
- $this->assertTrue(FilesUtil::isEmptyDir($this->outputDirname));
+ static::assertTrue(FilesUtil::isEmptyDir($this->outputDirname));
}
/**
- * No modified archive
+ * No modified archive.
+ *
+ * @throws ZipException
*
* @see ZipOutputFile::create()
- * @throws ZipException
*/
public function testNoModifiedArchive()
{
- $this->assertTrue(mkdir($this->outputDirname, 0755, true));
+ static::assertTrue(mkdir($this->outputDirname, 0755, true));
- $fileActual = $this->outputDirname . DIRECTORY_SEPARATOR . 'file_actual.zip';
- $fileExpected = $this->outputDirname . DIRECTORY_SEPARATOR . 'file_expected.zip';
+ $fileActual = $this->outputDirname . \DIRECTORY_SEPARATOR . 'file_actual.zip';
+ $fileExpected = $this->outputDirname . \DIRECTORY_SEPARATOR . 'file_expected.zip';
$zipFile = new ZipFile();
- $zipFile->addDirRecursive(__DIR__.'/../../src');
+ $zipFile->addDirRecursive(__DIR__ . '/../../src');
$sourceCount = $zipFile->count();
- $this->assertTrue($sourceCount > 0);
+ static::assertTrue($sourceCount > 0);
$zipFile
->saveAsFile($fileActual)
- ->close();
- $this->assertCorrectZipArchive($fileActual);
+ ->close()
+ ;
+ static::assertCorrectZipArchive($fileActual);
$zipFile
->openFile($fileActual)
- ->saveAsFile($fileExpected);
- $this->assertCorrectZipArchive($fileExpected);
+ ->saveAsFile($fileExpected)
+ ;
+ static::assertCorrectZipArchive($fileExpected);
$zipFileExpected = new ZipFile();
$zipFileExpected->openFile($fileExpected);
- $this->assertEquals($zipFile->count(), $sourceCount);
- $this->assertEquals($zipFileExpected->count(), $zipFile->count());
- $this->assertEquals($zipFileExpected->getListFiles(), $zipFile->getListFiles());
+ static::assertSame($zipFile->count(), $sourceCount);
+ static::assertSame($zipFileExpected->count(), $zipFile->count());
+ static::assertSame($zipFileExpected->getListFiles(), $zipFile->getListFiles());
foreach ($zipFile as $entryName => $content) {
- $this->assertEquals($zipFileExpected[$entryName], $content);
+ static::assertSame($zipFileExpected[$entryName], $content);
}
$zipFileExpected->close();
@@ -296,18 +329,19 @@ class ZipFileTest extends ZipTestCase
/**
* Create archive and add files.
*
- * @see ZipOutputFile::addFromString()
+ * @throws ZipException
+ *
* @see ZipOutputFile::addFromFile()
* @see ZipOutputFile::addFromStream()
* @see ZipFile::getEntryContents()
- * @throws ZipException
+ * @see ZipOutputFile::addFromString()
*/
public function testCreateArchiveAndAddFiles()
{
$outputFromString = file_get_contents(__FILE__);
- $outputFromString2 = file_get_contents(dirname(dirname(__DIR__)) . DIRECTORY_SEPARATOR . 'README.md');
- $outputFromFile = file_get_contents(dirname(dirname(__DIR__)) . DIRECTORY_SEPARATOR . 'phpunit.xml');
- $outputFromStream = file_get_contents(dirname(dirname(__DIR__)) . DIRECTORY_SEPARATOR . 'composer.json');
+ $outputFromString2 = file_get_contents(\dirname(\dirname(__DIR__)) . \DIRECTORY_SEPARATOR . 'README.md');
+ $outputFromFile = file_get_contents(\dirname(\dirname(__DIR__)) . \DIRECTORY_SEPARATOR . 'phpunit.xml');
+ $outputFromStream = file_get_contents(\dirname(\dirname(__DIR__)) . \DIRECTORY_SEPARATOR . 'composer.json');
$filenameFromString = basename(__FILE__);
$filenameFromString2 = 'test_file.txt';
@@ -323,44 +357,46 @@ class ZipFileTest extends ZipTestCase
$tempStream = tmpfile();
fwrite($tempStream, $outputFromStream);
- $zipFile = new ZipFile;
+ $zipFile = new ZipFile();
$zipFile
->addFromString($filenameFromString, $outputFromString)
->addFile($tempFile, $filenameFromFile)
->addFromStream($tempStream, $filenameFromStream)
- ->addEmptyDir($emptyDirName);
+ ->addEmptyDir($emptyDirName)
+ ;
$zipFile[$filenameFromString2] = $outputFromString2;
$zipFile[$emptyDirName2] = null;
$zipFile[$emptyDirName3] = 'this content ignoring';
- $this->assertEquals(count($zipFile), 7);
+ static::assertSame(\count($zipFile), 7);
$zipFile
->saveAsFile($this->outputFilename)
- ->close();
+ ->close()
+ ;
unlink($tempFile);
- $this->assertCorrectZipArchive($this->outputFilename);
+ static::assertCorrectZipArchive($this->outputFilename);
$zipFile->openFile($this->outputFilename);
- $this->assertEquals(count($zipFile), 7);
- $this->assertEquals($zipFile[$filenameFromString], $outputFromString);
- $this->assertEquals($zipFile[$filenameFromFile], $outputFromFile);
- $this->assertEquals($zipFile[$filenameFromStream], $outputFromStream);
- $this->assertEquals($zipFile[$filenameFromString2], $outputFromString2);
- $this->assertTrue(isset($zipFile[$emptyDirName]));
- $this->assertTrue(isset($zipFile[$emptyDirName2]));
- $this->assertTrue(isset($zipFile[$emptyDirName3]));
- $this->assertTrue($zipFile->isDirectory($emptyDirName));
- $this->assertTrue($zipFile->isDirectory($emptyDirName2));
- $this->assertTrue($zipFile->isDirectory($emptyDirName3));
+ static::assertSame(\count($zipFile), 7);
+ static::assertSame($zipFile[$filenameFromString], $outputFromString);
+ static::assertSame($zipFile[$filenameFromFile], $outputFromFile);
+ static::assertSame($zipFile[$filenameFromStream], $outputFromStream);
+ static::assertSame($zipFile[$filenameFromString2], $outputFromString2);
+ static::assertTrue(isset($zipFile[$emptyDirName]));
+ static::assertTrue(isset($zipFile[$emptyDirName2]));
+ static::assertTrue(isset($zipFile[$emptyDirName3]));
+ static::assertTrue($zipFile->isDirectory($emptyDirName));
+ static::assertTrue($zipFile->isDirectory($emptyDirName2));
+ static::assertTrue($zipFile->isDirectory($emptyDirName3));
$listFiles = $zipFile->getListFiles();
- $this->assertEquals($listFiles[0], $filenameFromString);
- $this->assertEquals($listFiles[1], $filenameFromFile);
- $this->assertEquals($listFiles[2], $filenameFromStream);
- $this->assertEquals($listFiles[3], $emptyDirName);
- $this->assertEquals($listFiles[4], $filenameFromString2);
- $this->assertEquals($listFiles[5], $emptyDirName2);
- $this->assertEquals($listFiles[6], $emptyDirName3);
+ static::assertSame($listFiles[0], $filenameFromString);
+ static::assertSame($listFiles[1], $filenameFromFile);
+ static::assertSame($listFiles[2], $filenameFromStream);
+ static::assertSame($listFiles[3], $emptyDirName);
+ static::assertSame($listFiles[4], $filenameFromString2);
+ static::assertSame($listFiles[5], $emptyDirName2);
+ static::assertSame($listFiles[6], $emptyDirName3);
$zipFile->close();
}
@@ -376,22 +412,23 @@ class ZipFileTest extends ZipTestCase
$zipFile->close();
$zipFile->openFile($this->outputFilename);
- $this->assertEquals($zipFile['file'], '');
+ static::assertSame($zipFile['file'], '');
$zipFile->close();
}
/**
* Test compression method from image file.
+ *
* @throws ZipException
*/
public function testCompressionMethodFromImageMimeType()
{
- if (!function_exists('mime_content_type')) {
- $this->markTestSkipped('Function mime_content_type not exists');
+ if (!\function_exists('mime_content_type')) {
+ static::markTestSkipped('Function mime_content_type not exists');
}
$outputFilename = $this->outputFilename;
$this->outputFilename .= '.gif';
- $this->assertNotFalse(
+ static::assertNotFalse(
file_put_contents(
$this->outputFilename,
base64_decode('R0lGODlhAQABAJAAAP8AAAAAACH5BAUQAAAALAAAAAABAAEAAAICBAEAOw==')
@@ -407,12 +444,13 @@ class ZipFileTest extends ZipTestCase
$zipFile->openFile($this->outputFilename);
$info = $zipFile->getEntryInfo($basename);
- $this->assertEquals($info->getMethodName(), 'No compression');
+ static::assertSame($info->getMethodName(), 'No compression');
$zipFile->close();
}
/**
* Rename zip entry name.
+ *
* @throws ZipException
*/
public function testRename()
@@ -425,7 +463,7 @@ class ZipFileTest extends ZipTestCase
$zipFile->saveAsFile($this->outputFilename);
$zipFile->close();
- $this->assertCorrectZipArchive($this->outputFilename);
+ static::assertCorrectZipArchive($this->outputFilename);
$zipFile->openFile($this->outputFilename);
$zipFile->rename($oldName, $newName);
@@ -438,49 +476,49 @@ class ZipFileTest extends ZipTestCase
$zipFile->saveAsFile($this->outputFilename);
$zipFile->close();
- $this->assertCorrectZipArchive($this->outputFilename);
+ static::assertCorrectZipArchive($this->outputFilename);
$zipFile->openFile($this->outputFilename);
- $this->assertFalse(isset($zipFile[$oldName]));
- $this->assertTrue(isset($zipFile[$newName]));
- $this->assertFalse(isset($zipFile['file1.txt']));
- $this->assertFalse(isset($zipFile['file2.txt']));
- $this->assertFalse(isset($zipFile['file3.txt']));
- $this->assertTrue(isset($zipFile['file_long_name.txt']));
- $this->assertTrue(isset($zipFile['file4.txt']));
- $this->assertTrue(isset($zipFile['fi.txt']));
+ static::assertFalse(isset($zipFile[$oldName]));
+ static::assertTrue(isset($zipFile[$newName]));
+ static::assertFalse(isset($zipFile['file1.txt']));
+ static::assertFalse(isset($zipFile['file2.txt']));
+ static::assertFalse(isset($zipFile['file3.txt']));
+ static::assertTrue(isset($zipFile['file_long_name.txt']));
+ static::assertTrue(isset($zipFile['file4.txt']));
+ static::assertTrue(isset($zipFile['fi.txt']));
$zipFile->close();
}
/**
- * @expectedException \PhpZip\Exception\InvalidArgumentException
- * @expectedExceptionMessage name is null
* @throws ZipException
*/
public function testRenameEntryNull()
{
+ $this->setExpectedException(InvalidArgumentException::class, 'name is null');
+
$zipFile = new ZipFile();
$zipFile->rename(null, 'new-file');
}
/**
- * @expectedException \PhpZip\Exception\InvalidArgumentException
- * @expectedExceptionMessage name is null
* @throws ZipException
*/
public function testRenameEntryNull2()
{
+ $this->setExpectedException(InvalidArgumentException::class, 'name is null');
+
$zipFile = new ZipFile();
$zipFile->rename('old-file', null);
}
/**
- * @expectedException \PhpZip\Exception\InvalidArgumentException
- * @expectedExceptionMessage is exists
* @throws ZipException
*/
- public function testRenameEntryNewEntyExists()
+ public function testRenameEntryToExistsNewEntry()
{
+ $this->setExpectedException(InvalidArgumentException::class, 'is exists');
+
$zipFile = new ZipFile();
$zipFile['file'] = 'content';
$zipFile['file2'] = 'content 2';
@@ -493,11 +531,12 @@ class ZipFileTest extends ZipTestCase
}
/**
- * @expectedException \PhpZip\Exception\ZipEntryNotFoundException
* @throws ZipException
*/
public function testRenameEntryNotFound()
{
+ $this->setExpectedException(ZipEntryNotFoundException::class);
+
$zipFile = new ZipFile();
$zipFile['file'] = 'content';
$zipFile['file2'] = 'content 2';
@@ -511,11 +550,12 @@ class ZipFileTest extends ZipTestCase
/**
* Delete entry from name.
+ *
* @throws ZipException
*/
public function testDeleteFromName()
{
- $inputDir = dirname(dirname(__DIR__)) . DIRECTORY_SEPARATOR;
+ $inputDir = \dirname(\dirname(__DIR__)) . \DIRECTORY_SEPARATOR;
$deleteEntryName = 'composer.json';
$zipFile = new ZipFile();
@@ -523,17 +563,17 @@ class ZipFileTest extends ZipTestCase
$zipFile->saveAsFile($this->outputFilename);
$zipFile->close();
- $this->assertCorrectZipArchive($this->outputFilename);
+ static::assertCorrectZipArchive($this->outputFilename);
$zipFile->openFile($this->outputFilename);
$zipFile->deleteFromName($deleteEntryName);
$zipFile->saveAsFile($this->outputFilename);
$zipFile->close();
- $this->assertCorrectZipArchive($this->outputFilename);
+ static::assertCorrectZipArchive($this->outputFilename);
$zipFile->openFile($this->outputFilename);
- $this->assertFalse(isset($zipFile[$deleteEntryName]));
+ static::assertFalse(isset($zipFile[$deleteEntryName]));
$zipFile->close();
}
@@ -551,93 +591,93 @@ class ZipFileTest extends ZipTestCase
$zipFile->close();
$zipFile->openFile($this->outputFilename);
- $this->assertEquals(sizeof($zipFile), 1);
- $this->assertTrue(isset($zipFile['entry1']));
- $this->assertFalse(isset($zipFile['entry2']));
+ static::assertSame(\count($zipFile), 1);
+ static::assertTrue(isset($zipFile['entry1']));
+ static::assertFalse(isset($zipFile['entry2']));
$zipFile->close();
}
/**
- * @expectedException \PhpZip\Exception\ZipEntryNotFoundException
+ * @throws ZipEntryNotFoundException
*/
public function testDeleteFromNameNotFoundEntry()
{
+ $this->setExpectedException(ZipEntryNotFoundException::class);
+
$zipFile = new ZipFile();
$zipFile->deleteFromName('entry');
}
/**
- * Delete zip entries from glob pattern
+ * Delete zip entries from glob pattern.
+ *
* @throws ZipException
*/
public function testDeleteFromGlob()
{
- $inputDir = dirname(dirname(__DIR__));
+ $inputDir = \dirname(\dirname(__DIR__));
$zipFile = new ZipFile();
$zipFile->addFilesFromGlobRecursive($inputDir, '**.{xml,json,md}', '/');
- $this->assertTrue(isset($zipFile['composer.json']));
- $this->assertTrue(isset($zipFile['phpunit.xml']));
+ static::assertTrue(isset($zipFile['composer.json']));
+ static::assertTrue(isset($zipFile['phpunit.xml']));
$zipFile->saveAsFile($this->outputFilename);
$zipFile->close();
- $this->assertCorrectZipArchive($this->outputFilename);
+ static::assertCorrectZipArchive($this->outputFilename);
$zipFile->openFile($this->outputFilename);
- $this->assertTrue(isset($zipFile['composer.json']));
- $this->assertTrue(isset($zipFile['phpunit.xml']));
+ static::assertTrue(isset($zipFile['composer.json']));
+ static::assertTrue(isset($zipFile['phpunit.xml']));
$zipFile->deleteFromGlob('**.{xml,json}');
- $this->assertFalse(isset($zipFile['composer.json']));
- $this->assertFalse(isset($zipFile['phpunit.xml']));
+ static::assertFalse(isset($zipFile['composer.json']));
+ static::assertFalse(isset($zipFile['phpunit.xml']));
$zipFile->saveAsFile($this->outputFilename);
$zipFile->close();
- $this->assertCorrectZipArchive($this->outputFilename);
+ static::assertCorrectZipArchive($this->outputFilename);
$zipFile->openFile($this->outputFilename);
- $this->assertTrue($zipFile->count() > 0);
+ static::assertTrue($zipFile->count() > 0);
foreach ($zipFile->getListFiles() as $name) {
- $this->assertStringEndsWith('.md', $name);
+ static::assertStringEndsWith('.md', $name);
}
$zipFile->close();
}
- /**
- * @expectedException \PhpZip\Exception\InvalidArgumentException
- * @expectedExceptionMessage The glob pattern is not specified
- */
public function testDeleteFromGlobFailNull()
{
+ $this->setExpectedException(InvalidArgumentException::class, 'The glob pattern is not specified');
+
$zipFile = new ZipFile();
$zipFile->deleteFromGlob(null);
}
- /**
- * @expectedException \PhpZip\Exception\InvalidArgumentException
- * @expectedExceptionMessage The glob pattern is not specified
- */
public function testDeleteFromGlobFailEmpty()
{
+ $this->setExpectedException(InvalidArgumentException::class, 'The glob pattern is not specified');
+
$zipFile = new ZipFile();
$zipFile->deleteFromGlob('');
}
/**
- * Delete entries from regex pattern
+ * Delete entries from regex pattern.
+ *
* @throws ZipException
*/
public function testDeleteFromRegex()
{
- $inputDir = dirname(dirname(__DIR__));
+ $inputDir = \dirname(\dirname(__DIR__));
$zipFile = new ZipFile();
$zipFile->addFilesFromRegexRecursive($inputDir, '~\.(xml|json)$~i', 'Path');
$zipFile->saveAsFile($this->outputFilename);
$zipFile->close();
- $this->assertCorrectZipArchive($this->outputFilename);
+ static::assertCorrectZipArchive($this->outputFilename);
$zipFile->openFile($this->outputFilename);
$zipFile->deleteFromRegex('~\.(json)$~i');
@@ -646,75 +686,73 @@ class ZipFileTest extends ZipTestCase
$zipFile->saveAsFile($this->outputFilename);
$zipFile->close();
- $this->assertCorrectZipArchive($this->outputFilename);
+ static::assertCorrectZipArchive($this->outputFilename);
$zipFile->openFile($this->outputFilename);
- $this->assertFalse(isset($zipFile['Path/composer.json']));
- $this->assertFalse(isset($zipFile['Path/test.txt']));
- $this->assertTrue(isset($zipFile['Path/phpunit.xml']));
+ static::assertFalse(isset($zipFile['Path/composer.json']));
+ static::assertFalse(isset($zipFile['Path/test.txt']));
+ static::assertTrue(isset($zipFile['Path/phpunit.xml']));
$zipFile->close();
}
- /**
- * @expectedException \PhpZip\Exception\InvalidArgumentException
- * @expectedExceptionMessage The regex pattern is not specified
- */
public function testDeleteFromRegexFailNull()
{
+ $this->setExpectedException(InvalidArgumentException::class, 'The regex pattern is not specified');
+
$zipFile = new ZipFile();
$zipFile->deleteFromRegex(null);
}
- /**
- * @expectedException \PhpZip\Exception\InvalidArgumentException
- * @expectedExceptionMessage The regex pattern is not specified
- */
public function testDeleteFromRegexFailEmpty()
{
+ $this->setExpectedException(InvalidArgumentException::class, 'The regex pattern is not specified');
+
$zipFile = new ZipFile();
$zipFile->deleteFromRegex('');
}
/**
- * Delete all entries
+ * Delete all entries.
+ *
* @throws ZipException
*/
public function testDeleteAll()
{
$zipFile = new ZipFile();
- $zipFile->addDirRecursive(dirname(dirname(__DIR__)) .DIRECTORY_SEPARATOR. 'src');
- $this->assertTrue($zipFile->count() > 0);
+ $zipFile->addDirRecursive(\dirname(\dirname(__DIR__)) . \DIRECTORY_SEPARATOR . 'src');
+ static::assertTrue($zipFile->count() > 0);
$zipFile->saveAsFile($this->outputFilename);
$zipFile->close();
- $this->assertCorrectZipArchive($this->outputFilename);
+ static::assertCorrectZipArchive($this->outputFilename);
$zipFile->openFile($this->outputFilename);
- $this->assertTrue($zipFile->count() > 0);
+ static::assertTrue($zipFile->count() > 0);
$zipFile->deleteAll();
$zipFile->saveAsFile($this->outputFilename);
$zipFile->close();
- $this->assertCorrectEmptyZip($this->outputFilename);
+ static::assertCorrectEmptyZip($this->outputFilename);
$zipFile->openFile($this->outputFilename);
- $this->assertEquals($zipFile->count(), 0);
+ static::assertSame($zipFile->count(), 0);
$zipFile->close();
}
/**
* Test zip archive comment.
+ *
* @throws ZipException
*/
public function testArchiveComment()
{
- $comment = "This zip file comment" . PHP_EOL
- . "Αυτό το σχόλιο αρχείο zip" . PHP_EOL
- . "Это комментарий zip архива" . PHP_EOL
- . "這個ZIP文件註釋" . PHP_EOL
- . "ეს zip ფაილის კომენტარი" . PHP_EOL
- . "このzipファイルにコメント" . PHP_EOL
- . "ความคิดเห็นนี้ไฟล์ซิป";
+ $comment = 'This zip file comment' . \PHP_EOL
+ . 'Αυτό το σχόλιο αρχείο zip' . \PHP_EOL
+ . 'Это комментарий zip архива' . \PHP_EOL
+ . '這個ZIP文件註釋' . \PHP_EOL
+ . 'ეს zip ფაილის კომენტარი' . \PHP_EOL
+ . 'このzipファイルにコメント' . \PHP_EOL
+ . 'ความคิดเห็นนี้ไฟล์ซิป';
$zipFile = new ZipFile();
$zipFile->setArchiveComment($comment);
@@ -722,32 +760,32 @@ class ZipFileTest extends ZipTestCase
$zipFile->saveAsFile($this->outputFilename);
$zipFile->close();
- $this->assertCorrectZipArchive($this->outputFilename);
+ static::assertCorrectZipArchive($this->outputFilename);
$zipFile->openFile($this->outputFilename);
- $this->assertEquals($zipFile->getArchiveComment(), $comment);
+ static::assertSame($zipFile->getArchiveComment(), $comment);
$zipFile->setArchiveComment(null); // remove archive comment
$zipFile->saveAsFile($this->outputFilename);
$zipFile->close();
- $this->assertCorrectZipArchive($this->outputFilename);
+ static::assertCorrectZipArchive($this->outputFilename);
// check empty comment
$zipFile->openFile($this->outputFilename);
- $this->assertEquals($zipFile->getArchiveComment(), "");
+ static::assertNull($zipFile->getArchiveComment());
$zipFile->close();
}
/**
* Test very long archive comment.
- *
- * @expectedException \PhpZip\Exception\InvalidArgumentException
*/
public function testVeryLongArchiveComment()
{
- $comment = "Very long comment" . PHP_EOL .
- "Очень длинный комментарий" . PHP_EOL;
- $comment = str_repeat($comment, ceil(0xffff / strlen($comment)) + strlen($comment) + 1);
+ $this->setExpectedException(InvalidArgumentException::class);
+
+ $comment = 'Very long comment' . \PHP_EOL .
+ 'Очень длинный комментарий' . \PHP_EOL;
+ $comment = str_repeat($comment, ceil(0xffff / \strlen($comment)) + \strlen($comment) + 1);
$zipFile = new ZipFile();
$zipFile->setArchiveComment($comment);
@@ -755,6 +793,7 @@ class ZipFileTest extends ZipTestCase
/**
* Test zip entry comment.
+ *
* @throws ZipException
*/
public function testEntryComment()
@@ -762,11 +801,11 @@ class ZipFileTest extends ZipTestCase
$entries = [
'文件1.txt' => [
'data' => CryptoUtil::randomBytes(255),
- 'comment' => "這是註釋的條目。",
+ 'comment' => '這是註釋的條目。',
],
'file2.txt' => [
'data' => CryptoUtil::randomBytes(255),
- 'comment' => null
+ 'comment' => null,
],
'file3.txt' => [
'data' => CryptoUtil::randomBytes(255),
@@ -774,20 +813,21 @@ class ZipFileTest extends ZipTestCase
],
'file4.txt' => [
'data' => CryptoUtil::randomBytes(255),
- 'comment' => "Комментарий файла"
+ 'comment' => 'Комментарий файла',
],
'file5.txt' => [
'data' => CryptoUtil::randomBytes(255),
- 'comment' => "ไฟล์แสดงความคิดเห็น"
+ 'comment' => 'ไฟล์แสดงความคิดเห็น',
],
'file6 emoji 🙍🏼.txt' => [
'data' => CryptoUtil::randomBytes(255),
- 'comment' => "Emoji comment file - 😀 ⛈ ❤️ 🤴🏽"
+ 'comment' => 'Emoji comment file - 😀 ⛈ ❤️ 🤴🏽',
],
];
// create archive with entry comments
$zipFile = new ZipFile();
+
foreach ($entries as $entryName => $item) {
$zipFile->addFromString($entryName, $item['data']);
$zipFile->setEntryComment($entryName, $item['comment']);
@@ -795,15 +835,16 @@ class ZipFileTest extends ZipTestCase
$zipFile->saveAsFile($this->outputFilename);
$zipFile->close();
- $this->assertCorrectZipArchive($this->outputFilename);
+ static::assertCorrectZipArchive($this->outputFilename);
// check and modify comments
$zipFile->openFile($this->outputFilename);
+
foreach ($zipFile->getListFiles() as $entryName) {
$entriesItem = $entries[$entryName];
- $this->assertNotEmpty($entriesItem);
- $this->assertEquals($zipFile[$entryName], $entriesItem['data']);
- $this->assertEquals($zipFile->getEntryComment($entryName), (string)$entriesItem['comment']);
+ static::assertNotEmpty($entriesItem);
+ static::assertSame($zipFile[$entryName], $entriesItem['data']);
+ static::assertSame($zipFile->getEntryComment($entryName), (string) $entriesItem['comment']);
}
// modify comment
$entries['file5.txt']['comment'] = mt_rand(1, 100000000);
@@ -811,14 +852,15 @@ class ZipFileTest extends ZipTestCase
$zipFile->saveAsFile($this->outputFilename);
$zipFile->close();
- $this->assertCorrectZipArchive($this->outputFilename);
+ static::assertCorrectZipArchive($this->outputFilename);
// check modify comments
$zipFile->openFile($this->outputFilename);
+
foreach ($entries as $entryName => $entriesItem) {
- $this->assertTrue(isset($zipFile[$entryName]));
- $this->assertEquals($zipFile->getEntryComment($entryName), (string)$entriesItem['comment']);
- $this->assertEquals($zipFile[$entryName], $entriesItem['data']);
+ static::assertTrue(isset($zipFile[$entryName]));
+ static::assertSame($zipFile->getEntryComment($entryName), (string) $entriesItem['comment']);
+ static::assertSame($zipFile[$entryName], $entriesItem['data']);
}
$zipFile->close();
}
@@ -826,14 +868,15 @@ class ZipFileTest extends ZipTestCase
/**
* Test zip entry very long comment.
*
- * @expectedException \PhpZip\Exception\ZipException
- * @expectedExceptionMessage Comment too long
+ * @throws ZipException
*/
public function testVeryLongEntryComment()
{
- $comment = "Very long comment" . PHP_EOL .
- "Очень длинный комментарий" . PHP_EOL;
- $comment = str_repeat($comment, ceil(0xffff / strlen($comment)) + strlen($comment) + 1);
+ $this->setExpectedException(ZipException::class, 'Comment too long');
+
+ $comment = 'Very long comment' . \PHP_EOL .
+ 'Очень длинный комментарий' . \PHP_EOL;
+ $comment = str_repeat($comment, ceil(0xffff / \strlen($comment)) + \strlen($comment) + 1);
$zipFile = new ZipFile();
$zipFile->addFile(__FILE__, 'test');
@@ -841,17 +884,19 @@ class ZipFileTest extends ZipTestCase
}
/**
- * @expectedException \PhpZip\Exception\ZipEntryNotFoundException
* @throws ZipException
*/
public function testSetEntryCommentNotFoundEntry()
{
+ $this->setExpectedException(ZipEntryNotFoundException::class);
+
$zipFile = new ZipFile();
$zipFile->setEntryComment('test', 'comment');
}
/**
* Test all available support compression methods.
+ *
* @throws ZipException
*/
public function testCompressionMethod()
@@ -868,7 +913,8 @@ class ZipFileTest extends ZipTestCase
'expected' => 'Deflate',
],
];
- if (extension_loaded("bz2")) {
+
+ if (\extension_loaded('bz2')) {
$entries['3'] = [
'data' => CryptoUtil::randomBytes(255),
'method' => ZipFileInterface::METHOD_BZIP2,
@@ -877,50 +923,53 @@ class ZipFileTest extends ZipTestCase
}
$zipFile = new ZipFile();
+
foreach ($entries as $entryName => $item) {
$zipFile->addFromString($entryName, $item['data'], $item['method']);
}
$zipFile->saveAsFile($this->outputFilename);
$zipFile->close();
- $this->assertCorrectZipArchive($this->outputFilename);
+ static::assertCorrectZipArchive($this->outputFilename);
$zipFile->openFile($this->outputFilename);
$zipFile->setCompressionLevel(ZipFileInterface::LEVEL_BEST_COMPRESSION);
$zipAllInfo = $zipFile->getAllInfo();
foreach ($zipAllInfo as $entryName => $info) {
- $this->assertEquals($zipFile[$entryName], $entries[$entryName]['data']);
- $this->assertEquals($info->getMethodName(), $entries[$entryName]['expected']);
+ static::assertSame($zipFile[$entryName], $entries[$entryName]['data']);
+ static::assertSame($info->getMethodName(), $entries[$entryName]['expected']);
$entryInfo = $zipFile->getEntryInfo($entryName);
- $this->assertEquals($entryInfo, $info);
+ static::assertEquals($entryInfo, $info);
}
$zipFile->close();
}
- /**
- * @expectedException \PhpZip\Exception\InvalidArgumentException
- * @expectedExceptionMessage Invalid compression level. Minimum level -1. Maximum level 9
- */
public function testSetInvalidCompressionLevel()
{
+ $this->setExpectedException(
+ InvalidArgumentException::class,
+ 'Invalid compression level. Minimum level -1. Maximum level 9'
+ );
+
$zipFile = new ZipFile();
$zipFile->setCompressionLevel(-2);
}
- /**
- * /**
- * @expectedException \PhpZip\Exception\InvalidArgumentException
- * @expectedExceptionMessage Invalid compression level. Minimum level -1. Maximum level 9
- */
public function testSetInvalidCompressionLevel2()
{
+ $this->setExpectedException(
+ InvalidArgumentException::class,
+ 'Invalid compression level. Minimum level -1. Maximum level 9'
+ );
+
$zipFile = new ZipFile();
$zipFile->setCompressionLevel(10);
}
/**
* Test extract all files.
+ *
* @throws ZipException
*/
public function testExtract()
@@ -933,6 +982,7 @@ class ZipFileTest extends ZipTestCase
];
$zipFile = new ZipFile();
+
foreach ($entries as $entryName => $value) {
if ($value === null) {
$zipFile->addEmptyDir($entryName);
@@ -943,26 +993,29 @@ class ZipFileTest extends ZipTestCase
$zipFile->saveAsFile($this->outputFilename);
$zipFile->close();
- $this->assertTrue(mkdir($this->outputDirname, 0755, true));
+ static::assertTrue(mkdir($this->outputDirname, 0755, true));
$zipFile->openFile($this->outputFilename);
$zipFile->extractTo($this->outputDirname);
+
foreach ($entries as $entryName => $value) {
- $fullExtractedFilename = $this->outputDirname . DIRECTORY_SEPARATOR . $entryName;
+ $fullExtractedFilename = $this->outputDirname . \DIRECTORY_SEPARATOR . $entryName;
+
if ($value === null) {
- $this->assertTrue(is_dir($fullExtractedFilename));
- $this->assertTrue(FilesUtil::isEmptyDir($fullExtractedFilename));
+ static::assertTrue(is_dir($fullExtractedFilename));
+ static::assertTrue(FilesUtil::isEmptyDir($fullExtractedFilename));
} else {
- $this->assertTrue(is_file($fullExtractedFilename));
+ static::assertTrue(is_file($fullExtractedFilename));
$contents = file_get_contents($fullExtractedFilename);
- $this->assertEquals($contents, $value);
+ static::assertSame($contents, $value);
}
}
$zipFile->close();
}
/**
- * Test extract some files
+ * Test extract some files.
+ *
* @throws ZipException
*/
public function testExtractSomeFiles()
@@ -984,10 +1037,10 @@ class ZipFileTest extends ZipTestCase
'test3.txt',
'test5.txt',
'test/test/test 2.txt',
- 'test empty/dir2/'
+ 'test empty/dir2/',
];
- $this->assertTrue(mkdir($this->outputDirname, 0755, true));
+ static::assertTrue(mkdir($this->outputDirname, 0755, true));
$zipFile = new ZipFile();
$zipFile->addAll($entries);
@@ -998,37 +1051,37 @@ class ZipFileTest extends ZipTestCase
$zipFile->extractTo($this->outputDirname, $extractEntries);
foreach ($entries as $entryName => $value) {
- $fullExtractFilename = $this->outputDirname . DIRECTORY_SEPARATOR . $entryName;
- if (in_array($entryName, $extractEntries)) {
+ $fullExtractFilename = $this->outputDirname . \DIRECTORY_SEPARATOR . $entryName;
+
+ if (\in_array($entryName, $extractEntries, true)) {
if ($value === null) {
- $this->assertTrue(is_dir($fullExtractFilename));
- $this->assertTrue(FilesUtil::isEmptyDir($fullExtractFilename));
+ static::assertTrue(is_dir($fullExtractFilename));
+ static::assertTrue(FilesUtil::isEmptyDir($fullExtractFilename));
} else {
- $this->assertTrue(is_file($fullExtractFilename));
+ static::assertTrue(is_file($fullExtractFilename));
$contents = file_get_contents($fullExtractFilename);
- $this->assertEquals($contents, $value);
+ static::assertEquals($contents, $value);
}
+ } elseif ($value === null) {
+ static::assertFalse(is_dir($fullExtractFilename));
} else {
- if ($value === null) {
- $this->assertFalse(is_dir($fullExtractFilename));
- } else {
- $this->assertFalse(is_file($fullExtractFilename));
- }
+ static::assertFalse(is_file($fullExtractFilename));
}
}
- $this->assertFalse(is_file($this->outputDirname . DIRECTORY_SEPARATOR . 'test/test/test.txt'));
+ static::assertFalse(is_file($this->outputDirname . \DIRECTORY_SEPARATOR . 'test/test/test.txt'));
$zipFile->extractTo($this->outputDirname, 'test/test/test.txt');
- $this->assertTrue(is_file($this->outputDirname . DIRECTORY_SEPARATOR . 'test/test/test.txt'));
+ static::assertTrue(is_file($this->outputDirname . \DIRECTORY_SEPARATOR . 'test/test/test.txt'));
$zipFile->close();
}
/**
- * @expectedException \PhpZip\Exception\ZipException
- * @expectedExceptionMessage not found
+ * @throws ZipException
*/
public function testExtractFail()
{
+ $this->setExpectedException(ZipException::class, 'not found');
+
$zipFile = new ZipFile();
$zipFile['file'] = 'content';
$zipFile->saveAsFile($this->outputFilename);
@@ -1039,11 +1092,12 @@ class ZipFileTest extends ZipTestCase
}
/**
- * @expectedException \PhpZip\Exception\ZipException
- * @expectedExceptionMessage Destination is not directory
+ * @throws ZipException
*/
public function testExtractFail2()
{
+ $this->setExpectedException(ZipException::class, 'Destination is not directory');
+
$zipFile = new ZipFile();
$zipFile['file'] = 'content';
$zipFile->saveAsFile($this->outputFilename);
@@ -1054,14 +1108,15 @@ class ZipFileTest extends ZipTestCase
}
/**
- * @expectedException \PhpZip\Exception\ZipException
- * @expectedExceptionMessage Destination is not writable directory
+ * @throws ZipException
*/
public function testExtractFail3()
{
+ $this->setExpectedException(ZipException::class, 'Destination is not writable directory');
+
/** @noinspection PhpComposerExtensionStubsInspection */
if (posix_getuid() === 0) {
- $this->markTestSkipped('Skip the test for a user with root privileges');
+ static::markTestSkipped('Skip the test for a user with root privileges');
}
$zipFile = new ZipFile();
@@ -1069,79 +1124,82 @@ class ZipFileTest extends ZipTestCase
$zipFile->saveAsFile($this->outputFilename);
$zipFile->close();
- $this->assertTrue(mkdir($this->outputDirname, 0444, true));
- $this->assertTrue(chmod($this->outputDirname, 0444));
+ static::assertTrue(mkdir($this->outputDirname, 0444, true));
+ static::assertTrue(chmod($this->outputDirname, 0444));
$zipFile->openFile($this->outputFilename);
$zipFile->extractTo($this->outputDirname);
}
/**
- * @expectedException \PhpZip\Exception\InvalidArgumentException
- * @expectedExceptionMessage entryName is null
+ * @noinspection OnlyWritesOnParameterInspection
*/
public function testAddFromArrayAccessNullName()
{
+ $this->setExpectedException(InvalidArgumentException::class, 'entryName is null');
+
$zipFile = new ZipFile();
$zipFile[null] = 'content';
}
/**
- * @expectedException \PhpZip\Exception\InvalidArgumentException
- * @expectedExceptionMessage entryName is empty
+ * @noinspection OnlyWritesOnParameterInspection
*/
public function testAddFromArrayAccessEmptyName()
{
+ $this->setExpectedException(InvalidArgumentException::class, 'entryName is empty');
+
$zipFile = new ZipFile();
$zipFile[''] = 'content';
}
/**
- * @expectedException \PhpZip\Exception\InvalidArgumentException
- * @expectedExceptionMessage Contents is null
* @throws ZipException
*/
public function testAddFromStringNullContents()
{
+ $this->setExpectedException(InvalidArgumentException::class, 'Contents is null');
+
$zipFile = new ZipFile();
$zipFile->addFromString('file', null);
}
/**
- * @expectedException \PhpZip\Exception\InvalidArgumentException
- * @expectedExceptionMessage Entry name is null
* @throws ZipException
*/
public function testAddFromStringNullEntryName()
{
+ $this->setExpectedException(InvalidArgumentException::class, 'Entry name is null');
+
$zipFile = new ZipFile();
$zipFile->addFromString(null, 'contents');
}
/**
- * @expectedException \PhpZip\Exception\ZipUnsupportMethodException
- * @expectedExceptionMessage Unsupported compression method
* @throws ZipException
*/
public function testAddFromStringUnsupportedMethod()
{
+ $this->setExpectedException(ZipUnsupportMethodException::class, 'Unsupported compression method');
+
$zipFile = new ZipFile();
$zipFile->addFromString('file', 'contents', ZipEntry::METHOD_WINZIP_AES);
}
/**
- * @expectedException \PhpZip\Exception\InvalidArgumentException
- * @expectedExceptionMessage Empty entry name
* @throws ZipException
*/
public function testAddFromStringEmptyEntryName()
{
+ $this->setExpectedException(InvalidArgumentException::class, 'Empty entry name');
+
$zipFile = new ZipFile();
$zipFile->addFromString('', 'contents');
}
/**
* Test compression method from add string.
+ *
* @throws ZipException
*/
public function testAddFromStringCompressionMethod()
@@ -1149,8 +1207,8 @@ class ZipFileTest extends ZipTestCase
$fileStored = sys_get_temp_dir() . '/zip-stored.txt';
$fileDeflated = sys_get_temp_dir() . '/zip-deflated.txt';
- $this->assertNotFalse(file_put_contents($fileStored, 'content'));
- $this->assertNotFalse(file_put_contents($fileDeflated, str_repeat('content', 200)));
+ static::assertNotFalse(file_put_contents($fileStored, 'content'));
+ static::assertNotFalse(file_put_contents($fileDeflated, str_repeat('content', 200)));
$zipFile = new ZipFile();
$zipFile->addFromString(basename($fileStored), file_get_contents($fileStored));
@@ -1164,43 +1222,43 @@ class ZipFileTest extends ZipTestCase
$zipFile->openFile($this->outputFilename);
$infoStored = $zipFile->getEntryInfo(basename($fileStored));
$infoDeflated = $zipFile->getEntryInfo(basename($fileDeflated));
- $this->assertEquals($infoStored->getMethodName(), 'No compression');
- $this->assertEquals($infoDeflated->getMethodName(), 'Deflate');
+ static::assertSame($infoStored->getMethodName(), 'No compression');
+ static::assertSame($infoDeflated->getMethodName(), 'Deflate');
$zipFile->close();
}
/**
- * @expectedException \PhpZip\Exception\InvalidArgumentException
- * @expectedExceptionMessage Stream is not resource
* @throws ZipException
*/
public function testAddFromStreamInvalidResource()
{
+ $this->setExpectedException(InvalidArgumentException::class, 'Stream is not resource');
+
$zipFile = new ZipFile();
/** @noinspection PhpParamsInspection */
- $zipFile->addFromStream("invalid resource", "name");
+ $zipFile->addFromStream('invalid resource', 'name');
}
/**
- * @expectedException \PhpZip\Exception\InvalidArgumentException
- * @expectedExceptionMessage Empty entry name
* @throws ZipException
*/
public function testAddFromStreamEmptyEntryName()
{
+ $this->setExpectedException(InvalidArgumentException::class, 'Empty entry name');
+
$handle = fopen(__FILE__, 'rb');
$zipFile = new ZipFile();
- $zipFile->addFromStream($handle, "");
+ $zipFile->addFromStream($handle, '');
}
/**
- * @expectedException \PhpZip\Exception\ZipUnsupportMethodException
- * @expectedExceptionMessage Unsupported method
* @throws ZipException
*/
public function testAddFromStreamUnsupportedMethod()
{
+ $this->setExpectedException(ZipUnsupportMethodException::class, 'Unsupported method');
+
$handle = fopen(__FILE__, 'rb');
$zipFile = new ZipFile();
@@ -1209,6 +1267,7 @@ class ZipFileTest extends ZipTestCase
/**
* Test compression method from add stream.
+ *
* @throws ZipException
*/
public function testAddFromStreamCompressionMethod()
@@ -1216,8 +1275,8 @@ class ZipFileTest extends ZipTestCase
$fileStored = sys_get_temp_dir() . '/zip-stored.txt';
$fileDeflated = sys_get_temp_dir() . '/zip-deflated.txt';
- $this->assertNotFalse(file_put_contents($fileStored, 'content'));
- $this->assertNotFalse(file_put_contents($fileDeflated, str_repeat('content', 200)));
+ static::assertNotFalse(file_put_contents($fileStored, 'content'));
+ static::assertNotFalse(file_put_contents($fileDeflated, str_repeat('content', 200)));
$fpStored = fopen($fileStored, 'rb');
$fpDeflated = fopen($fileDeflated, 'rb');
@@ -1234,376 +1293,377 @@ class ZipFileTest extends ZipTestCase
$zipFile->openFile($this->outputFilename);
$infoStored = $zipFile->getEntryInfo(basename($fileStored));
$infoDeflated = $zipFile->getEntryInfo(basename($fileDeflated));
- $this->assertEquals($infoStored->getMethodName(), 'No compression');
- $this->assertEquals($infoDeflated->getMethodName(), 'Deflate');
+ static::assertSame($infoStored->getMethodName(), 'No compression');
+ static::assertSame($infoDeflated->getMethodName(), 'Deflate');
$zipFile->close();
}
/**
- * @expectedException \PhpZip\Exception\InvalidArgumentException
- * @expectedExceptionMessage file is null
* @throws ZipException
*/
public function testAddFileNullFileName()
{
+ $this->setExpectedException(InvalidArgumentException::class, 'file is null');
+
$zipFile = new ZipFile();
$zipFile->addFile(null);
}
/**
- * @expectedException \PhpZip\Exception\ZipException
- * @expectedExceptionMessage does not exist
+ * @throws ZipException
*/
public function testAddFileCantExists()
{
+ $this->setExpectedException(ZipException::class, 'does not exist');
+
$zipFile = new ZipFile();
$zipFile->addFile('path/to/file');
}
/**
- * @expectedException \PhpZip\Exception\ZipUnsupportMethodException
- * @expectedExceptionMessage Unsupported compression method 99
* @throws ZipException
*/
public function testAddFileUnsupportedMethod()
{
+ $this->setExpectedException(ZipUnsupportMethodException::class, 'Unsupported compression method 99');
+
$zipFile = new ZipFile();
$zipFile->addFile(__FILE__, null, ZipEntry::METHOD_WINZIP_AES);
}
/**
- * @expectedException \PhpZip\Exception\ZipException
- * @expectedExceptionMessage file could not be read
* @throws ZipException
*/
public function testAddFileCantOpen()
{
+ $this->setExpectedException(ZipException::class, 'file could not be read');
+
/** @noinspection PhpComposerExtensionStubsInspection */
if (posix_getuid() === 0) {
- $this->markTestSkipped('Skip the test for a user with root privileges');
+ static::markTestSkipped('Skip the test for a user with root privileges');
}
- $this->assertNotFalse(file_put_contents($this->outputFilename, ''));
- $this->assertTrue(chmod($this->outputFilename, 0244));
+ static::assertNotFalse(file_put_contents($this->outputFilename, ''));
+ static::assertTrue(chmod($this->outputFilename, 0244));
$zipFile = new ZipFile();
$zipFile->addFile($this->outputFilename);
}
/**
- * @expectedException \PhpZip\Exception\InvalidArgumentException
- * @expectedExceptionMessage Input dir is null
* @throws ZipException
*/
public function testAddDirNullDirname()
{
+ $this->setExpectedException(InvalidArgumentException::class, 'Input dir is null');
+
$zipFile = new ZipFile();
$zipFile->addDir(null);
}
/**
- * @expectedException \PhpZip\Exception\InvalidArgumentException
- * @expectedExceptionMessage The input directory is not specified
* @throws ZipException
*/
public function testAddDirEmptyDirname()
{
+ $this->setExpectedException(InvalidArgumentException::class, 'The input directory is not specified');
+
$zipFile = new ZipFile();
- $zipFile->addDir("");
+ $zipFile->addDir('');
}
/**
- * @expectedException \PhpZip\Exception\InvalidArgumentException
- * @expectedExceptionMessage does not exist
* @throws ZipException
*/
public function testAddDirCantExists()
{
+ $this->setExpectedException(InvalidArgumentException::class, 'does not exist');
+
$zipFile = new ZipFile();
- $zipFile->addDir(uniqid());
+ $zipFile->addDir(uniqid('', true));
}
/**
- * @expectedException \PhpZip\Exception\InvalidArgumentException
- * @expectedExceptionMessage Input dir is null
* @throws ZipException
*/
public function testAddDirRecursiveNullDirname()
{
+ $this->setExpectedException(InvalidArgumentException::class, 'Input dir is null');
+
$zipFile = new ZipFile();
$zipFile->addDirRecursive(null);
}
/**
- * @expectedException \PhpZip\Exception\InvalidArgumentException
- * @expectedExceptionMessage The input directory is not specified
* @throws ZipException
*/
public function testAddDirRecursiveEmptyDirname()
{
+ $this->setExpectedException(InvalidArgumentException::class, 'The input directory is not specified');
+
$zipFile = new ZipFile();
- $zipFile->addDirRecursive("");
+ $zipFile->addDirRecursive('');
}
/**
- * @expectedException \PhpZip\Exception\InvalidArgumentException
- * @expectedExceptionMessage does not exist
* @throws ZipException
*/
public function testAddDirRecursiveCantExists()
{
+ $this->setExpectedException(InvalidArgumentException::class, 'does not exist');
+
$zipFile = new ZipFile();
- $zipFile->addDirRecursive(uniqid());
+ $zipFile->addDirRecursive(uniqid('', true));
}
/**
- * @expectedException \PhpZip\Exception\InvalidArgumentException
- * @expectedExceptionMessage Input dir is null
* @throws ZipException
*/
public function testAddFilesFromGlobNull()
{
+ $this->setExpectedException(InvalidArgumentException::class, 'Input dir is null');
+
$zipFile = new ZipFile();
$zipFile->addFilesFromGlob(null, '*.png');
}
/**
- * @expectedException \PhpZip\Exception\InvalidArgumentException
- * @expectedExceptionMessage The input directory is not specified
* @throws ZipException
*/
public function testAddFilesFromGlobEmpty()
{
+ $this->setExpectedException(InvalidArgumentException::class, 'The input directory is not specified');
+
$zipFile = new ZipFile();
- $zipFile->addFilesFromGlob("", '*.png');
+ $zipFile->addFilesFromGlob('', '*.png');
}
/**
- * @expectedException \PhpZip\Exception\InvalidArgumentException
- * @expectedExceptionMessage does not exist
* @throws ZipException
*/
public function testAddFilesFromGlobCantExists()
{
+ $this->setExpectedException(InvalidArgumentException::class, 'does not exist');
+
$zipFile = new ZipFile();
- $zipFile->addFilesFromGlob("path/to/path", '*.png');
+ $zipFile->addFilesFromGlob('path/to/path', '*.png');
}
/**
- * @expectedException \PhpZip\Exception\InvalidArgumentException
- * @expectedExceptionMessage The glob pattern is not specified
* @throws ZipException
*/
public function testAddFilesFromGlobNullPattern()
{
+ $this->setExpectedException(InvalidArgumentException::class, 'The glob pattern is not specified');
+
$zipFile = new ZipFile();
$zipFile->addFilesFromGlob(__DIR__, null);
}
/**
- * @expectedException \PhpZip\Exception\InvalidArgumentException
- * @expectedExceptionMessage The glob pattern is not specified
* @throws ZipException
*/
public function testAddFilesFromGlobEmptyPattern()
{
+ $this->setExpectedException(InvalidArgumentException::class, 'The glob pattern is not specified');
+
$zipFile = new ZipFile();
$zipFile->addFilesFromGlob(__DIR__, '');
}
/**
- * @expectedException \PhpZip\Exception\InvalidArgumentException
- * @expectedExceptionMessage Input dir is null
* @throws ZipException
*/
public function testAddFilesFromGlobRecursiveNull()
{
+ $this->setExpectedException(InvalidArgumentException::class, 'Input dir is null');
+
$zipFile = new ZipFile();
$zipFile->addFilesFromGlobRecursive(null, '*.png');
}
/**
- * @expectedException \PhpZip\Exception\InvalidArgumentException
- * @expectedExceptionMessage The input directory is not specified
* @throws ZipException
*/
public function testAddFilesFromGlobRecursiveEmpty()
{
+ $this->setExpectedException(InvalidArgumentException::class, 'The input directory is not specified');
+
$zipFile = new ZipFile();
- $zipFile->addFilesFromGlobRecursive("", '*.png');
+ $zipFile->addFilesFromGlobRecursive('', '*.png');
}
/**
- * @expectedException \PhpZip\Exception\InvalidArgumentException
- * @expectedExceptionMessage does not exist
* @throws ZipException
*/
public function testAddFilesFromGlobRecursiveCantExists()
{
+ $this->setExpectedException(InvalidArgumentException::class, 'does not exist');
+
$zipFile = new ZipFile();
- $zipFile->addFilesFromGlobRecursive("path/to/path", '*.png');
+ $zipFile->addFilesFromGlobRecursive('path/to/path', '*.png');
}
/**
- * @expectedException \PhpZip\Exception\InvalidArgumentException
- * @expectedExceptionMessage The glob pattern is not specified
* @throws ZipException
*/
public function testAddFilesFromGlobRecursiveNullPattern()
{
+ $this->setExpectedException(InvalidArgumentException::class, 'The glob pattern is not specified');
+
$zipFile = new ZipFile();
$zipFile->addFilesFromGlobRecursive(__DIR__, null);
}
/**
- * @expectedException \PhpZip\Exception\InvalidArgumentException
- * @expectedExceptionMessage The glob pattern is not specified
* @throws ZipException
*/
public function testAddFilesFromGlobRecursiveEmptyPattern()
{
+ $this->setExpectedException(InvalidArgumentException::class, 'The glob pattern is not specified');
+
$zipFile = new ZipFile();
$zipFile->addFilesFromGlobRecursive(__DIR__, '');
}
/**
- * @expectedException \PhpZip\Exception\InvalidArgumentException
- * @expectedExceptionMessage The input directory is not specified
* @throws ZipException
*/
public function testAddFilesFromRegexDirectoryNull()
{
+ $this->setExpectedException(InvalidArgumentException::class, 'The input directory is not specified');
+
$zipFile = new ZipFile();
$zipFile->addFilesFromRegex(null, '~\.png$~i');
}
/**
- * @expectedException \PhpZip\Exception\InvalidArgumentException
- * @expectedExceptionMessage The input directory is not specified
* @throws ZipException
*/
public function testAddFilesFromRegexDirectoryEmpty()
{
+ $this->setExpectedException(InvalidArgumentException::class, 'The input directory is not specified');
+
$zipFile = new ZipFile();
- $zipFile->addFilesFromRegex("", '~\.png$~i');
+ $zipFile->addFilesFromRegex('', '~\.png$~i');
}
/**
- * @expectedException \PhpZip\Exception\InvalidArgumentException
- * @expectedExceptionMessage does not exist
* @throws ZipException
*/
public function testAddFilesFromRegexCantExists()
{
+ $this->setExpectedException(InvalidArgumentException::class, 'does not exist');
+
$zipFile = new ZipFile();
- $zipFile->addFilesFromRegex("path/to/path", '~\.png$~i');
+ $zipFile->addFilesFromRegex('path/to/path', '~\.png$~i');
}
/**
- * @expectedException \PhpZip\Exception\InvalidArgumentException
- * @expectedExceptionMessage The regex pattern is not specified
* @throws ZipException
*/
public function testAddFilesFromRegexNullPattern()
{
+ $this->setExpectedException(InvalidArgumentException::class, 'The regex pattern is not specified');
+
$zipFile = new ZipFile();
$zipFile->addFilesFromRegex(__DIR__, null);
}
/**
- * @expectedException \PhpZip\Exception\InvalidArgumentException
- * @expectedExceptionMessage The regex pattern is not specified
* @throws ZipException
*/
public function testAddFilesFromRegexEmptyPattern()
{
+ $this->setExpectedException(InvalidArgumentException::class, 'The regex pattern is not specified');
+
$zipFile = new ZipFile();
$zipFile->addFilesFromRegex(__DIR__, '');
}
/**
- * @expectedException \PhpZip\Exception\InvalidArgumentException
- * @expectedExceptionMessage The input directory is not specified
* @throws ZipException
*/
public function testAddFilesFromRegexRecursiveDirectoryNull()
{
+ $this->setExpectedException(InvalidArgumentException::class, 'The input directory is not specified');
+
$zipFile = new ZipFile();
$zipFile->addFilesFromRegexRecursive(null, '~\.png$~i');
}
/**
- * @expectedException \PhpZip\Exception\InvalidArgumentException
- * @expectedExceptionMessage The input directory is not specified
* @throws ZipException
*/
public function testAddFilesFromRegexRecursiveEmpty()
{
+ $this->setExpectedException(InvalidArgumentException::class, 'The input directory is not specified');
+
$zipFile = new ZipFile();
- $zipFile->addFilesFromRegexRecursive("", '~\.png$~i');
+ $zipFile->addFilesFromRegexRecursive('', '~\.png$~i');
}
/**
- * @expectedException \PhpZip\Exception\InvalidArgumentException
- * @expectedExceptionMessage does not exist
* @throws ZipException
*/
public function testAddFilesFromRegexRecursiveCantExists()
{
+ $this->setExpectedException(InvalidArgumentException::class, 'does not exist');
+
$zipFile = new ZipFile();
- $zipFile->addFilesFromGlobRecursive("path/to/path", '~\.png$~i');
+ $zipFile->addFilesFromGlobRecursive('path/to/path', '~\.png$~i');
}
/**
- * @expectedException \PhpZip\Exception\InvalidArgumentException
- * @expectedExceptionMessage The regex pattern is not specified
* @throws ZipException
*/
public function testAddFilesFromRegexRecursiveNullPattern()
{
+ $this->setExpectedException(InvalidArgumentException::class, 'The regex pattern is not specified');
+
$zipFile = new ZipFile();
$zipFile->addFilesFromRegexRecursive(__DIR__, null);
}
/**
- * @expectedException \PhpZip\Exception\InvalidArgumentException
- * @expectedExceptionMessage The regex pattern is not specified
* @throws ZipException
*/
public function testAddFilesFromRegexRecursiveEmptyPattern()
{
+ $this->setExpectedException(InvalidArgumentException::class, 'The regex pattern is not specified');
+
$zipFile = new ZipFile();
$zipFile->addFilesFromRegexRecursive(__DIR__, '');
}
/**
- * @expectedException \PhpZip\Exception\InvalidArgumentException
- * @expectedExceptionMessage handle is not resource
* @throws ZipException
*/
public function testSaveAsStreamBadStream()
{
+ $this->setExpectedException(InvalidArgumentException::class, 'handle is not resource');
+
$zipFile = new ZipFile();
/** @noinspection PhpParamsInspection */
- $zipFile->saveAsStream("bad stream");
+ $zipFile->saveAsStream('bad stream');
}
/**
- * @expectedException \PhpZip\Exception\InvalidArgumentException
- * @expectedExceptionMessage can not open from write
* @throws ZipException
*/
public function testSaveAsFileNotWritable()
{
+ $this->setExpectedException(InvalidArgumentException::class, 'can not open from write');
+
/** @noinspection PhpComposerExtensionStubsInspection */
if (posix_getuid() === 0) {
- $this->markTestSkipped('Skip the test for a user with root privileges');
+ static::markTestSkipped('Skip the test for a user with root privileges');
}
- $this->assertTrue(mkdir($this->outputDirname, 0444, true));
- $this->assertTrue(chmod($this->outputDirname, 0444));
+ static::assertTrue(mkdir($this->outputDirname, 0444, true));
+ static::assertTrue(chmod($this->outputDirname, 0444));
- $this->outputFilename = $this->outputDirname . DIRECTORY_SEPARATOR . basename($this->outputFilename);
+ $this->outputFilename = $this->outputDirname . \DIRECTORY_SEPARATOR . basename($this->outputFilename);
$zipFile = new ZipFile();
$zipFile->saveAsFile($this->outputFilename);
@@ -1611,6 +1671,7 @@ class ZipFileTest extends ZipTestCase
/**
* Test `ZipFile` implemented \ArrayAccess, \Countable and |iterator.
+ *
* @throws ZipException
*/
public function testZipFileArrayAccessAndCountableAndIterator()
@@ -1622,31 +1683,34 @@ class ZipFileTest extends ZipTestCase
}
$methods = [ZipFileInterface::METHOD_STORED, ZipFileInterface::METHOD_DEFLATED];
- if (extension_loaded("bz2")) {
+
+ if (\extension_loaded('bz2')) {
$methods[] = ZipFileInterface::METHOD_BZIP2;
}
$zipFile = new ZipFile();
$zipFile->setCompressionLevel(ZipFileInterface::LEVEL_BEST_SPEED);
+
foreach ($files as $entryName => $content) {
$zipFile->addFromString($entryName, $content, $methods[array_rand($methods)]);
}
$zipFile->saveAsFile($this->outputFilename);
$zipFile->close();
- $this->assertCorrectZipArchive($this->outputFilename);
+ static::assertCorrectZipArchive($this->outputFilename);
$zipFile->openFile($this->outputFilename);
// Test \Countable
- $this->assertEquals($zipFile->count(), $numFiles);
- $this->assertEquals(count($zipFile), $numFiles);
+ static::assertSame($zipFile->count(), $numFiles);
+ static::assertSame(\count($zipFile), $numFiles);
// Test \ArrayAccess
reset($files);
+
foreach ($zipFile as $entryName => $content) {
- $this->assertEquals($entryName, key($files));
- $this->assertEquals($content, current($files));
+ static::assertSame($entryName, key($files));
+ static::assertSame($content, current($files));
next($files);
}
@@ -1654,12 +1718,13 @@ class ZipFileTest extends ZipTestCase
reset($files);
$iterator = new \ArrayIterator($zipFile);
$iterator->rewind();
+
while ($iterator->valid()) {
$key = $iterator->key();
$value = $iterator->current();
- $this->assertEquals($key, key($files));
- $this->assertEquals($value, current($files));
+ static::assertSame($key, key($files));
+ static::assertSame($value, current($files));
next($files);
$iterator->next();
@@ -1673,25 +1738,25 @@ class ZipFileTest extends ZipTestCase
$zipFile->saveAsFile($this->outputFilename);
$zipFile->close();
- $this->assertCorrectZipArchive($this->outputFilename);
+ static::assertCorrectZipArchive($this->outputFilename);
$zipFile->openFile($this->outputFilename);
- $this->assertTrue(isset($zipFile['file1.txt']));
- $this->assertTrue(isset($zipFile['dir/file2.txt']));
- $this->assertTrue(isset($zipFile['dir/empty dir/']));
- $this->assertFalse(isset($zipFile['dir/empty dir/2/']));
+ static::assertTrue(isset($zipFile['file1.txt']));
+ static::assertTrue(isset($zipFile['dir/file2.txt']));
+ static::assertTrue(isset($zipFile['dir/empty dir/']));
+ static::assertFalse(isset($zipFile['dir/empty dir/2/']));
$zipFile['dir/empty dir/2/'] = null;
unset($zipFile['dir/file2.txt'], $zipFile['dir/empty dir/']);
$zipFile->saveAsFile($this->outputFilename);
$zipFile->close();
- $this->assertCorrectZipArchive($this->outputFilename);
+ static::assertCorrectZipArchive($this->outputFilename);
$zipFile->openFile($this->outputFilename);
- $this->assertTrue(isset($zipFile['file1.txt']));
- $this->assertFalse(isset($zipFile['dir/file2.txt']));
- $this->assertFalse(isset($zipFile['dir/empty dir/']));
- $this->assertTrue(isset($zipFile['dir/empty dir/2/']));
+ static::assertTrue(isset($zipFile['file1.txt']));
+ static::assertFalse(isset($zipFile['dir/file2.txt']));
+ static::assertFalse(isset($zipFile['dir/empty dir/']));
+ static::assertTrue(isset($zipFile['dir/empty dir/2/']));
$zipFile->close();
}
@@ -1705,18 +1770,18 @@ class ZipFileTest extends ZipTestCase
$zipFile = new ZipFile();
$zipFile[$entryName] = new \SplFileInfo(__FILE__);
- $zipFile[$entryNameStream] = fopen(__FILE__, 'r');
+ $zipFile[$entryNameStream] = fopen(__FILE__, 'rb');
$zipFile->saveAsFile($this->outputFilename);
$zipFile->close();
- $this->assertCorrectZipArchive($this->outputFilename);
+ static::assertCorrectZipArchive($this->outputFilename);
$zipFile->openFile($this->outputFilename);
- $this->assertEquals(sizeof($zipFile), 2);
- $this->assertTrue(isset($zipFile[$entryName]));
- $this->assertTrue(isset($zipFile[$entryNameStream]));
- $this->assertEquals($zipFile[$entryName], file_get_contents(__FILE__));
- $this->assertEquals($zipFile[$entryNameStream], file_get_contents(__FILE__));
+ static::assertSame(\count($zipFile), 2);
+ static::assertTrue(isset($zipFile[$entryName]));
+ static::assertTrue(isset($zipFile[$entryNameStream]));
+ static::assertSame($zipFile[$entryName], file_get_contents(__FILE__));
+ static::assertSame($zipFile[$entryNameStream], file_get_contents(__FILE__));
$zipFile->close();
}
@@ -1731,54 +1796,53 @@ class ZipFileTest extends ZipTestCase
$zipFile->addFromString('file', 'content', ZipEntry::UNKNOWN);
$zipFile->addFromString('file2', base64_encode(CryptoUtil::randomBytes(512)), ZipEntry::UNKNOWN);
- $this->assertEquals($zipFile->getEntryInfo('file')->getMethodName(), 'Unknown');
- $this->assertEquals($zipFile->getEntryInfo('file2')->getMethodName(), 'Unknown');
+ static::assertSame($zipFile->getEntryInfo('file')->getMethodName(), 'Unknown');
+ static::assertSame($zipFile->getEntryInfo('file2')->getMethodName(), 'Unknown');
$zipFile->saveAsFile($this->outputFilename);
$zipFile->close();
$zipFile->openFile($this->outputFilename);
- $this->assertEquals($zipFile->getEntryInfo('file')->getMethodName(), 'No compression');
- $this->assertEquals($zipFile->getEntryInfo('file2')->getMethodName(), 'Deflate');
+ static::assertSame($zipFile->getEntryInfo('file')->getMethodName(), 'No compression');
+ static::assertSame($zipFile->getEntryInfo('file2')->getMethodName(), 'Deflate');
$zipFile->close();
}
/**
- * @expectedException \PhpZip\Exception\InvalidArgumentException
- * @expectedExceptionMessage Dir name is null
* @throws ZipException
*/
public function testAddEmptyDirNullName()
{
+ $this->setExpectedException(InvalidArgumentException::class, 'Dir name is null');
+
$zipFile = new ZipFile();
$zipFile->addEmptyDir(null);
}
/**
- * @expectedException \PhpZip\Exception\InvalidArgumentException
- * @expectedExceptionMessage Empty dir name
* @throws ZipException
*/
public function testAddEmptyDirEmptyName()
{
+ $this->setExpectedException(InvalidArgumentException::class, 'Empty dir name');
+
$zipFile = new ZipFile();
- $zipFile->addEmptyDir("");
+ $zipFile->addEmptyDir('');
}
- /**
- * @expectedException \PhpZip\Exception\ZipEntryNotFoundException
- * @expectedExceptionMessage "bad entry name"
- */
public function testNotFoundEntry()
{
+ $this->setExpectedException(ZipEntryNotFoundException::class, '"bad entry name"');
+
$zipFile = new ZipFile();
$zipFile['bad entry name'];
}
/**
* Test rewrite input file.
+ *
* @throws ZipException
*/
public function testRewriteFile()
@@ -1786,31 +1850,33 @@ class ZipFileTest extends ZipTestCase
$zipFile = new ZipFile();
$zipFile['file'] = 'content';
$zipFile['file2'] = 'content2';
- $this->assertEquals(count($zipFile), 2);
+ static::assertSame(\count($zipFile), 2);
$zipFile
->saveAsFile($this->outputFilename)
- ->close();
+ ->close()
+ ;
$md5file = md5_file($this->outputFilename);
$zipFile->openFile($this->outputFilename);
- $this->assertEquals(count($zipFile), 2);
- $this->assertTrue(isset($zipFile['file']));
- $this->assertTrue(isset($zipFile['file2']));
+ static::assertSame(\count($zipFile), 2);
+ static::assertTrue(isset($zipFile['file']));
+ static::assertTrue(isset($zipFile['file2']));
$zipFile['file3'] = 'content3';
- $this->assertEquals(count($zipFile), 3);
+ static::assertSame(\count($zipFile), 3);
$zipFile = $zipFile->rewrite();
- $this->assertEquals(count($zipFile), 3);
- $this->assertTrue(isset($zipFile['file']));
- $this->assertTrue(isset($zipFile['file2']));
- $this->assertTrue(isset($zipFile['file3']));
+ static::assertSame(\count($zipFile), 3);
+ static::assertTrue(isset($zipFile['file']));
+ static::assertTrue(isset($zipFile['file2']));
+ static::assertTrue(isset($zipFile['file3']));
$zipFile->close();
- $this->assertNotEquals(md5_file($this->outputFilename), $md5file);
+ static::assertNotSame(md5_file($this->outputFilename), $md5file);
}
/**
* Test rewrite for string.
+ *
* @throws ZipException
*/
public function testRewriteString()
@@ -1822,24 +1888,25 @@ class ZipFileTest extends ZipTestCase
$zipFile->close();
$zipFile->openFromString(file_get_contents($this->outputFilename));
- $this->assertEquals(count($zipFile), 2);
- $this->assertTrue(isset($zipFile['file']));
- $this->assertTrue(isset($zipFile['file2']));
+ static::assertSame(\count($zipFile), 2);
+ static::assertTrue(isset($zipFile['file']));
+ static::assertTrue(isset($zipFile['file2']));
$zipFile['file3'] = 'content3';
$zipFile = $zipFile->rewrite();
- $this->assertEquals(count($zipFile), 3);
- $this->assertTrue(isset($zipFile['file']));
- $this->assertTrue(isset($zipFile['file2']));
- $this->assertTrue(isset($zipFile['file3']));
+ static::assertSame(\count($zipFile), 3);
+ static::assertTrue(isset($zipFile['file']));
+ static::assertTrue(isset($zipFile['file2']));
+ static::assertTrue(isset($zipFile['file3']));
$zipFile->close();
}
/**
- * @expectedException \PhpZip\Exception\ZipException
- * @expectedExceptionMessage input stream is null
+ * @throws ZipException
*/
public function testRewriteNullStream()
{
+ $this->setExpectedException(ZipException::class, 'input stream is null');
+
$zipFile = new ZipFile();
$zipFile->rewrite();
}
@@ -1851,34 +1918,36 @@ class ZipFileTest extends ZipTestCase
{
$zipFile = new ZipFile();
$zipFile[0] = 0;
- $this->assertTrue(isset($zipFile[0]));
- $this->assertTrue(isset($zipFile['0']));
- $this->assertCount(1, $zipFile);
+ static::assertTrue(isset($zipFile[0]));
+ static::assertTrue(isset($zipFile['0']));
+ static::assertCount(1, $zipFile);
$zipFile
->saveAsFile($this->outputFilename)
- ->close();
+ ->close()
+ ;
- $this->assertCorrectZipArchive($this->outputFilename);
+ static::assertCorrectZipArchive($this->outputFilename);
$zipFile->openFile($this->outputFilename);
- $this->assertTrue(isset($zipFile[0]));
- $this->assertTrue(isset($zipFile['0']));
- $this->assertEquals($zipFile['0'], '0');
- $this->assertCount(1, $zipFile);
+ static::assertTrue(isset($zipFile[0]));
+ static::assertTrue(isset($zipFile['0']));
+ static::assertSame($zipFile['0'], '0');
+ static::assertCount(1, $zipFile);
$zipFile->close();
- $this->assertTrue(unlink($this->outputFilename));
+ static::assertTrue(unlink($this->outputFilename));
$zipFile = new ZipFile();
$zipFile->addFromString(0, 0);
- $this->assertTrue(isset($zipFile[0]));
- $this->assertTrue(isset($zipFile['0']));
- $this->assertCount(1, $zipFile);
+ static::assertTrue(isset($zipFile[0]));
+ static::assertTrue(isset($zipFile['0']));
+ static::assertCount(1, $zipFile);
$zipFile
->saveAsFile($this->outputFilename)
- ->close();
+ ->close()
+ ;
- $this->assertCorrectZipArchive($this->outputFilename);
+ static::assertCorrectZipArchive($this->outputFilename);
}
/**
@@ -1892,9 +1961,9 @@ class ZipFileTest extends ZipTestCase
}
$filename = 'file.jar';
$response = $zipFile->outputAsResponse(new Response(), $filename);
- $this->assertInstanceOf(ResponseInterface::class, $response);
- $this->assertEquals('application/java-archive', $response->getHeaderLine('content-type'));
- $this->assertEquals('attachment; filename="file.jar"', $response->getHeaderLine('content-disposition'));
+ static::assertInstanceOf(ResponseInterface::class, $response);
+ static::assertSame('application/java-archive', $response->getHeaderLine('content-type'));
+ static::assertSame('attachment; filename="file.jar"', $response->getHeaderLine('content-disposition'));
}
/**
@@ -1914,41 +1983,54 @@ class ZipFileTest extends ZipTestCase
->addFromString('file4', 'content', ZipFileInterface::METHOD_DEFLATED)
->setCompressionLevelEntry('file4', ZipFileInterface::LEVEL_DEFAULT_COMPRESSION)
->saveAsFile($this->outputFilename)
- ->close();
+ ->close()
+ ;
- $this->assertCorrectZipArchive($this->outputFilename);
+ static::assertCorrectZipArchive($this->outputFilename);
$zipFile->openFile($this->outputFilename);
- $this->assertEquals($zipFile->getEntryInfo('file')
- ->getCompressionLevel(), ZipFileInterface::LEVEL_BEST_COMPRESSION);
- $this->assertEquals($zipFile->getEntryInfo('file2')
- ->getCompressionLevel(), ZipFileInterface::LEVEL_FAST);
- $this->assertEquals($zipFile->getEntryInfo('file3')
- ->getCompressionLevel(), ZipFileInterface::LEVEL_SUPER_FAST);
- $this->assertEquals($zipFile->getEntryInfo('file4')
- ->getCompressionLevel(), ZipFileInterface::LEVEL_DEFAULT_COMPRESSION);
+ static::assertSame(
+ $zipFile->getEntryInfo('file')
+ ->getCompressionLevel(),
+ ZipFileInterface::LEVEL_BEST_COMPRESSION
+ );
+ static::assertSame(
+ $zipFile->getEntryInfo('file2')
+ ->getCompressionLevel(),
+ ZipFileInterface::LEVEL_FAST
+ );
+ static::assertSame(
+ $zipFile->getEntryInfo('file3')
+ ->getCompressionLevel(),
+ ZipFileInterface::LEVEL_SUPER_FAST
+ );
+ static::assertSame(
+ $zipFile->getEntryInfo('file4')
+ ->getCompressionLevel(),
+ ZipFileInterface::LEVEL_DEFAULT_COMPRESSION
+ );
$zipFile->close();
}
/**
- * @expectedException \PhpZip\Exception\InvalidArgumentException
- * @expectedExceptionMessage Invalid compression level
* @throws ZipException
*/
public function testInvalidCompressionLevel()
{
+ $this->setExpectedException(InvalidArgumentException::class, 'Invalid compression level');
+
$zipFile = new ZipFile();
$zipFile->addFromString('file', 'content');
$zipFile->setCompressionLevel(15);
}
/**
- * @expectedException \PhpZip\Exception\InvalidArgumentException
- * @expectedExceptionMessage Invalid compression level
* @throws ZipException
*/
public function testInvalidCompressionLevelEntry()
{
+ $this->setExpectedException(InvalidArgumentException::class, 'Invalid compression level');
+
$zipFile = new ZipFile();
$zipFile->addFromString('file', 'content');
$zipFile->setCompressionLevelEntry('file', 15);
@@ -1966,15 +2048,19 @@ class ZipFileTest extends ZipTestCase
$zipFile
->setCompressionLevel(ZipFileInterface::LEVEL_BEST_SPEED)
->saveAsFile($this->outputFilename)
- ->close();
+ ->close()
+ ;
- $this->assertCorrectZipArchive($this->outputFilename);
+ static::assertCorrectZipArchive($this->outputFilename);
$zipFile->openFile($this->outputFilename);
$infoList = $zipFile->getAllInfo();
- array_walk($infoList, function (ZipInfo $zipInfo) {
- $this->assertEquals($zipInfo->getCompressionLevel(), ZipFileInterface::LEVEL_BEST_SPEED);
- });
+ array_walk(
+ $infoList,
+ function (ZipInfo $zipInfo) {
+ $this->assertSame($zipInfo->getCompressionLevel(), ZipFileInterface::LEVEL_BEST_SPEED);
+ }
+ );
$zipFile->close();
}
@@ -1990,21 +2076,21 @@ class ZipFileTest extends ZipTestCase
$zipFile->close();
$zipFile->openFile($this->outputFilename);
- $this->assertEquals($zipFile->getEntryInfo('file')->getMethodName(), 'No compression');
+ static::assertSame($zipFile->getEntryInfo('file')->getMethodName(), 'No compression');
$zipFile->setCompressionMethodEntry('file', ZipFileInterface::METHOD_DEFLATED);
- $this->assertEquals($zipFile->getEntryInfo('file')->getMethodName(), 'Deflate');
+ static::assertSame($zipFile->getEntryInfo('file')->getMethodName(), 'Deflate');
$zipFile->rewrite();
- $this->assertEquals($zipFile->getEntryInfo('file')->getMethodName(), 'Deflate');
+ static::assertSame($zipFile->getEntryInfo('file')->getMethodName(), 'Deflate');
}
/**
- * @expectedException \PhpZip\Exception\ZipUnsupportMethodException
- * @expectedExceptionMessage Unsupported method
* @throws ZipException
*/
public function testInvalidCompressionMethodEntry()
{
+ $this->setExpectedException(ZipUnsupportMethodException::class, 'Unsupported method');
+
$zipFile = new ZipFile();
$zipFile->addFromString('file', 'content', ZipFileInterface::METHOD_STORED);
$zipFile->setCompressionMethodEntry('file', 99);
@@ -2020,29 +2106,29 @@ class ZipFileTest extends ZipTestCase
$zipFile[$i] = $i;
}
$zipFile->setArchiveComment('comment');
- $this->assertCount(10, $zipFile);
- $this->assertEquals($zipFile->getArchiveComment(), 'comment');
+ static::assertCount(10, $zipFile);
+ static::assertSame($zipFile->getArchiveComment(), 'comment');
$zipFile->saveAsFile($this->outputFilename);
$zipFile->unchangeAll();
- $this->assertCount(0, $zipFile);
- $this->assertEquals($zipFile->getArchiveComment(), null);
+ static::assertCount(0, $zipFile);
+ static::assertNull($zipFile->getArchiveComment());
$zipFile->close();
$zipFile->openFile($this->outputFilename);
- $this->assertCount(10, $zipFile);
- $this->assertEquals($zipFile->getArchiveComment(), 'comment');
+ static::assertCount(10, $zipFile);
+ static::assertSame($zipFile->getArchiveComment(), 'comment');
for ($i = 10; $i < 100; $i++) {
$zipFile[$i] = $i;
}
$zipFile->setArchiveComment('comment 2');
- $this->assertCount(100, $zipFile);
- $this->assertEquals($zipFile->getArchiveComment(), 'comment 2');
+ static::assertCount(100, $zipFile);
+ static::assertSame($zipFile->getArchiveComment(), 'comment 2');
$zipFile->unchangeAll();
- $this->assertCount(10, $zipFile);
- $this->assertEquals($zipFile->getArchiveComment(), 'comment');
+ static::assertCount(10, $zipFile);
+ static::assertSame($zipFile->getArchiveComment(), 'comment');
$zipFile->close();
}
@@ -2056,20 +2142,20 @@ class ZipFileTest extends ZipTestCase
$zipFile[$i] = $i;
}
$zipFile->setArchiveComment('comment');
- $this->assertEquals($zipFile->getArchiveComment(), 'comment');
+ static::assertSame($zipFile->getArchiveComment(), 'comment');
$zipFile->saveAsFile($this->outputFilename);
$zipFile->unchangeArchiveComment();
- $this->assertEquals($zipFile->getArchiveComment(), null);
+ static::assertNull($zipFile->getArchiveComment());
$zipFile->close();
$zipFile->openFile($this->outputFilename);
- $this->assertEquals($zipFile->getArchiveComment(), 'comment');
+ static::assertSame($zipFile->getArchiveComment(), 'comment');
$zipFile->setArchiveComment('comment 2');
- $this->assertEquals($zipFile->getArchiveComment(), 'comment 2');
+ static::assertSame($zipFile->getArchiveComment(), 'comment 2');
$zipFile->unchangeArchiveComment();
- $this->assertEquals($zipFile->getArchiveComment(), 'comment');
+ static::assertSame($zipFile->getArchiveComment(), 'comment');
$zipFile->close();
}
@@ -2084,55 +2170,27 @@ class ZipFileTest extends ZipTestCase
$zipFile['file 2'] = 'content 2';
$zipFile
->saveAsFile($this->outputFilename)
- ->close();
+ ->close()
+ ;
$zipFile->openFile($this->outputFilename);
$zipFile['file 1'] = 'modify content 1';
$zipFile->setPasswordEntry('file 1', 'password');
- $this->assertEquals($zipFile['file 1'], 'modify content 1');
- $this->assertTrue($zipFile->getEntryInfo('file 1')->isEncrypted());
+ static::assertSame($zipFile['file 1'], 'modify content 1');
+ static::assertTrue($zipFile->getEntryInfo('file 1')->isEncrypted());
- $this->assertEquals($zipFile['file 2'], 'content 2');
- $this->assertFalse($zipFile->getEntryInfo('file 2')->isEncrypted());
+ static::assertSame($zipFile['file 2'], 'content 2');
+ static::assertFalse($zipFile->getEntryInfo('file 2')->isEncrypted());
$zipFile->unchangeEntry('file 1');
- $this->assertEquals($zipFile['file 1'], 'content 1');
- $this->assertFalse($zipFile->getEntryInfo('file 1')->isEncrypted());
+ static::assertSame($zipFile['file 1'], 'content 1');
+ static::assertFalse($zipFile->getEntryInfo('file 1')->isEncrypted());
- $this->assertEquals($zipFile['file 2'], 'content 2');
- $this->assertFalse($zipFile->getEntryInfo('file 2')->isEncrypted());
- $zipFile->close();
- }
-
- /**
- * Test support ZIP64 ext (slow test - normal).
- * Create > 65535 files in archive and open and extract to /dev/null.
- * @throws ZipException
- */
- public function testCreateAndOpenZip64Ext()
- {
- $countFiles = 0xffff + 1;
-
- $zipFile = new ZipFile();
- for ($i = 0; $i < $countFiles; $i++) {
- $zipFile[$i . '.txt'] = $i;
- }
- $zipFile->saveAsFile($this->outputFilename);
- $zipFile->close();
-
- $this->assertCorrectZipArchive($this->outputFilename);
-
- $zipFile->openFile($this->outputFilename);
- $this->assertEquals($zipFile->count(), $countFiles);
- $i = 0;
- foreach ($zipFile as $entry => $content) {
- $this->assertEquals($entry, $i . '.txt');
- $this->assertEquals($content, $i);
- $i++;
- }
+ static::assertSame($zipFile['file 2'], 'content 2');
+ static::assertFalse($zipFile->getEntryInfo('file 2')->isEncrypted());
$zipFile->close();
}
}
diff --git a/tests/PhpZip/ZipMatcherTest.php b/tests/PhpZip/ZipMatcherTest.php
index 32da1b4..8d29d6b 100644
--- a/tests/PhpZip/ZipMatcherTest.php
+++ b/tests/PhpZip/ZipMatcherTest.php
@@ -2,11 +2,18 @@
namespace PhpZip;
+use PHPUnit\Framework\TestCase;
use PhpZip\Model\ZipEntryMatcher;
use PhpZip\Model\ZipInfo;
use PhpZip\Util\CryptoUtil;
-class ZipMatcherTest extends \PHPUnit_Framework_TestCase
+/**
+ * @internal
+ *
+ * @small
+ * @covers
+ */
+class ZipMatcherTest extends TestCase
{
public function testMatcher()
{
@@ -16,41 +23,45 @@ class ZipMatcherTest extends \PHPUnit_Framework_TestCase
}
$matcher = $zipFile->matcher();
- $this->assertInstanceOf(ZipEntryMatcher::class, $matcher);
+ static::assertInstanceOf(ZipEntryMatcher::class, $matcher);
- $this->assertTrue(is_array($matcher->getMatches()));
- $this->assertCount(0, $matcher);
+ static::assertInternalType('array', $matcher->getMatches());
+ static::assertCount(0, $matcher);
$matcher->add(1)->add(10)->add(20);
- $this->assertCount(3, $matcher);
- $this->assertEquals($matcher->getMatches(), ['1', '10', '20']);
+ static::assertCount(3, $matcher);
+ static::assertEquals($matcher->getMatches(), ['1', '10', '20']);
$matcher->delete();
- $this->assertCount(97, $zipFile);
- $this->assertCount(0, $matcher);
+ static::assertCount(97, $zipFile);
+ static::assertCount(0, $matcher);
$matcher->match('~^[2][1-5]|[3][6-9]|40$~s');
- $this->assertCount(10, $matcher);
+ static::assertCount(10, $matcher);
$actualMatches = [
'21', '22', '23', '24', '25',
- '36', '37', '38', '39',
- '40'
+ '36', '37', '38', '39', '40',
];
- $this->assertEquals($matcher->getMatches(), $actualMatches);
+ static::assertSame($matcher->getMatches(), $actualMatches);
$matcher->setPassword('qwerty');
$info = $zipFile->getAllInfo();
- array_walk($info, function (ZipInfo $zipInfo) use ($actualMatches) {
- $this->assertEquals($zipInfo->isEncrypted(), in_array($zipInfo->getName(), $actualMatches));
- });
+ array_walk(
+ $info,
+ function (ZipInfo $zipInfo) use ($actualMatches) {
+ $this->assertSame($zipInfo->isEncrypted(), \in_array($zipInfo->getName(), $actualMatches, true));
+ }
+ );
$matcher->all();
- $this->assertCount(count($zipFile), $matcher);
+ static::assertCount(\count($zipFile), $matcher);
$expectedNames = [];
- $matcher->invoke(function ($entryName) use (&$expectedNames) {
- $expectedNames[] = $entryName;
- });
- $this->assertEquals($expectedNames, $matcher->getMatches());
+ $matcher->invoke(
+ static function ($entryName) use (&$expectedNames) {
+ $expectedNames[] = $entryName;
+ }
+ );
+ static::assertSame($expectedNames, $matcher->getMatches());
$zipFile->close();
}
@@ -59,7 +70,7 @@ class ZipMatcherTest extends \PHPUnit_Framework_TestCase
{
$zipFile = new ZipFile();
for ($i = 0; $i < 100; $i++) {
- $zipFile['file_'.$i.'.jpg'] = CryptoUtil::randomBytes(100);
+ $zipFile['file_' . $i . '.jpg'] = CryptoUtil::randomBytes(100);
}
$renameEntriesArray = [
@@ -86,24 +97,26 @@ class ZipMatcherTest extends \PHPUnit_Framework_TestCase
];
foreach ($renameEntriesArray as $name) {
- $this->assertTrue(isset($zipFile[$name]));
+ static::assertTrue(isset($zipFile[$name]));
}
$matcher = $zipFile->matcher();
$matcher->match('~^file_(1|5)\d+~');
- $this->assertEquals($matcher->getMatches(), $renameEntriesArray);
+ static::assertSame($matcher->getMatches(), $renameEntriesArray);
- $matcher->invoke(function ($entryName) use ($zipFile) {
- $newName = preg_replace('~\.(jpe?g)$~i', '.no_optimize.$1', $entryName);
- $zipFile->rename($entryName, $newName);
- });
+ $matcher->invoke(
+ static function ($entryName) use ($zipFile) {
+ $newName = preg_replace('~\.(jpe?g)$~i', '.no_optimize.$1', $entryName);
+ $zipFile->rename($entryName, $newName);
+ }
+ );
foreach ($renameEntriesArray as $name) {
- $this->assertFalse(isset($zipFile[$name]));
+ static::assertFalse(isset($zipFile[$name]));
$pathInfo = pathinfo($name);
- $newName = $pathInfo['filename'].'.no_optimize.'.$pathInfo['extension'];
- $this->assertTrue(isset($zipFile[$newName]));
+ $newName = $pathInfo['filename'] . '.no_optimize.' . $pathInfo['extension'];
+ static::assertTrue(isset($zipFile[$newName]));
}
$zipFile->close();
diff --git a/tests/PhpZip/ZipPasswordTest.php b/tests/PhpZip/ZipPasswordTest.php
index a887126..994439e 100644
--- a/tests/PhpZip/ZipPasswordTest.php
+++ b/tests/PhpZip/ZipPasswordTest.php
@@ -10,21 +10,27 @@ use PhpZip\Util\CryptoUtil;
/**
* Tests with zip password.
+ *
+ * @internal
+ *
+ * @small
+ * @covers
*/
class ZipPasswordTest extends ZipFileAddDirTest
{
/**
* Test archive password.
+ *
* @throws ZipException
*/
public function testSetPassword()
{
- if (PHP_INT_SIZE === 4) {
- $this->markTestSkipped('Skip test for 32-bit system. Not support Traditional PKWARE Encryption.');
+ if (\PHP_INT_SIZE === 4) {
+ static::markTestSkipped('Skip test for 32-bit system. Not support Traditional PKWARE Encryption.');
}
$password = base64_encode(CryptoUtil::randomBytes(100));
- $badPassword = "bad password";
+ $badPassword = 'bad password';
// create encryption password with ZipCrypto
$zipFile = new ZipFile();
@@ -33,28 +39,30 @@ class ZipPasswordTest extends ZipFileAddDirTest
$zipFile->saveAsFile($this->outputFilename);
$zipFile->close();
- $this->assertCorrectZipArchive($this->outputFilename, $password);
+ static::assertCorrectZipArchive($this->outputFilename, $password);
// check bad password for ZipCrypto
$zipFile->openFile($this->outputFilename);
$zipFile->setReadPassword($badPassword);
+
foreach ($zipFile->getListFiles() as $entryName) {
try {
$zipFile[$entryName];
- $this->fail("Expected Exception has not been raised.");
+ static::fail('Expected Exception has not been raised.');
} catch (ZipAuthenticationException $ae) {
- $this->assertContains('Invalid password for zip entry', $ae->getMessage());
+ static::assertContains('Invalid password for zip entry', $ae->getMessage());
}
}
// check correct password for ZipCrypto
$zipFile->setReadPassword($password);
+
foreach ($zipFile->getAllInfo() as $info) {
- $this->assertTrue($info->isEncrypted());
- $this->assertContains('ZipCrypto', $info->getMethodName());
+ static::assertTrue($info->isEncrypted());
+ static::assertContains('ZipCrypto', $info->getMethodName());
$decryptContent = $zipFile[$info->getName()];
- $this->assertNotEmpty($decryptContent);
- $this->assertContains('saveAsFile($this->outputFilename);
$zipFile->close();
- $this->assertCorrectZipArchive($this->outputFilename, $password);
+ static::assertCorrectZipArchive($this->outputFilename, $password);
// check from WinZip AES encryption
$zipFile->openFile($this->outputFilename);
// set bad password WinZip AES
$zipFile->setReadPassword($badPassword);
+
foreach ($zipFile->getListFiles() as $entryName) {
try {
$zipFile[$entryName];
- $this->fail("Expected Exception has not been raised.");
+ static::fail('Expected Exception has not been raised.');
} catch (ZipAuthenticationException $ae) {
- $this->assertNotNull($ae);
+ static::assertNotNull($ae);
}
}
// set correct password WinZip AES
$zipFile->setReadPassword($password);
+
foreach ($zipFile->getAllInfo() as $info) {
- $this->assertTrue($info->isEncrypted());
- $this->assertContains('WinZip', $info->getMethodName());
+ static::assertTrue($info->isEncrypted());
+ static::assertContains('WinZip', $info->getMethodName());
$decryptContent = $zipFile[$info->getName()];
- $this->assertNotEmpty($decryptContent);
- $this->assertContains('saveAsFile($this->outputFilename);
$zipFile->close();
- $this->assertCorrectZipArchive($this->outputFilename);
+ static::assertCorrectZipArchive($this->outputFilename);
// check remove password
$zipFile->openFile($this->outputFilename);
+
foreach ($zipFile->getAllInfo() as $info) {
- $this->assertFalse($info->isEncrypted());
+ static::assertFalse($info->isEncrypted());
}
$zipFile->close();
}
@@ -109,8 +120,8 @@ class ZipPasswordTest extends ZipFileAddDirTest
*/
public function testTraditionalEncryption()
{
- if (PHP_INT_SIZE === 4) {
- $this->markTestSkipped('Skip test for 32-bit system. Not support Traditional PKWARE Encryption.');
+ if (\PHP_INT_SIZE === 4) {
+ static::markTestSkipped('Skip test for 32-bit system. Not support Traditional PKWARE Encryption.');
}
$password = base64_encode(CryptoUtil::randomBytes(50));
@@ -121,15 +132,16 @@ class ZipPasswordTest extends ZipFileAddDirTest
$zip->saveAsFile($this->outputFilename);
$zip->close();
- $this->assertCorrectZipArchive($this->outputFilename, $password);
+ static::assertCorrectZipArchive($this->outputFilename, $password);
$zip->openFile($this->outputFilename);
$zip->setReadPassword($password);
- $this->assertFilesResult($zip, array_keys(self::$files));
+ static::assertFilesResult($zip, array_keys(self::$files));
+
foreach ($zip->getAllInfo() as $info) {
if (!$info->isFolder()) {
- $this->assertTrue($info->isEncrypted());
- $this->assertContains('ZipCrypto', $info->getMethodName());
+ static::assertTrue($info->isEncrypted());
+ static::assertContains('ZipCrypto', $info->getMethodName());
}
}
$zip->close();
@@ -137,8 +149,10 @@ class ZipPasswordTest extends ZipFileAddDirTest
/**
* @dataProvider winZipKeyStrengthProvider
+ *
* @param int $encryptionMethod
* @param int $bitSize
+ *
* @throws ZipException
*/
public function testWinZipAesEncryption($encryptionMethod, $bitSize)
@@ -151,16 +165,17 @@ class ZipPasswordTest extends ZipFileAddDirTest
$zip->saveAsFile($this->outputFilename);
$zip->close();
- $this->assertCorrectZipArchive($this->outputFilename, $password);
+ static::assertCorrectZipArchive($this->outputFilename, $password);
$zip->openFile($this->outputFilename);
$zip->setReadPassword($password);
- $this->assertFilesResult($zip, array_keys(self::$files));
+ static::assertFilesResult($zip, array_keys(self::$files));
+
foreach ($zip->getAllInfo() as $info) {
if (!$info->isFolder()) {
- $this->assertTrue($info->isEncrypted());
- $this->assertEquals($info->getEncryptionMethod(), $encryptionMethod);
- $this->assertContains('WinZip AES-' . $bitSize, $info->getMethodName());
+ static::assertTrue($info->isEncrypted());
+ static::assertSame($info->getEncryptionMethod(), $encryptionMethod);
+ static::assertContains('WinZip AES-' . $bitSize, $info->getMethodName());
}
}
$zip->close();
@@ -185,8 +200,8 @@ class ZipPasswordTest extends ZipFileAddDirTest
*/
public function testEncryptionEntries()
{
- if (PHP_INT_SIZE === 4) {
- $this->markTestSkipped('Skip test for 32-bit system. Not support Traditional PKWARE Encryption.');
+ if (\PHP_INT_SIZE === 4) {
+ static::markTestSkipped('Skip test for 32-bit system. Not support Traditional PKWARE Encryption.');
}
$password1 = '353442434235424234';
@@ -202,23 +217,26 @@ class ZipPasswordTest extends ZipFileAddDirTest
$zip->openFile($this->outputFilename);
$zip->setReadPasswordEntry('.hidden', $password1);
$zip->setReadPasswordEntry('text file.txt', $password2);
- $this->assertFilesResult($zip, [
- '.hidden',
- 'text file.txt',
- 'Текстовый документ.txt',
- 'empty dir/',
- ]);
+ static::assertFilesResult(
+ $zip,
+ [
+ '.hidden',
+ 'text file.txt',
+ 'Текстовый документ.txt',
+ 'empty dir/',
+ ]
+ );
$info = $zip->getEntryInfo('.hidden');
- $this->assertTrue($info->isEncrypted());
- $this->assertContains('ZipCrypto', $info->getMethodName());
+ static::assertTrue($info->isEncrypted());
+ static::assertContains('ZipCrypto', $info->getMethodName());
$info = $zip->getEntryInfo('text file.txt');
- $this->assertTrue($info->isEncrypted());
- $this->assertContains('WinZip AES', $info->getMethodName());
+ static::assertTrue($info->isEncrypted());
+ static::assertContains('WinZip AES', $info->getMethodName());
- $this->assertFalse($zip->getEntryInfo('Текстовый документ.txt')->isEncrypted());
- $this->assertFalse($zip->getEntryInfo('empty dir/')->isEncrypted());
+ static::assertFalse($zip->getEntryInfo('Текстовый документ.txt')->isEncrypted());
+ static::assertFalse($zip->getEntryInfo('empty dir/')->isEncrypted());
$zip->close();
}
@@ -229,8 +247,8 @@ class ZipPasswordTest extends ZipFileAddDirTest
*/
public function testEncryptionEntriesWithDefaultPassword()
{
- if (PHP_INT_SIZE === 4) {
- $this->markTestSkipped('Skip test for 32-bit system. Not support Traditional PKWARE Encryption.');
+ if (\PHP_INT_SIZE === 4) {
+ static::markTestSkipped('Skip test for 32-bit system. Not support Traditional PKWARE Encryption.');
}
$password1 = '353442434235424234';
@@ -249,36 +267,40 @@ class ZipPasswordTest extends ZipFileAddDirTest
$zip->setReadPassword($defaultPassword);
$zip->setReadPasswordEntry('.hidden', $password1);
$zip->setReadPasswordEntry('text file.txt', $password2);
- $this->assertFilesResult($zip, [
- '.hidden',
- 'text file.txt',
- 'Текстовый документ.txt',
- 'empty dir/',
- ]);
+ static::assertFilesResult(
+ $zip,
+ [
+ '.hidden',
+ 'text file.txt',
+ 'Текстовый документ.txt',
+ 'empty dir/',
+ ]
+ );
$info = $zip->getEntryInfo('.hidden');
- $this->assertTrue($info->isEncrypted());
- $this->assertContains('ZipCrypto', $info->getMethodName());
+ static::assertTrue($info->isEncrypted());
+ static::assertContains('ZipCrypto', $info->getMethodName());
$info = $zip->getEntryInfo('text file.txt');
- $this->assertTrue($info->isEncrypted());
- $this->assertContains('WinZip AES', $info->getMethodName());
+ static::assertTrue($info->isEncrypted());
+ static::assertContains('WinZip AES', $info->getMethodName());
$info = $zip->getEntryInfo('Текстовый документ.txt');
- $this->assertTrue($info->isEncrypted());
- $this->assertContains('WinZip AES', $info->getMethodName());
+ static::assertTrue($info->isEncrypted());
+ static::assertContains('WinZip AES', $info->getMethodName());
- $this->assertFalse($zip->getEntryInfo('empty dir/')->isEncrypted());
+ static::assertFalse($zip->getEntryInfo('empty dir/')->isEncrypted());
$zip->close();
}
/**
- * @expectedException \PhpZip\Exception\ZipException
- * @expectedExceptionMessage Invalid encryption method
+ * @throws ZipException
*/
public function testSetEncryptionMethodInvalid()
{
+ $this->setExpectedException(ZipException::class, 'Invalid encryption method');
+
$zipFile = new ZipFile();
$encryptionMethod = 9999;
$zipFile->setPassword('pass', $encryptionMethod);
@@ -295,33 +317,38 @@ class ZipPasswordTest extends ZipFileAddDirTest
$zipFile = new ZipFile();
$zipFile->setPassword('pass');
$zipFile['file'] = 'content';
- $this->assertFalse($zipFile->getEntryInfo('file')->isEncrypted());
+ static::assertFalse($zipFile->getEntryInfo('file')->isEncrypted());
for ($i = 1; $i <= 10; $i++) {
$zipFile['file' . $i] = 'content';
+
if ($i < 6) {
$zipFile->setPasswordEntry('file' . $i, 'pass');
- $this->assertTrue($zipFile->getEntryInfo('file' . $i)->isEncrypted());
+ static::assertTrue($zipFile->getEntryInfo('file' . $i)->isEncrypted());
} else {
- $this->assertFalse($zipFile->getEntryInfo('file' . $i)->isEncrypted());
+ static::assertFalse($zipFile->getEntryInfo('file' . $i)->isEncrypted());
}
}
$zipFile->disableEncryptionEntry('file3');
- $this->assertFalse($zipFile->getEntryInfo('file3')->isEncrypted());
- $this->asserttrue($zipFile->getEntryInfo('file2')->isEncrypted());
+ static::assertFalse($zipFile->getEntryInfo('file3')->isEncrypted());
+ static::assertTrue($zipFile->getEntryInfo('file2')->isEncrypted());
$zipFile->disableEncryption();
$infoList = $zipFile->getAllInfo();
- array_walk($infoList, function (ZipInfo $zipInfo) {
- $this->assertFalse($zipInfo->isEncrypted());
- });
+ array_walk(
+ $infoList,
+ function (ZipInfo $zipInfo) {
+ $this->assertFalse($zipInfo->isEncrypted());
+ }
+ );
$zipFile->close();
}
/**
- * @expectedException \PhpZip\Exception\ZipException
- * @expectedExceptionMessage Invalid encryption method
+ * @throws ZipException
*/
public function testInvalidEncryptionMethodEntry()
{
+ $this->setExpectedException(ZipException::class, 'Invalid encryption method');
+
$zipFile = new ZipFile();
$zipFile->addFromString('file', 'content', ZipFileInterface::METHOD_STORED);
$zipFile->setPasswordEntry('file', 'pass', 99);
@@ -341,42 +368,44 @@ class ZipPasswordTest extends ZipFileAddDirTest
$zipFile->saveAsFile($this->outputFilename);
$zipFile->close();
- $this->assertCorrectZipArchive($this->outputFilename, 'password');
+ static::assertCorrectZipArchive($this->outputFilename, 'password');
$zipFile->openFile($this->outputFilename);
- $this->assertCount(3, $zipFile);
+ static::assertCount(3, $zipFile);
+
foreach ($zipFile->getAllInfo() as $info) {
- $this->assertTrue($info->isEncrypted());
+ static::assertTrue($info->isEncrypted());
}
unset($zipFile['file3']);
$zipFile['file4'] = 'content';
$zipFile->rewrite();
- $this->assertCorrectZipArchive($this->outputFilename, 'password');
+ static::assertCorrectZipArchive($this->outputFilename, 'password');
- $this->assertCount(3, $zipFile);
- $this->assertFalse(isset($zipFile['file3']));
- $this->assertTrue(isset($zipFile['file4']));
- $this->assertTrue($zipFile->getEntryInfo('file1')->isEncrypted());
- $this->assertTrue($zipFile->getEntryInfo('file2')->isEncrypted());
- $this->assertFalse($zipFile->getEntryInfo('file4')->isEncrypted());
- $this->assertEquals($zipFile['file4'], 'content');
+ static::assertCount(3, $zipFile);
+ static::assertFalse(isset($zipFile['file3']));
+ static::assertTrue(isset($zipFile['file4']));
+ static::assertTrue($zipFile->getEntryInfo('file1')->isEncrypted());
+ static::assertTrue($zipFile->getEntryInfo('file2')->isEncrypted());
+ static::assertFalse($zipFile->getEntryInfo('file4')->isEncrypted());
+ static::assertSame($zipFile['file4'], 'content');
$zipFile->extractTo($this->outputDirname, ['file4']);
- $this->assertTrue(file_exists($this->outputDirname . DIRECTORY_SEPARATOR . 'file4'));
- $this->assertEquals(file_get_contents($this->outputDirname . DIRECTORY_SEPARATOR . 'file4'), $zipFile['file4']);
+ static::assertFileExists($this->outputDirname . \DIRECTORY_SEPARATOR . 'file4');
+ static::assertStringEqualsFile($this->outputDirname . \DIRECTORY_SEPARATOR . 'file4', $zipFile['file4']);
$zipFile->close();
}
/**
* @see https://github.com/Ne-Lexa/php-zip/issues/9
+ *
* @throws ZipException
*/
public function testIssues9()
{
- $contents = str_pad('', 1000, 'test;test2;test3' . PHP_EOL, STR_PAD_RIGHT);
+ $contents = str_pad('', 1000, 'test;test2;test3' . \PHP_EOL, \STR_PAD_RIGHT);
$password = base64_encode(CryptoUtil::randomBytes(20));
$encryptMethod = ZipFile::ENCRYPTION_METHOD_WINZIP_AES_256;
@@ -385,13 +414,14 @@ class ZipPasswordTest extends ZipFileAddDirTest
->addFromString('codes.csv', $contents)
->setPassword($password, $encryptMethod)
->saveAsFile($this->outputFilename)
- ->close();
+ ->close()
+ ;
- $this->assertCorrectZipArchive($this->outputFilename, $password);
+ static::assertCorrectZipArchive($this->outputFilename, $password);
$zipFile->openFile($this->outputFilename);
$zipFile->setReadPassword($password);
- $this->assertEquals($zipFile['codes.csv'], $contents);
+ static::assertSame($zipFile['codes.csv'], $contents);
$zipFile->close();
}
@@ -413,12 +443,13 @@ class ZipPasswordTest extends ZipFileAddDirTest
$zipFile2 = new ZipFile();
$zipFile2->openFile($this->outputFilename);
$zipFile2->setReadPassword($password);
- $this->assertEquals($zipFile2->getListFiles(), $zipFile->getListFiles());
+ static::assertSame($zipFile2->getListFiles(), $zipFile->getListFiles());
+
foreach ($zipFile as $name => $contents) {
- $this->assertNotEmpty($name);
- $this->assertNotEmpty($contents);
- $this->assertContains('test contents', $contents);
- $this->assertEquals($zipFile2[$name], $contents);
+ static::assertNotEmpty($name);
+ static::assertNotEmpty($contents);
+ static::assertContains('test contents', $contents);
+ static::assertSame($zipFile2[$name], $contents);
}
$zipFile2->close();
diff --git a/tests/PhpZip/ZipRemoteFileTest.php b/tests/PhpZip/ZipRemoteFileTest.php
index dbd5a59..e5a6d12 100644
--- a/tests/PhpZip/ZipRemoteFileTest.php
+++ b/tests/PhpZip/ZipRemoteFileTest.php
@@ -3,20 +3,17 @@
namespace PhpZip;
use PhpZip\Exception\ZipException;
-use PhpZip\Util\Iterator\IgnoreFilesFilterIterator;
-use PhpZip\Util\Iterator\IgnoreFilesRecursiveFilterIterator;
/**
- * Test add remote files to zip archive
+ * Test add remote files to zip archive.
+ *
+ * @internal
+ *
+ * @small
+ * @covers
*/
class ZipRemoteFileTest extends ZipTestCase
{
-
- protected function setUp()
- {
- parent::setUp();
- }
-
/**
* @throws ZipException
*/
@@ -25,16 +22,28 @@ class ZipRemoteFileTest extends ZipTestCase
$zipFile = new ZipFile();
$outputZip = $this->outputFilename;
$fileUrl = 'https://raw.githubusercontent.com/Ne-Lexa/php-zip/master/README.md';
- $fp = @fopen($fileUrl, 'rb', false, stream_context_create([
- 'http' => [
- 'timeout' => 3,
- ]
- ]));
+ /** @noinspection PhpUsageOfSilenceOperatorInspection */
+ $fp = @fopen(
+ $fileUrl,
+ 'rb',
+ false,
+ stream_context_create(
+ [
+ 'http' => [
+ 'timeout' => 3,
+ ],
+ ]
+ )
+ );
+
if ($fp === false) {
- self::markTestSkipped(sprintf(
- "Could not fetch remote file: %s",
- $fileUrl
- ));
+ static::markTestSkipped(
+ sprintf(
+ 'Could not fetch remote file: %s',
+ $fileUrl
+ )
+ );
+
return;
}
@@ -47,9 +56,8 @@ class ZipRemoteFileTest extends ZipTestCase
$zipFile = new ZipFile();
$zipFile->openFile($outputZip);
$files = $zipFile->getListFiles();
- self::assertCount(1, $files);
- self::assertSame($fileName, $files[0]);
+ static::assertCount(1, $files);
+ static::assertSame($fileName, $files[0]);
$zipFile->close();
}
-
}
diff --git a/tests/PhpZip/ZipSlipVulnerabilityTest.php b/tests/PhpZip/ZipSlipVulnerabilityTest.php
index 825dc5c..ce2882f 100644
--- a/tests/PhpZip/ZipSlipVulnerabilityTest.php
+++ b/tests/PhpZip/ZipSlipVulnerabilityTest.php
@@ -3,11 +3,15 @@
namespace PhpZip;
/**
- * Class ZipSlipVulnerabilityTest
+ * Class ZipSlipVulnerabilityTest.
*
- * @package PhpZip
* @see https://github.com/Ne-Lexa/php-zip/issues/39 Issue#31
* @see https://snyk.io/research/zip-slip-vulnerability Zip Slip Vulnerability
+ *
+ * @internal
+ *
+ * @small
+ * @covers
*/
class ZipSlipVulnerabilityTest extends ZipTestCase
{
@@ -19,7 +23,7 @@ class ZipSlipVulnerabilityTest extends ZipTestCase
$localFile = '../dir/./../../file.txt';
$zipFile = new ZipFile();
$zipFile->addFromString($localFile, 'contents');
- self::assertContains($localFile, $zipFile->getListFiles());
+ static::assertContains($localFile, $zipFile->getListFiles());
$zipFile->close();
}
@@ -28,7 +32,7 @@ class ZipSlipVulnerabilityTest extends ZipTestCase
*/
public function testUnpack()
{
- $this->assertTrue(mkdir($this->outputDirname, 0755, true));
+ static::assertTrue(mkdir($this->outputDirname, 0755, true));
$zipFile = new ZipFile();
$zipFile->addFromString('../dir/./../../file.txt', 'contents');
@@ -36,6 +40,6 @@ class ZipSlipVulnerabilityTest extends ZipTestCase
$zipFile->close();
$expectedExtractedFile = $this->outputDirname . '/dir/file.txt';
- self::assertTrue(is_file($expectedExtractedFile));
+ static::assertTrue(is_file($expectedExtractedFile));
}
}
diff --git a/tests/PhpZip/ZipTestCase.php b/tests/PhpZip/ZipTestCase.php
index 91fd205..5dfd400 100644
--- a/tests/PhpZip/ZipTestCase.php
+++ b/tests/PhpZip/ZipTestCase.php
@@ -2,32 +2,29 @@
namespace PhpZip;
+use PHPUnit\Framework\TestCase;
use PhpZip\Model\EndOfCentralDirectory;
use PhpZip\Util\FilesUtil;
/**
* PHPUnit test case and helper methods.
*/
-class ZipTestCase extends \PHPUnit_Framework_TestCase
+abstract class ZipTestCase extends TestCase
{
- /**
- * @var string
- */
+ /** @var string */
protected $outputFilename;
- /**
- * @var string
- */
+
+ /** @var string */
protected $outputDirname;
/**
- * Before test
+ * Before test.
*/
protected function setUp()
{
- parent::setUp();
-
$id = uniqid('phpzip', true);
$tempDir = sys_get_temp_dir() . '/phpunit-phpzip';
+
if (!is_dir($tempDir) && !mkdir($tempDir, 0755, true) && !is_dir($tempDir)) {
throw new \RuntimeException('Dir ' . $tempDir . " can't created");
}
@@ -36,7 +33,7 @@ class ZipTestCase extends \PHPUnit_Framework_TestCase
}
/**
- * After test
+ * After test.
*/
protected function tearDown()
{
@@ -45,6 +42,7 @@ class ZipTestCase extends \PHPUnit_Framework_TestCase
if ($this->outputFilename !== null && file_exists($this->outputFilename)) {
unlink($this->outputFilename);
}
+
if ($this->outputDirname !== null && is_dir($this->outputDirname)) {
FilesUtil::removeDir($this->outputDirname);
}
@@ -53,25 +51,29 @@ class ZipTestCase extends \PHPUnit_Framework_TestCase
/**
* Assert correct zip archive.
*
- * @param string $filename
+ * @param string $filename
* @param string|null $password
*/
public static function assertCorrectZipArchive($filename, $password = null)
{
if (self::existsProgram('unzip')) {
$command = 'unzip';
+
if ($password !== null) {
$command .= ' -P ' . escapeshellarg($password);
}
$command .= ' -t ' . escapeshellarg($filename);
exec($command, $output, $returnCode);
- $output = implode(PHP_EOL, $output);
+ $output = implode(\PHP_EOL, $output);
if ($password !== null && $returnCode === 81) {
if (self::existsProgram('7z')) {
- // WinZip 99-character limit
- // @see https://sourceforge.net/p/p7zip/discussion/383044/thread/c859a2f0/
+ /**
+ * WinZip 99-character limit.
+ *
+ * @see https://sourceforge.net/p/p7zip/discussion/383044/thread/c859a2f0/
+ */
$password = substr($password, 0, 99);
$command = '7z t -p' . escapeshellarg($password) . ' ' . escapeshellarg($filename);
@@ -79,31 +81,34 @@ class ZipTestCase extends \PHPUnit_Framework_TestCase
/**
* @var array $output
*/
- $output = implode(PHP_EOL, $output);
+ $output = implode(\PHP_EOL, $output);
- self::assertEquals($returnCode, 0);
- self::assertNotContains(' Errors', $output);
- self::assertContains(' Ok', $output);
+ static::assertSame($returnCode, 0);
+ static::assertNotContains(' Errors', $output);
+ static::assertContains(' Ok', $output);
} else {
- fwrite(STDERR, 'Program unzip cannot support this function.' . PHP_EOL);
- fwrite(STDERR, 'Please install 7z. For Ubuntu-like: sudo apt-get install p7zip-full' . PHP_EOL);
+ fwrite(\STDERR, 'Program unzip cannot support this function.' . \PHP_EOL);
+ fwrite(\STDERR, 'Please install 7z. For Ubuntu-like: sudo apt-get install p7zip-full' . \PHP_EOL);
}
} else {
- self::assertEquals($returnCode, 0, $output);
- self::assertNotContains('incorrect password', $output);
- self::assertContains(' OK', $output);
- self::assertContains('No errors', $output);
+ static::assertSame($returnCode, 0, $output);
+ static::assertNotContains('incorrect password', $output);
+ static::assertContains(' OK', $output);
+ static::assertContains('No errors', $output);
}
}
}
/**
* @param string $program
+ *
* @return bool
*/
- private static function existsProgram($program){
- if (DIRECTORY_SEPARATOR !== '\\') {
+ private static function existsProgram($program)
+ {
+ if (\DIRECTORY_SEPARATOR !== '\\') {
exec('which ' . escapeshellarg($program), $output, $returnCode);
+
return $returnCode === 0;
}
// false for Windows
@@ -120,30 +125,34 @@ class ZipTestCase extends \PHPUnit_Framework_TestCase
if (self::existsProgram('zipinfo')) {
exec('zipinfo ' . escapeshellarg($filename), $output, $returnCode);
- $output = implode(PHP_EOL, $output);
+ $output = implode(\PHP_EOL, $output);
- self::assertContains('Empty zipfile', $output);
+ static::assertContains('Empty zipfile', $output);
}
$actualEmptyZipData = pack('VVVVVv', EndOfCentralDirectory::END_OF_CENTRAL_DIRECTORY_RECORD_SIG, 0, 0, 0, 0, 0);
- self::assertStringEqualsFile($filename, $actualEmptyZipData);
+ static::assertStringEqualsFile($filename, $actualEmptyZipData);
}
/**
* @param string $filename
- * @param bool $showErrors
- * @return bool|null If null - can not install zipalign
+ * @param bool $showErrors
+ *
+ * @return bool|null If null returned, then the zipalign program is not installed
*/
public static function assertVerifyZipAlign($filename, $showErrors = false)
{
if (self::existsProgram('zipalign')) {
exec('zipalign -c -v 4 ' . escapeshellarg($filename), $output, $returnCode);
+
if ($showErrors && $returnCode !== 0) {
- fwrite(STDERR, implode(PHP_EOL, $output));
+ fwrite(\STDERR, implode(\PHP_EOL, $output));
}
+
return $returnCode === 0;
}
- fwrite(STDERR, 'Can not find program "zipalign" for test' . PHP_EOL);
+ fwrite(\STDERR, "Cannot find the program 'zipalign' for the test" . \PHP_EOL);
+
return null;
}
}
From c0786f59471f6966800d2d7e6eb048a74b7671da Mon Sep 17 00:00:00 2001
From: wapplay
Date: Thu, 5 Dec 2019 23:52:17 +0300
Subject: [PATCH 2/8] set travis dist
---
.travis.yml | 2 ++
1 file changed, 2 insertions(+)
diff --git a/.travis.yml b/.travis.yml
index d8693db..07dc34d 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,3 +1,5 @@
+dist: trusty
+
language: php
php:
- '5.5'
From e03c963dc192b35cf142085b904cad1f84bd2007 Mon Sep 17 00:00:00 2001
From: wapplay
Date: Fri, 6 Dec 2019 08:32:33 +0300
Subject: [PATCH 3/8] refactoring
---
.php_cs | 2 +-
.../Exception/ZipUnsupportMethodException.php | 3 ++
src/PhpZip/Model/EndOfCentralDirectory.php | 2 +-
src/PhpZip/Stream/ZipInputStream.php | 1 +
src/PhpZip/ZipFile.php | 2 +
.../PhpZip/Internal/DummyFileSystemStream.php | 37 +++++++++++++------
tests/PhpZip/PhpZipExtResourceTest.php | 4 +-
7 files changed, 36 insertions(+), 15 deletions(-)
diff --git a/.php_cs b/.php_cs
index 976ecbf..520825d 100644
--- a/.php_cs
+++ b/.php_cs
@@ -899,7 +899,7 @@ $rules = [
* Risky when PHPUnit classes are overridden or not accessible, or
* when project has PHPUnit incompatibilities.
*/
- 'php_unit_expectation' => true,
+ 'php_unit_expectation' => false,
// PHPUnit annotations should be a FQCNs including a root namespace.
'php_unit_fqcn_annotation' => true,
diff --git a/src/PhpZip/Exception/ZipUnsupportMethodException.php b/src/PhpZip/Exception/ZipUnsupportMethodException.php
index dd66cce..2f03167 100644
--- a/src/PhpZip/Exception/ZipUnsupportMethodException.php
+++ b/src/PhpZip/Exception/ZipUnsupportMethodException.php
@@ -2,6 +2,9 @@
namespace PhpZip\Exception;
+/**
+ * Class ZipUnsupportMethodException.
+ */
class ZipUnsupportMethodException extends RuntimeException
{
}
diff --git a/src/PhpZip/Model/EndOfCentralDirectory.php b/src/PhpZip/Model/EndOfCentralDirectory.php
index f27d57f..93716bd 100644
--- a/src/PhpZip/Model/EndOfCentralDirectory.php
+++ b/src/PhpZip/Model/EndOfCentralDirectory.php
@@ -81,7 +81,7 @@ class EndOfCentralDirectory
private $entryCount;
/** @var bool */
- private $zip64 = false;
+ private $zip64;
/**
* EndOfCentralDirectory constructor.
diff --git a/src/PhpZip/Stream/ZipInputStream.php b/src/PhpZip/Stream/ZipInputStream.php
index b2e677f..bd0d777 100644
--- a/src/PhpZip/Stream/ZipInputStream.php
+++ b/src/PhpZip/Stream/ZipInputStream.php
@@ -507,6 +507,7 @@ class ZipInputStream implements ZipInputStreamInterface
break;
case ZipFileInterface::METHOD_DEFLATED:
+ /** @noinspection PhpUsageOfSilenceOperatorInspection */
$content = @gzinflate($content);
break;
diff --git a/src/PhpZip/ZipFile.php b/src/PhpZip/ZipFile.php
index aacf4e0..2a3aba4 100644
--- a/src/PhpZip/ZipFile.php
+++ b/src/PhpZip/ZipFile.php
@@ -1,5 +1,7 @@
stream_open($path, $mode, $options)" . PHP_EOL;
-
$parsedUrl = parse_url($path);
$path = $parsedUrl['path'];
$this->fp = fopen($path, $mode);
@@ -21,37 +27,46 @@ class DummyFileSystemStream
return true;
}
+ /**
+ * @param $count
+ *
+ * @return false|string
+ */
public function stream_read($count)
{
-// echo "DummyFileSystemStream->stream_read($count)" . PHP_EOL;
- $position = ftell($this->fp);
-
-// echo "Loading chunk " . $position . " to " . ($position + $count - 1) . PHP_EOL;
return fread($this->fp, $count);
-// echo "String length: " . strlen($ret) . PHP_EOL;
}
+ /**
+ * @return false|int
+ */
public function stream_tell()
{
-// echo "DummyFileSystemStream->stream_tell()" . PHP_EOL;
return ftell($this->fp);
}
+ /**
+ * @return bool
+ */
public function stream_eof()
{
-// echo "DummyFileSystemStream->stream_eof()" . PHP_EOL;
return feof($this->fp);
}
+ /**
+ * @param $offset
+ * @param $whence
+ */
public function stream_seek($offset, $whence)
{
-// echo "DummyFileSystemStream->stream_seek($offset, $whence)" . PHP_EOL;
fseek($this->fp, $offset, $whence);
}
+ /**
+ * @return array
+ */
public function stream_stat()
{
-// echo "DummyFileSystemStream->stream_stat()" . PHP_EOL;
return fstat($this->fp);
}
}
diff --git a/tests/PhpZip/PhpZipExtResourceTest.php b/tests/PhpZip/PhpZipExtResourceTest.php
index 98cb736..0ba2542 100644
--- a/tests/PhpZip/PhpZipExtResourceTest.php
+++ b/tests/PhpZip/PhpZipExtResourceTest.php
@@ -133,10 +133,10 @@ class PhpZipExtResourceTest extends ZipTestCase
static::assertTrue(mkdir($this->outputDirname, 0755, true));
$zipFile = new ZipFile();
+ $zipFile->openFile($filename);
+ $zipFile->setReadPassword('bar');
try {
- $zipFile->openFile($filename);
- $zipFile->setReadPassword('bar');
$zipFile->extractTo($this->outputDirname);
static::markTestIncomplete('failed test');
} catch (ZipException $exception) {
From e2c058840cbcd4744594d99eb2753b4a1a4fe538 Mon Sep 17 00:00:00 2001
From: Ne-Lexa
Date: Fri, 6 Dec 2019 12:09:37 +0300
Subject: [PATCH 4/8] fixed for php 32-bit
---
.php_cs | 2 +-
composer.json | 7 +-
.../TraditionalPkwareEncryptionEngine.php | 11 ++-
src/PhpZip/Crypto/WinZipAesEngine.php | 8 +-
src/PhpZip/Extra/Fields/Zip64ExtraField.php | 18 ++--
src/PhpZip/Model/Entry/ZipAbstractEntry.php | 84 ++++---------------
src/PhpZip/Model/ZipEntry.php | 21 ++---
src/PhpZip/Model/ZipInfo.php | 38 ++++-----
src/PhpZip/Stream/ZipInputStream.php | 17 ++--
src/PhpZip/Stream/ZipOutputStream.php | 15 +++-
tests/PhpZip/Issue24Test.php | 1 -
tests/PhpZip/PhpZipExtResourceTest.php | 11 ++-
tests/PhpZip/Zip64Test.php | 1 -
tests/PhpZip/ZipAlignTest.php | 1 -
tests/PhpZip/ZipEventTest.php | 1 -
tests/PhpZip/ZipFileAddDirTest.php | 1 -
tests/PhpZip/ZipFileTest.php | 13 ++-
tests/PhpZip/ZipMatcherTest.php | 1 -
tests/PhpZip/ZipPasswordTest.php | 18 ++--
tests/PhpZip/ZipRemoteFileTest.php | 1 -
tests/PhpZip/ZipSlipVulnerabilityTest.php | 1 -
21 files changed, 117 insertions(+), 154 deletions(-)
diff --git a/.php_cs b/.php_cs
index 520825d..001d019 100644
--- a/.php_cs
+++ b/.php_cs
@@ -1028,7 +1028,7 @@ $rules = [
* Adds a default `@coversNothing` annotation to PHPUnit test
* classes that have no `@covers*` annotation.
*/
- 'php_unit_test_class_requires_covers' => true,
+ 'php_unit_test_class_requires_covers' => false,
// PHPDoc should contain `@param` for all params.
'phpdoc_add_missing_param_annotation' => [
diff --git a/composer.json b/composer.json
index b3658ab..94cc8ce 100644
--- a/composer.json
+++ b/composer.json
@@ -25,8 +25,13 @@
"ext-zlib": "*",
"psr/http-message": "^1.0"
},
+ "config": {
+ "platform": {
+ "php": "5.5"
+ }
+ },
"require-dev": {
- "phpunit/phpunit": "~4.8|~5.7",
+ "phpunit/phpunit": "^4.8|^5.7",
"zendframework/zend-diactoros": "^1.4"
},
"autoload": {
diff --git a/src/PhpZip/Crypto/TraditionalPkwareEncryptionEngine.php b/src/PhpZip/Crypto/TraditionalPkwareEncryptionEngine.php
index ff6d357..a90dff5 100644
--- a/src/PhpZip/Crypto/TraditionalPkwareEncryptionEngine.php
+++ b/src/PhpZip/Crypto/TraditionalPkwareEncryptionEngine.php
@@ -2,6 +2,7 @@
namespace PhpZip\Crypto;
+use PhpZip\Exception\RuntimeException;
use PhpZip\Exception\ZipAuthenticationException;
use PhpZip\Exception\ZipCryptoException;
use PhpZip\Model\ZipEntry;
@@ -324,7 +325,7 @@ class TraditionalPkwareEncryptionEngine implements ZipEncryptionEngine
/**
* Update keys.
*
- * @param string $charAt
+ * @param int $charAt
*/
private function updateKeys($charAt)
{
@@ -356,6 +357,10 @@ class TraditionalPkwareEncryptionEngine implements ZipEncryptionEngine
*/
public function decrypt($content)
{
+ if (\PHP_INT_SIZE === 4) {
+ throw new RuntimeException('Traditional PKWARE Encryption is not supported in 32-bit PHP.');
+ }
+
$password = $this->entry->getPassword();
$this->initKeys($password);
@@ -418,6 +423,10 @@ class TraditionalPkwareEncryptionEngine implements ZipEncryptionEngine
*/
public function encrypt($data)
{
+ if (\PHP_INT_SIZE === 4) {
+ throw new RuntimeException('Traditional PKWARE Encryption is not supported in 32-bit PHP.');
+ }
+
$crc = $this->entry->isDataDescriptorRequired() ?
($this->entry->getDosTime() & 0x0000ffff) << 16 :
$this->entry->getCrc();
diff --git a/src/PhpZip/Crypto/WinZipAesEngine.php b/src/PhpZip/Crypto/WinZipAesEngine.php
index 6c4b4de..4e1056e 100644
--- a/src/PhpZip/Crypto/WinZipAesEngine.php
+++ b/src/PhpZip/Crypto/WinZipAesEngine.php
@@ -49,9 +49,9 @@ class WinZipAesEngine implements ZipEncryptionEngine
*
* @param string $content Input stream buffer
*
- * @throws ZipAuthenticationException
* @throws ZipCryptoException
* @throws ZipException
+ * @throws ZipAuthenticationException
*
* @return string
*/
@@ -100,8 +100,10 @@ class WinZipAesEngine implements ZipEncryptionEngine
}
$password = $this->entry->getPassword();
- \assert($password !== null);
- \assert($keyStrengthBits >= self::AES_BLOCK_SIZE_BITS);
+
+ if ($password === null) {
+ throw new ZipException(sprintf('Password not set for entry %s', $this->entry->getName()));
+ }
/**
* WinZip 99-character limit.
diff --git a/src/PhpZip/Extra/Fields/Zip64ExtraField.php b/src/PhpZip/Extra/Fields/Zip64ExtraField.php
index 982010d..7d424ac 100644
--- a/src/PhpZip/Extra/Fields/Zip64ExtraField.php
+++ b/src/PhpZip/Extra/Fields/Zip64ExtraField.php
@@ -102,27 +102,21 @@ class Zip64ExtraField implements ExtraField
throw new RuntimeException('entry is null');
}
$off = 0;
- // Read in Uncompressed Size.
- $size = $this->entry->getSize();
- if ($size >= 0xffffffff) {
- \assert($size === 0xffffffff);
+ // Read in Uncompressed Size.
+ if ($this->entry->getSize() === 0xffffffff) {
$this->entry->setSize(PackUtil::unpackLongLE(substr($data, $off, 8)));
$off += 8;
}
- // Read in Compressed Size.
- $compressedSize = $this->entry->getCompressedSize();
- if ($compressedSize >= 0xffffffff) {
- \assert($compressedSize === 0xffffffff);
+ // Read in Compressed Size.
+ if ($this->entry->getCompressedSize() === 0xffffffff) {
$this->entry->setCompressedSize(PackUtil::unpackLongLE(substr($data, $off, 8)));
$off += 8;
}
- // Read in Relative Header Offset.
- $offset = $this->entry->getOffset();
- if ($offset >= 0xffffffff) {
- \assert(0xffffffff, $offset);
+ // Read in Relative Header Offset.
+ if ($this->entry->getOffset() === 0xffffffff) {
$this->entry->setOffset(PackUtil::unpackLongLE(substr($data, $off, 8)));
}
}
diff --git a/src/PhpZip/Model/Entry/ZipAbstractEntry.php b/src/PhpZip/Model/Entry/ZipAbstractEntry.php
index 2b4c14d..c5435c6 100644
--- a/src/PhpZip/Model/Entry/ZipAbstractEntry.php
+++ b/src/PhpZip/Model/Entry/ZipAbstractEntry.php
@@ -22,29 +22,26 @@ use PhpZip\ZipFileInterface;
*/
abstract class ZipAbstractEntry implements ZipEntry
{
- /** @var int bit flags for init state */
- private $init;
-
/** @var string Entry name (filename in archive) */
private $name;
/** @var int Made by platform */
- private $platform;
+ private $platform = self::UNKNOWN;
/** @var int */
private $versionNeededToExtract = 20;
/** @var int Compression method */
- private $method;
+ private $method = self::UNKNOWN;
/** @var int */
- private $general;
+ private $general = 0;
/** @var int Dos time */
- private $dosTime;
+ private $dosTime = self::UNKNOWN;
/** @var int Crc32 */
- private $crc;
+ private $crc = self::UNKNOWN;
/** @var int Compressed size */
private $compressedSize = self::UNKNOWN;
@@ -53,7 +50,7 @@ abstract class ZipAbstractEntry implements ZipEntry
private $size = self::UNKNOWN;
/** @var int External attributes */
- private $externalAttributes;
+ private $externalAttributes = 0;
/** @var int relative Offset Of Local File Header */
private $offset = self::UNKNOWN;
@@ -67,7 +64,7 @@ abstract class ZipAbstractEntry implements ZipEntry
*/
private $extraFieldsCollection;
- /** @var string comment field */
+ /** @var string|null comment field */
private $comment;
/** @var string entry password for read or write encryption data */
@@ -150,6 +147,7 @@ abstract class ZipAbstractEntry implements ZipEntry
}
$this->setGeneralPurposeBitFlag(self::GPBF_UTF8, true);
$this->name = $name;
+ $this->externalAttributes = $this->isDirectory() ? 0x10 : 0;
return $this;
}
@@ -174,11 +172,11 @@ abstract class ZipAbstractEntry implements ZipEntry
}
/**
- * @return int Get platform
+ * @return int platform
*/
public function getPlatform()
{
- return $this->isInit(self::BIT_PLATFORM) ? $this->platform & 0xffff : self::UNKNOWN;
+ return $this->platform;
}
/**
@@ -192,44 +190,18 @@ abstract class ZipAbstractEntry implements ZipEntry
*/
public function setPlatform($platform)
{
- $known = $platform !== self::UNKNOWN;
-
- if ($known) {
+ if ($platform !== self::UNKNOWN) {
if ($platform < 0x00 || $platform > 0xff) {
throw new ZipException('Platform out of range');
}
$this->platform = $platform;
} else {
- $this->platform = 0;
+ $this->platform = 0; // ms-dos
}
- $this->setInit(self::BIT_PLATFORM, $known);
return $this;
}
- /**
- * @param int $mask
- *
- * @return bool
- */
- protected function isInit($mask)
- {
- return ($this->init & $mask) !== 0;
- }
-
- /**
- * @param int $mask
- * @param bool $init
- */
- protected function setInit($mask, $init)
- {
- if ($init) {
- $this->init |= $mask;
- } else {
- $this->init &= ~$mask;
- }
- }
-
/**
* Version needed to extract.
*
@@ -450,11 +422,7 @@ abstract class ZipAbstractEntry implements ZipEntry
*/
public function getMethod()
{
- $isInit = $this->isInit(self::BIT_METHOD);
-
- return $isInit ?
- $this->method & 0xffff :
- self::UNKNOWN;
+ return $this->method;
}
/**
@@ -470,7 +438,6 @@ abstract class ZipAbstractEntry implements ZipEntry
{
if ($method === self::UNKNOWN) {
$this->method = $method;
- $this->setInit(self::BIT_METHOD, false);
return $this;
}
@@ -484,7 +451,6 @@ abstract class ZipAbstractEntry implements ZipEntry
case ZipFileInterface::METHOD_DEFLATED:
case ZipFileInterface::METHOD_BZIP2:
$this->method = $method;
- $this->setInit(self::BIT_METHOD, true);
break;
default:
@@ -501,7 +467,7 @@ abstract class ZipAbstractEntry implements ZipEntry
*/
public function getTime()
{
- if (!$this->isInit(self::BIT_DATE_TIME)) {
+ if ($this->getDosTime() === self::UNKNOWN) {
return self::UNKNOWN;
}
@@ -533,7 +499,6 @@ abstract class ZipAbstractEntry implements ZipEntry
throw new ZipException('DosTime out of range');
}
$this->dosTime = $dosTime;
- $this->setInit(self::BIT_DATE_TIME, true);
}
/**
@@ -554,7 +519,6 @@ abstract class ZipAbstractEntry implements ZipEntry
} else {
$this->dosTime = 0;
}
- $this->setInit(self::BIT_DATE_TIME, $known);
return $this;
}
@@ -566,10 +530,6 @@ abstract class ZipAbstractEntry implements ZipEntry
*/
public function getExternalAttributes()
{
- if (!$this->isInit(self::BIT_EXTERNAL_ATTR)) {
- return $this->isDirectory() ? 0x10 : 0;
- }
-
return $this->externalAttributes;
}
@@ -582,14 +542,7 @@ abstract class ZipAbstractEntry implements ZipEntry
*/
public function setExternalAttributes($externalAttributes)
{
- $known = $externalAttributes !== self::UNKNOWN;
-
- if ($known) {
- $this->externalAttributes = $externalAttributes;
- } else {
- $this->externalAttributes = 0;
- }
- $this->setInit(self::BIT_EXTERNAL_ATTR, $known);
+ $this->externalAttributes = $externalAttributes;
return $this;
}
@@ -655,7 +608,7 @@ abstract class ZipAbstractEntry implements ZipEntry
/**
* Set entry comment.
*
- * @param $comment
+ * @param string|null $comment
*
* @throws ZipException
*
@@ -669,8 +622,8 @@ abstract class ZipAbstractEntry implements ZipEntry
if ($commentLength < 0x0000 || $commentLength > 0xffff) {
throw new ZipException('Comment too long');
}
+ $this->setGeneralPurposeBitFlag(self::GPBF_UTF8, true);
}
- $this->setGeneralPurposeBitFlag(self::GPBF_UTF8, true);
$this->comment = $comment;
return $this;
@@ -703,8 +656,7 @@ abstract class ZipAbstractEntry implements ZipEntry
*/
public function setCrc($crc)
{
- $this->crc = $crc;
- $this->setInit(self::BIT_CRC, true);
+ $this->crc = (int) $crc;
return $this;
}
diff --git a/src/PhpZip/Model/ZipEntry.php b/src/PhpZip/Model/ZipEntry.php
index eca9d9d..7f9ece0 100644
--- a/src/PhpZip/Model/ZipEntry.php
+++ b/src/PhpZip/Model/ZipEntry.php
@@ -17,14 +17,6 @@ use PhpZip\ZipFileInterface;
interface ZipEntry
{
// Bit masks for initialized fields.
- const BIT_PLATFORM = 1;
-
- const BIT_METHOD = 2;
-
- const BIT_CRC = 4;
-
- const BIT_DATE_TIME = 64;
-
const BIT_EXTERNAL_ATTR = 128;
/** The unknown value for numeric properties. */
@@ -48,13 +40,12 @@ interface ZipEntry
/** General Purpose Bit Flag mask for encrypted data. */
const GPBF_ENCRYPTED = 1;
- // 1 << 0
-// (For Methods 8 and 9 - Deflating)
-// Bit 2 Bit 1
-// 0 0 Normal compression
-// 0 1 Maximum compression
-// 1 0 Fast compression
-// 1 1 Super Fast compression
+ // (For Methods 8 and 9 - Deflating)
+ // Bit 2 Bit 1
+ // 0 0 Normal compression
+ // 0 1 Maximum compression
+ // 1 0 Fast compression
+ // 1 1 Super Fast compression
const GPBF_COMPRESSION_FLAG1 = 2; // 1 << 1
const GPBF_COMPRESSION_FLAG2 = 4; // 1 << 2
diff --git a/src/PhpZip/Model/ZipInfo.php b/src/PhpZip/Model/ZipInfo.php
index 234a849..19b90fa 100644
--- a/src/PhpZip/Model/ZipInfo.php
+++ b/src/PhpZip/Model/ZipInfo.php
@@ -234,12 +234,8 @@ class ZipInfo
$this->name = $entry->getName();
$this->folder = $entry->isDirectory();
- $this->size = \PHP_INT_SIZE === 4 ?
- sprintf('%u', $entry->getSize()) :
- $entry->getSize();
- $this->compressedSize = \PHP_INT_SIZE === 4 ?
- sprintf('%u', $entry->getCompressedSize()) :
- $entry->getCompressedSize();
+ $this->size = $entry->getSize();
+ $this->compressedSize = $entry->getCompressedSize();
$this->mtime = $mtime;
$this->ctime = $ctime;
$this->atime = $atime;
@@ -255,16 +251,13 @@ class ZipInfo
$attributes = str_repeat(' ', 12);
$externalAttributes = $entry->getExternalAttributes();
- $externalAttributes = \PHP_INT_SIZE === 4 ?
- sprintf('%u', $externalAttributes) :
- $externalAttributes;
$xattr = (($externalAttributes >> 16) & 0xFFFF);
switch ($entry->getPlatform()) {
case self::MADE_BY_MS_DOS:
case self::MADE_BY_WINDOWS_NTFS:
if ($entry->getPlatform() !== self::MADE_BY_MS_DOS ||
- ($xattr & 0700) !==
- (0400 |
+ ($xattr & self::UNX_IRWXU) !==
+ (self::UNX_IRUSR |
(!($externalAttributes & 1) << 7) |
(($externalAttributes & 0x10) << 2))
) {
@@ -392,30 +385,29 @@ class ZipInfo
{
$return = '';
+ $compressionMethod = $entry->getMethod();
+
if ($entry->isEncrypted()) {
if ($entry->getMethod() === ZipEntry::METHOD_WINZIP_AES) {
- $return = ucfirst(self::$valuesCompressionMethod[$entry->getMethod()]);
+ $return .= ucfirst(self::$valuesCompressionMethod[$entry->getMethod()]);
/** @var WinZipAesEntryExtraField|null $field */
$field = $entry->getExtraFieldsCollection()->get(WinZipAesEntryExtraField::getHeaderId());
if ($field !== null) {
$return .= '-' . $field->getKeyStrength();
-
- if (isset(self::$valuesCompressionMethod[$field->getMethod()])) {
- $return .= ' ' . ucfirst(self::$valuesCompressionMethod[$field->getMethod()]);
- }
+ $compressionMethod = $field->getMethod();
}
} else {
$return .= 'ZipCrypto';
-
- if (isset(self::$valuesCompressionMethod[$entry->getMethod()])) {
- $return .= ' ' . ucfirst(self::$valuesCompressionMethod[$entry->getMethod()]);
- }
}
- } elseif (isset(self::$valuesCompressionMethod[$entry->getMethod()])) {
- $return = ucfirst(self::$valuesCompressionMethod[$entry->getMethod()]);
+
+ $return .= ' ';
+ }
+
+ if (isset(self::$valuesCompressionMethod[$compressionMethod])) {
+ $return .= ucfirst(self::$valuesCompressionMethod[$compressionMethod]);
} else {
- $return = 'unknown';
+ $return .= 'unknown';
}
return $return;
diff --git a/src/PhpZip/Stream/ZipInputStream.php b/src/PhpZip/Stream/ZipInputStream.php
index bd0d777..1f42647 100644
--- a/src/PhpZip/Stream/ZipInputStream.php
+++ b/src/PhpZip/Stream/ZipInputStream.php
@@ -277,7 +277,6 @@ class ZipInputStream implements ZipInputStreamInterface
// Extra Field may have been parsed, map it to the real
// offset and conditionally update the preamble size from it.
$lfhOff = $this->mapper->map($entry->getOffset());
- $lfhOff = \PHP_INT_SIZE === 4 ? sprintf('%u', $lfhOff) : $lfhOff;
if ($lfhOff < $this->preamble) {
$this->preamble = $lfhOff;
@@ -412,9 +411,6 @@ class ZipInputStream implements ZipInputStreamInterface
}
$pos = $entry->getOffset();
- $pos = \PHP_INT_SIZE === 4
- ? sprintf('%u', $pos) // PHP 32-Bit
- : $pos; // PHP 64-Bit
$startPos = $pos = $this->mapper->map($pos);
fseek($this->in, $startPos);
@@ -429,7 +425,9 @@ class ZipInputStream implements ZipInputStreamInterface
$data = unpack('vfileLength/vextraLength', fread($this->in, 4));
$pos += ZipEntry::LOCAL_FILE_HEADER_MIN_LEN + $data['fileLength'] + $data['extraLength'];
- \assert($entry->getCrc() !== ZipEntry::UNKNOWN);
+ if ($entry->getCrc() === ZipEntry::UNKNOWN) {
+ throw new ZipException(sprintf('Missing crc for entry %s', $entry->getName()));
+ }
$method = $entry->getMethod();
@@ -437,7 +435,6 @@ class ZipInputStream implements ZipInputStreamInterface
// Get raw entry content
$compressedSize = $entry->getCompressedSize();
- $compressedSize = \PHP_INT_SIZE === 4 ? sprintf('%u', $compressedSize) : $compressedSize;
$content = '';
if ($compressedSize > 0) {
@@ -587,8 +584,11 @@ class ZipInputStream implements ZipInputStreamInterface
public function copyEntry(ZipEntry $entry, ZipOutputStreamInterface $out)
{
$pos = $entry->getOffset();
- \assert($pos !== ZipEntry::UNKNOWN);
- $pos = \PHP_INT_SIZE === 4 ? sprintf('%u', $pos) : $pos;
+
+ if ($pos === ZipEntry::UNKNOWN) {
+ throw new ZipException(sprintf('Missing local header offset for entry %s', $entry->getName()));
+ }
+
$pos = $this->mapper->map($pos);
$nameLength = \strlen($entry->getName());
@@ -688,7 +688,6 @@ class ZipInputStream implements ZipInputStreamInterface
public function copyEntryData(ZipEntry $entry, ZipOutputStreamInterface $out)
{
$offset = $entry->getOffset();
- $offset = \PHP_INT_SIZE === 4 ? sprintf('%u', $offset) : $offset;
$offset = $this->mapper->map($offset);
$nameLength = \strlen($entry->getName());
diff --git a/src/PhpZip/Stream/ZipOutputStream.php b/src/PhpZip/Stream/ZipOutputStream.php
index fca9074..897b5d1 100644
--- a/src/PhpZip/Stream/ZipOutputStream.php
+++ b/src/PhpZip/Stream/ZipOutputStream.php
@@ -179,8 +179,17 @@ class ZipOutputStream implements ZipOutputStreamInterface
fwrite($this->out, $entryContent);
}
- \assert($entry->getCrc() !== ZipEntry::UNKNOWN);
- \assert($entry->getSize() !== ZipEntry::UNKNOWN);
+ if ($entry->getCrc() === ZipEntry::UNKNOWN) {
+ throw new ZipException(sprintf('No crc for entry %s', $entry->getName()));
+ }
+
+ if ($entry->getSize() === ZipEntry::UNKNOWN) {
+ throw new ZipException(sprintf('No uncompressed size for entry %s', $entry->getName()));
+ }
+
+ if ($entry->getCompressedSize() === ZipEntry::UNKNOWN) {
+ throw new ZipException(sprintf('No compressed size for entry %s', $entry->getName()));
+ }
if ($entry->getGeneralPurposeBitFlag(ZipEntry::GPBF_DATA_DESCRIPTOR)) {
// data descriptor signature 4 bytes (0x08074b50)
@@ -226,7 +235,7 @@ class ZipOutputStream implements ZipOutputStreamInterface
$utf8 = true;
if ($encrypted && $entry->getPassword() === null) {
- throw new ZipException('Can not password from entry ' . $entry->getName());
+ throw new ZipException(sprintf('Password not set for entry %s', $entry->getName()));
}
// Compose General Purpose Bit Flag.
diff --git a/tests/PhpZip/Issue24Test.php b/tests/PhpZip/Issue24Test.php
index 7b9487e..710935d 100644
--- a/tests/PhpZip/Issue24Test.php
+++ b/tests/PhpZip/Issue24Test.php
@@ -9,7 +9,6 @@ use PhpZip\Util\CryptoUtil;
* @internal
*
* @small
- * @covers
*/
class Issue24Test extends ZipTestCase
{
diff --git a/tests/PhpZip/PhpZipExtResourceTest.php b/tests/PhpZip/PhpZipExtResourceTest.php
index 0ba2542..1c1ee9a 100644
--- a/tests/PhpZip/PhpZipExtResourceTest.php
+++ b/tests/PhpZip/PhpZipExtResourceTest.php
@@ -3,6 +3,7 @@
namespace PhpZip;
use PhpZip\Exception\Crc32Exception;
+use PhpZip\Exception\RuntimeException;
use PhpZip\Exception\ZipAuthenticationException;
use PhpZip\Exception\ZipException;
@@ -12,7 +13,6 @@ use PhpZip\Exception\ZipException;
* @internal
*
* @small
- * @covers
*/
class PhpZipExtResourceTest extends ZipTestCase
{
@@ -126,7 +126,14 @@ class PhpZipExtResourceTest extends ZipTestCase
*/
public function testBug70752()
{
- $this->setExpectedException(ZipAuthenticationException::class, 'nvalid password for zip entry "bug70752.txt"');
+ if (\PHP_INT_SIZE === 4) { // php 32 bit
+ $this->setExpectedException(RuntimeException::class, 'Traditional PKWARE Encryption is not supported in 32-bit PHP.');
+ } else { // php 64 bit
+ $this->setExpectedException(
+ ZipAuthenticationException::class,
+ 'nvalid password for zip entry "bug70752.txt"'
+ );
+ }
$filename = __DIR__ . '/php-zip-ext-test-resources/bug70752.zip';
diff --git a/tests/PhpZip/Zip64Test.php b/tests/PhpZip/Zip64Test.php
index a11eb18..e9ebe85 100644
--- a/tests/PhpZip/Zip64Test.php
+++ b/tests/PhpZip/Zip64Test.php
@@ -8,7 +8,6 @@ use PhpZip\Exception\ZipException;
* @internal
*
* @large
- * @covers
*/
class Zip64Test extends ZipTestCase
{
diff --git a/tests/PhpZip/ZipAlignTest.php b/tests/PhpZip/ZipAlignTest.php
index 24b09d8..177f0a9 100644
--- a/tests/PhpZip/ZipAlignTest.php
+++ b/tests/PhpZip/ZipAlignTest.php
@@ -11,7 +11,6 @@ use PhpZip\Util\CryptoUtil;
* @internal
*
* @small
- * @covers
*/
class ZipAlignTest extends ZipTestCase
{
diff --git a/tests/PhpZip/ZipEventTest.php b/tests/PhpZip/ZipEventTest.php
index fef6bc2..950a645 100644
--- a/tests/PhpZip/ZipEventTest.php
+++ b/tests/PhpZip/ZipEventTest.php
@@ -8,7 +8,6 @@ use PhpZip\Exception\ZipException;
* @internal
*
* @small
- * @covers
*/
class ZipEventTest extends ZipTestCase
{
diff --git a/tests/PhpZip/ZipFileAddDirTest.php b/tests/PhpZip/ZipFileAddDirTest.php
index b8a1143..69d5c22 100644
--- a/tests/PhpZip/ZipFileAddDirTest.php
+++ b/tests/PhpZip/ZipFileAddDirTest.php
@@ -12,7 +12,6 @@ use PhpZip\Util\Iterator\IgnoreFilesRecursiveFilterIterator;
* @internal
*
* @small
- * @covers
*/
class ZipFileAddDirTest extends ZipTestCase
{
diff --git a/tests/PhpZip/ZipFileTest.php b/tests/PhpZip/ZipFileTest.php
index cb0163f..fa97374 100644
--- a/tests/PhpZip/ZipFileTest.php
+++ b/tests/PhpZip/ZipFileTest.php
@@ -19,7 +19,6 @@ use Zend\Diactoros\Response;
* @internal
*
* @small
- * @covers
*/
class ZipFileTest extends ZipTestCase
{
@@ -44,6 +43,8 @@ class ZipFileTest extends ZipTestCase
/** @noinspection PhpComposerExtensionStubsInspection */
if (posix_getuid() === 0) {
static::markTestSkipped('Skip the test for a user with root privileges');
+
+ return;
}
static::assertNotFalse(file_put_contents($this->outputFilename, 'content'));
@@ -170,6 +171,8 @@ class ZipFileTest extends ZipTestCase
if (!\extension_loaded('gd')) {
static::markTestSkipped('not extension gd');
+
+ return;
}
/** @noinspection PhpComposerExtensionStubsInspection */
$zipFile->openFromStream(imagecreate(1, 1));
@@ -425,6 +428,8 @@ class ZipFileTest extends ZipTestCase
{
if (!\function_exists('mime_content_type')) {
static::markTestSkipped('Function mime_content_type not exists');
+
+ return;
}
$outputFilename = $this->outputFilename;
$this->outputFilename .= '.gif';
@@ -1117,6 +1122,8 @@ class ZipFileTest extends ZipTestCase
/** @noinspection PhpComposerExtensionStubsInspection */
if (posix_getuid() === 0) {
static::markTestSkipped('Skip the test for a user with root privileges');
+
+ return;
}
$zipFile = new ZipFile();
@@ -1341,6 +1348,8 @@ class ZipFileTest extends ZipTestCase
/** @noinspection PhpComposerExtensionStubsInspection */
if (posix_getuid() === 0) {
static::markTestSkipped('Skip the test for a user with root privileges');
+
+ return;
}
static::assertNotFalse(file_put_contents($this->outputFilename, ''));
@@ -1658,6 +1667,8 @@ class ZipFileTest extends ZipTestCase
/** @noinspection PhpComposerExtensionStubsInspection */
if (posix_getuid() === 0) {
static::markTestSkipped('Skip the test for a user with root privileges');
+
+ return;
}
static::assertTrue(mkdir($this->outputDirname, 0444, true));
diff --git a/tests/PhpZip/ZipMatcherTest.php b/tests/PhpZip/ZipMatcherTest.php
index 8d29d6b..debf574 100644
--- a/tests/PhpZip/ZipMatcherTest.php
+++ b/tests/PhpZip/ZipMatcherTest.php
@@ -11,7 +11,6 @@ use PhpZip\Util\CryptoUtil;
* @internal
*
* @small
- * @covers
*/
class ZipMatcherTest extends TestCase
{
diff --git a/tests/PhpZip/ZipPasswordTest.php b/tests/PhpZip/ZipPasswordTest.php
index 994439e..dc00b26 100644
--- a/tests/PhpZip/ZipPasswordTest.php
+++ b/tests/PhpZip/ZipPasswordTest.php
@@ -2,6 +2,7 @@
namespace PhpZip;
+use PhpZip\Exception\RuntimeException;
use PhpZip\Exception\ZipAuthenticationException;
use PhpZip\Exception\ZipEntryNotFoundException;
use PhpZip\Exception\ZipException;
@@ -14,7 +15,6 @@ use PhpZip\Util\CryptoUtil;
* @internal
*
* @small
- * @covers
*/
class ZipPasswordTest extends ZipFileAddDirTest
{
@@ -25,8 +25,8 @@ class ZipPasswordTest extends ZipFileAddDirTest
*/
public function testSetPassword()
{
- if (\PHP_INT_SIZE === 4) {
- static::markTestSkipped('Skip test for 32-bit system. Not support Traditional PKWARE Encryption.');
+ if (\PHP_INT_SIZE === 4) { // php 32 bit
+ $this->setExpectedException(RuntimeException::class, 'Traditional PKWARE Encryption is not supported in 32-bit PHP.');
}
$password = base64_encode(CryptoUtil::randomBytes(100));
@@ -120,8 +120,8 @@ class ZipPasswordTest extends ZipFileAddDirTest
*/
public function testTraditionalEncryption()
{
- if (\PHP_INT_SIZE === 4) {
- static::markTestSkipped('Skip test for 32-bit system. Not support Traditional PKWARE Encryption.');
+ if (\PHP_INT_SIZE === 4) { // php 32 bit
+ $this->setExpectedException(RuntimeException::class, 'Traditional PKWARE Encryption is not supported in 32-bit PHP.');
}
$password = base64_encode(CryptoUtil::randomBytes(50));
@@ -200,8 +200,8 @@ class ZipPasswordTest extends ZipFileAddDirTest
*/
public function testEncryptionEntries()
{
- if (\PHP_INT_SIZE === 4) {
- static::markTestSkipped('Skip test for 32-bit system. Not support Traditional PKWARE Encryption.');
+ if (\PHP_INT_SIZE === 4) { // php 32 bit
+ $this->setExpectedException(RuntimeException::class, 'Traditional PKWARE Encryption is not supported in 32-bit PHP.');
}
$password1 = '353442434235424234';
@@ -247,8 +247,8 @@ class ZipPasswordTest extends ZipFileAddDirTest
*/
public function testEncryptionEntriesWithDefaultPassword()
{
- if (\PHP_INT_SIZE === 4) {
- static::markTestSkipped('Skip test for 32-bit system. Not support Traditional PKWARE Encryption.');
+ if (\PHP_INT_SIZE === 4) { // php 32 bit
+ $this->setExpectedException(RuntimeException::class, 'Traditional PKWARE Encryption is not supported in 32-bit PHP.');
}
$password1 = '353442434235424234';
diff --git a/tests/PhpZip/ZipRemoteFileTest.php b/tests/PhpZip/ZipRemoteFileTest.php
index e5a6d12..5047d04 100644
--- a/tests/PhpZip/ZipRemoteFileTest.php
+++ b/tests/PhpZip/ZipRemoteFileTest.php
@@ -10,7 +10,6 @@ use PhpZip\Exception\ZipException;
* @internal
*
* @small
- * @covers
*/
class ZipRemoteFileTest extends ZipTestCase
{
diff --git a/tests/PhpZip/ZipSlipVulnerabilityTest.php b/tests/PhpZip/ZipSlipVulnerabilityTest.php
index ce2882f..45d92e7 100644
--- a/tests/PhpZip/ZipSlipVulnerabilityTest.php
+++ b/tests/PhpZip/ZipSlipVulnerabilityTest.php
@@ -11,7 +11,6 @@ namespace PhpZip;
* @internal
*
* @small
- * @covers
*/
class ZipSlipVulnerabilityTest extends ZipTestCase
{
From 95e3312e6044e57638f283b370dbbf07f1101521 Mon Sep 17 00:00:00 2001
From: Ne-Lexa
Date: Fri, 6 Dec 2019 17:36:22 +0300
Subject: [PATCH 5/8] refactoring zip64, add property softwareVersion, internal
attrs, extracted os
---
composer.json | 5 -
src/PhpZip/Crypto/WinZipAesEngine.php | 2 +-
.../Extra/Fields/WinZipAesEntryExtraField.php | 8 +-
src/PhpZip/Mapper/OffsetPositionMapper.php | 43 --
src/PhpZip/Mapper/PositionMapper.php | 32 --
src/PhpZip/Model/EndOfCentralDirectory.php | 70 ++-
src/PhpZip/Model/Entry/OutputOffsetEntry.php | 2 +
src/PhpZip/Model/Entry/ZipAbstractEntry.php | 233 ++++++--
src/PhpZip/Model/Entry/ZipChangesEntry.php | 2 +
src/PhpZip/Model/Entry/ZipNewEntry.php | 20 -
src/PhpZip/Model/ZipEntry.php | 89 +++-
src/PhpZip/Model/ZipInfo.php | 14 +-
src/PhpZip/Model/ZipModel.php | 6 +-
src/PhpZip/Stream/ZipInputStream.php | 496 +++++++++---------
src/PhpZip/Stream/ZipInputStreamInterface.php | 8 +-
src/PhpZip/Stream/ZipOutputStream.php | 157 +++---
src/PhpZip/ZipFile.php | 66 +--
src/PhpZip/ZipFileInterface.php | 58 +-
tests/PhpZip/PhpZipExtResourceTest.php | 17 +-
tests/PhpZip/ZipAlignTest.php | 10 +-
tests/PhpZip/ZipFileTest.php | 50 +-
tests/PhpZip/ZipMatcherTest.php | 12 +-
tests/PhpZip/ZipPasswordTest.php | 45 +-
tests/PhpZip/ZipTestCase.php | 2 +-
24 files changed, 821 insertions(+), 626 deletions(-)
delete mode 100644 src/PhpZip/Mapper/OffsetPositionMapper.php
delete mode 100644 src/PhpZip/Mapper/PositionMapper.php
diff --git a/composer.json b/composer.json
index 94cc8ce..6f0c4dc 100644
--- a/composer.json
+++ b/composer.json
@@ -25,11 +25,6 @@
"ext-zlib": "*",
"psr/http-message": "^1.0"
},
- "config": {
- "platform": {
- "php": "5.5"
- }
- },
"require-dev": {
"phpunit/phpunit": "^4.8|^5.7",
"zendframework/zend-diactoros": "^1.4"
diff --git a/src/PhpZip/Crypto/WinZipAesEngine.php b/src/PhpZip/Crypto/WinZipAesEngine.php
index 4e1056e..d050fca 100644
--- a/src/PhpZip/Crypto/WinZipAesEngine.php
+++ b/src/PhpZip/Crypto/WinZipAesEngine.php
@@ -49,9 +49,9 @@ class WinZipAesEngine implements ZipEncryptionEngine
*
* @param string $content Input stream buffer
*
- * @throws ZipCryptoException
* @throws ZipException
* @throws ZipAuthenticationException
+ * @throws ZipCryptoException
*
* @return string
*/
diff --git a/src/PhpZip/Extra/Fields/WinZipAesEntryExtraField.php b/src/PhpZip/Extra/Fields/WinZipAesEntryExtraField.php
index 948452a..582514a 100644
--- a/src/PhpZip/Extra/Fields/WinZipAesEntryExtraField.php
+++ b/src/PhpZip/Extra/Fields/WinZipAesEntryExtraField.php
@@ -4,7 +4,7 @@ namespace PhpZip\Extra\Fields;
use PhpZip\Exception\ZipException;
use PhpZip\Extra\ExtraField;
-use PhpZip\ZipFileInterface;
+use PhpZip\ZipFile;
/**
* WinZip AES Extra Field.
@@ -49,9 +49,9 @@ class WinZipAesEntryExtraField implements ExtraField
];
protected static $encryptionMethods = [
- self::KEY_STRENGTH_128BIT => ZipFileInterface::ENCRYPTION_METHOD_WINZIP_AES_128,
- self::KEY_STRENGTH_192BIT => ZipFileInterface::ENCRYPTION_METHOD_WINZIP_AES_192,
- self::KEY_STRENGTH_256BIT => ZipFileInterface::ENCRYPTION_METHOD_WINZIP_AES_256,
+ self::KEY_STRENGTH_128BIT => ZipFile::ENCRYPTION_METHOD_WINZIP_AES_128,
+ self::KEY_STRENGTH_192BIT => ZipFile::ENCRYPTION_METHOD_WINZIP_AES_192,
+ self::KEY_STRENGTH_256BIT => ZipFile::ENCRYPTION_METHOD_WINZIP_AES_256,
];
/**
diff --git a/src/PhpZip/Mapper/OffsetPositionMapper.php b/src/PhpZip/Mapper/OffsetPositionMapper.php
deleted file mode 100644
index 747b8a1..0000000
--- a/src/PhpZip/Mapper/OffsetPositionMapper.php
+++ /dev/null
@@ -1,43 +0,0 @@
-offset = (int) $offset;
- }
-
- /**
- * @param int $position
- *
- * @return int
- */
- public function map($position)
- {
- return parent::map($position) + $this->offset;
- }
-
- /**
- * @param int $position
- *
- * @return int
- */
- public function unmap($position)
- {
- return parent::unmap($position) - $this->offset;
- }
-}
diff --git a/src/PhpZip/Mapper/PositionMapper.php b/src/PhpZip/Mapper/PositionMapper.php
deleted file mode 100644
index 42a9b29..0000000
--- a/src/PhpZip/Mapper/PositionMapper.php
+++ /dev/null
@@ -1,32 +0,0 @@
-entryCount = $entryCount;
- $this->comment = $comment;
+ $this->cdOffset = $cdOffset;
+ $this->cdSize = $cdSize;
$this->zip64 = $zip64;
+ $this->comment = $comment;
}
/**
- * @return string|null
+ * @param string|null $comment
*/
- public function getComment()
+ public function setComment($comment)
{
- return $this->comment;
+ $this->comment = $comment;
}
/**
@@ -113,6 +123,30 @@ class EndOfCentralDirectory
return $this->entryCount;
}
+ /**
+ * @return int
+ */
+ public function getCdOffset()
+ {
+ return $this->cdOffset;
+ }
+
+ /**
+ * @return int
+ */
+ public function getCdSize()
+ {
+ return $this->cdSize;
+ }
+
+ /**
+ * @return string|null
+ */
+ public function getComment()
+ {
+ return $this->comment;
+ }
+
/**
* @return bool
*/
diff --git a/src/PhpZip/Model/Entry/OutputOffsetEntry.php b/src/PhpZip/Model/Entry/OutputOffsetEntry.php
index fea5383..b968212 100644
--- a/src/PhpZip/Model/Entry/OutputOffsetEntry.php
+++ b/src/PhpZip/Model/Entry/OutputOffsetEntry.php
@@ -9,6 +9,8 @@ use PhpZip\Model\ZipEntry;
*
* @author Ne-Lexa alexey@nelexa.ru
* @license MIT
+ *
+ * @internal
*/
class OutputOffsetEntry
{
diff --git a/src/PhpZip/Model/Entry/ZipAbstractEntry.php b/src/PhpZip/Model/Entry/ZipAbstractEntry.php
index c5435c6..f8dcc1a 100644
--- a/src/PhpZip/Model/Entry/ZipAbstractEntry.php
+++ b/src/PhpZip/Model/Entry/ZipAbstractEntry.php
@@ -10,7 +10,7 @@ use PhpZip\Extra\Fields\WinZipAesEntryExtraField;
use PhpZip\Model\ZipEntry;
use PhpZip\Util\DateTimeConverter;
use PhpZip\Util\StringUtil;
-use PhpZip\ZipFileInterface;
+use PhpZip\ZipFile;
/**
* Abstract ZIP entry.
@@ -26,16 +26,22 @@ abstract class ZipAbstractEntry implements ZipEntry
private $name;
/** @var int Made by platform */
- private $platform = self::UNKNOWN;
+ private $createdOS = self::UNKNOWN;
+
+ /** @var int Extracted by platform */
+ private $extractedOS = self::UNKNOWN;
/** @var int */
- private $versionNeededToExtract = 20;
+ private $softwareVersion = self::UNKNOWN;
+
+ /** @var int */
+ private $versionNeededToExtract = self::UNKNOWN;
/** @var int Compression method */
private $method = self::UNKNOWN;
/** @var int */
- private $general = 0;
+ private $generalPurposeBitFlags = 0;
/** @var int Dos time */
private $dosTime = self::UNKNOWN;
@@ -49,11 +55,14 @@ abstract class ZipAbstractEntry implements ZipEntry
/** @var int Uncompressed size */
private $size = self::UNKNOWN;
+ /** @var int Internal attributes */
+ private $internalAttributes = 0;
+
/** @var int External attributes */
private $externalAttributes = 0;
/** @var int relative Offset Of Local File Header */
- private $offset = self::UNKNOWN;
+ private $offset = 0;
/**
* Collections of Extra Fields.
@@ -73,17 +82,17 @@ abstract class ZipAbstractEntry implements ZipEntry
/**
* Encryption method.
*
- * @see ZipFileInterface::ENCRYPTION_METHOD_TRADITIONAL
- * @see ZipFileInterface::ENCRYPTION_METHOD_WINZIP_AES_128
- * @see ZipFileInterface::ENCRYPTION_METHOD_WINZIP_AES_192
- * @see ZipFileInterface::ENCRYPTION_METHOD_WINZIP_AES_256
+ * @see ZipFile::ENCRYPTION_METHOD_TRADITIONAL
+ * @see ZipFile::ENCRYPTION_METHOD_WINZIP_AES_128
+ * @see ZipFile::ENCRYPTION_METHOD_WINZIP_AES_192
+ * @see ZipFile::ENCRYPTION_METHOD_WINZIP_AES_256
*
* @var int
*/
- private $encryptionMethod = ZipFileInterface::ENCRYPTION_METHOD_TRADITIONAL;
+ private $encryptionMethod = ZipFile::ENCRYPTION_METHOD_TRADITIONAL;
/** @var int */
- private $compressionLevel = ZipFileInterface::LEVEL_DEFAULT_COMPRESSION;
+ private $compressionLevel = ZipFile::LEVEL_DEFAULT_COMPRESSION;
/**
* ZipAbstractEntry constructor.
@@ -101,7 +110,9 @@ abstract class ZipAbstractEntry implements ZipEntry
public function setEntry(ZipEntry $entry)
{
$this->setName($entry->getName());
- $this->setPlatform($entry->getPlatform());
+ $this->setSoftwareVersion($entry->getSoftwareVersion());
+ $this->setCreatedOS($entry->getCreatedOS());
+ $this->setExtractedOS($entry->getExtractedOS());
$this->setVersionNeededToExtract($entry->getVersionNeededToExtract());
$this->setMethod($entry->getMethod());
$this->setGeneralPurposeBitFlags($entry->getGeneralPurposeBitFlags());
@@ -109,6 +120,7 @@ abstract class ZipAbstractEntry implements ZipEntry
$this->setCrc($entry->getCrc());
$this->setCompressedSize($entry->getCompressedSize());
$this->setSize($entry->getSize());
+ $this->setInternalAttributes($entry->getInternalAttributes());
$this->setExternalAttributes($entry->getExternalAttributes());
$this->setOffset($entry->getOffset());
$this->setExtra($entry->getExtra());
@@ -163,20 +175,48 @@ abstract class ZipAbstractEntry implements ZipEntry
public function setGeneralPurposeBitFlag($mask, $bit)
{
if ($bit) {
- $this->general |= $mask;
+ $this->generalPurposeBitFlags |= $mask;
} else {
- $this->general &= ~$mask;
+ $this->generalPurposeBitFlags &= ~$mask;
}
return $this;
}
/**
- * @return int platform
+ * @return int Get platform
+ *
+ * @deprecated Use {@see ZipEntry::getCreatedOS()}
*/
public function getPlatform()
{
- return $this->platform;
+ @trigger_error('ZipEntry::getPlatform() is deprecated. Use ZipEntry::getCreatedOS()', \E_USER_DEPRECATED);
+
+ return $this->getCreatedOS();
+ }
+
+ /**
+ * @param int $platform
+ *
+ * @throws ZipException
+ *
+ * @return ZipEntry
+ *
+ * @deprecated Use {@see ZipEntry::setCreatedOS()}
+ */
+ public function setPlatform($platform)
+ {
+ @trigger_error('ZipEntry::setPlatform() is deprecated. Use ZipEntry::setCreatedOS()', \E_USER_DEPRECATED);
+
+ return $this->setCreatedOS($platform);
+ }
+
+ /**
+ * @return int platform
+ */
+ public function getCreatedOS()
+ {
+ return $this->createdOS;
}
/**
@@ -188,16 +228,63 @@ abstract class ZipAbstractEntry implements ZipEntry
*
* @return ZipEntry
*/
- public function setPlatform($platform)
+ public function setCreatedOS($platform)
{
- if ($platform !== self::UNKNOWN) {
- if ($platform < 0x00 || $platform > 0xff) {
- throw new ZipException('Platform out of range');
- }
- $this->platform = $platform;
- } else {
- $this->platform = 0; // ms-dos
+ $platform = (int) $platform;
+
+ if ($platform < 0x00 || $platform > 0xff) {
+ throw new ZipException('Platform out of range');
}
+ $this->createdOS = $platform;
+
+ return $this;
+ }
+
+ /**
+ * @return int
+ */
+ public function getExtractedOS()
+ {
+ return $this->extractedOS;
+ }
+
+ /**
+ * Set extracted OS.
+ *
+ * @param int $platform
+ *
+ * @throws ZipException
+ *
+ * @return ZipEntry
+ */
+ public function setExtractedOS($platform)
+ {
+ $platform = (int) $platform;
+
+ if ($platform < 0x00 || $platform > 0xff) {
+ throw new ZipException('Platform out of range');
+ }
+ $this->extractedOS = $platform;
+
+ return $this;
+ }
+
+ /**
+ * @return int
+ */
+ public function getSoftwareVersion()
+ {
+ return $this->softwareVersion;
+ }
+
+ /**
+ * @param int $softwareVersion
+ *
+ * @return ZipEntry
+ */
+ public function setSoftwareVersion($softwareVersion)
+ {
+ $this->softwareVersion = (int) $softwareVersion;
return $this;
}
@@ -209,6 +296,24 @@ abstract class ZipAbstractEntry implements ZipEntry
*/
public function getVersionNeededToExtract()
{
+ if ($this->versionNeededToExtract === self::UNKNOWN) {
+ $method = $this->getMethod();
+
+ if ($method === self::METHOD_WINZIP_AES) {
+ return 51;
+ }
+
+ if ($method === ZipFile::METHOD_BZIP2) {
+ return 46;
+ }
+
+ if ($this->isZip64ExtensionsRequired()) {
+ return 45;
+ }
+
+ return $method === ZipFile::METHOD_DEFLATED || $this->isDirectory() ? 20 : 10;
+ }
+
return $this->versionNeededToExtract;
}
@@ -300,7 +405,7 @@ abstract class ZipAbstractEntry implements ZipEntry
*/
public function setOffset($offset)
{
- $this->offset = $offset;
+ $this->offset = (int) $offset;
return $this;
}
@@ -312,7 +417,7 @@ abstract class ZipAbstractEntry implements ZipEntry
*/
public function getGeneralPurposeBitFlags()
{
- return $this->general & 0xffff;
+ return $this->generalPurposeBitFlags & 0xffff;
}
/**
@@ -331,20 +436,20 @@ abstract class ZipAbstractEntry implements ZipEntry
if ($general < 0x0000 || $general > 0xffff) {
throw new ZipException('general out of range');
}
- $this->general = $general;
+ $this->generalPurposeBitFlags = $general;
- if ($this->method === ZipFileInterface::METHOD_DEFLATED) {
+ if ($this->method === ZipFile::METHOD_DEFLATED) {
$bit1 = $this->getGeneralPurposeBitFlag(self::GPBF_COMPRESSION_FLAG1);
$bit2 = $this->getGeneralPurposeBitFlag(self::GPBF_COMPRESSION_FLAG2);
if ($bit1 && !$bit2) {
- $this->compressionLevel = ZipFileInterface::LEVEL_BEST_COMPRESSION;
+ $this->compressionLevel = ZipFile::LEVEL_BEST_COMPRESSION;
} elseif (!$bit1 && $bit2) {
- $this->compressionLevel = ZipFileInterface::LEVEL_FAST;
+ $this->compressionLevel = ZipFile::LEVEL_FAST;
} elseif ($bit1 && $bit2) {
- $this->compressionLevel = ZipFileInterface::LEVEL_SUPER_FAST;
+ $this->compressionLevel = ZipFile::LEVEL_SUPER_FAST;
} else {
- $this->compressionLevel = ZipFileInterface::LEVEL_DEFAULT_COMPRESSION;
+ $this->compressionLevel = ZipFile::LEVEL_DEFAULT_COMPRESSION;
}
}
@@ -370,7 +475,7 @@ abstract class ZipAbstractEntry implements ZipEntry
*/
public function getGeneralPurposeBitFlag($mask)
{
- return ($this->general & $mask) !== 0;
+ return ($this->generalPurposeBitFlags & $mask) !== 0;
}
/**
@@ -447,9 +552,9 @@ abstract class ZipAbstractEntry implements ZipEntry
}
switch ($method) {
case self::METHOD_WINZIP_AES:
- case ZipFileInterface::METHOD_STORED:
- case ZipFileInterface::METHOD_DEFLATED:
- case ZipFileInterface::METHOD_BZIP2:
+ case ZipFile::METHOD_STORED:
+ case ZipFile::METHOD_DEFLATED:
+ case ZipFile::METHOD_BZIP2:
$this->method = $method;
break;
@@ -490,6 +595,8 @@ abstract class ZipAbstractEntry implements ZipEntry
* @param int $dosTime
*
* @throws ZipException
+ *
+ * @return ZipEntry
*/
public function setDosTime($dosTime)
{
@@ -499,6 +606,8 @@ abstract class ZipAbstractEntry implements ZipEntry
throw new ZipException('DosTime out of range');
}
$this->dosTime = $dosTime;
+
+ return $this;
}
/**
@@ -547,6 +656,30 @@ abstract class ZipAbstractEntry implements ZipEntry
return $this;
}
+ /**
+ * Sets the internal file attributes.
+ *
+ * @param int $attributes the internal file attributes
+ *
+ * @return ZipEntry
+ */
+ public function setInternalAttributes($attributes)
+ {
+ $this->internalAttributes = (int) $attributes;
+
+ return $this;
+ }
+
+ /**
+ * Returns the internal file attributes.
+ *
+ * @return int the internal file attributes
+ */
+ public function getInternalAttributes()
+ {
+ return $this->internalAttributes;
+ }
+
/**
* Returns true if and only if this ZIP entry represents a directory entry
* (i.e. end with '/').
@@ -589,10 +722,14 @@ abstract class ZipAbstractEntry implements ZipEntry
* @param string $data the byte array holding the serialized Extra Fields
*
* @throws ZipException if the serialized Extra Fields exceed 64 KB
+ *
+ * @return ZipEntry
*/
public function setExtra($data)
{
$this->extraFieldsCollection = ExtraFieldsFactory::createExtraFieldCollections($data, $this);
+
+ return $this;
}
/**
@@ -713,19 +850,19 @@ abstract class ZipAbstractEntry implements ZipEntry
*
* @return ZipEntry
*
- * @see ZipFileInterface::ENCRYPTION_METHOD_WINZIP_AES_256
- * @see ZipFileInterface::ENCRYPTION_METHOD_TRADITIONAL
- * @see ZipFileInterface::ENCRYPTION_METHOD_WINZIP_AES_128
- * @see ZipFileInterface::ENCRYPTION_METHOD_WINZIP_AES_192
+ * @see ZipFile::ENCRYPTION_METHOD_WINZIP_AES_256
+ * @see ZipFile::ENCRYPTION_METHOD_TRADITIONAL
+ * @see ZipFile::ENCRYPTION_METHOD_WINZIP_AES_128
+ * @see ZipFile::ENCRYPTION_METHOD_WINZIP_AES_192
*/
public function setEncryptionMethod($encryptionMethod)
{
if ($encryptionMethod !== null) {
if (
- $encryptionMethod !== ZipFileInterface::ENCRYPTION_METHOD_TRADITIONAL
- && $encryptionMethod !== ZipFileInterface::ENCRYPTION_METHOD_WINZIP_AES_128
- && $encryptionMethod !== ZipFileInterface::ENCRYPTION_METHOD_WINZIP_AES_192
- && $encryptionMethod !== ZipFileInterface::ENCRYPTION_METHOD_WINZIP_AES_256
+ $encryptionMethod !== ZipFile::ENCRYPTION_METHOD_TRADITIONAL
+ && $encryptionMethod !== ZipFile::ENCRYPTION_METHOD_WINZIP_AES_128
+ && $encryptionMethod !== ZipFile::ENCRYPTION_METHOD_WINZIP_AES_192
+ && $encryptionMethod !== ZipFile::ENCRYPTION_METHOD_WINZIP_AES_256
) {
throw new ZipException('Invalid encryption method');
}
@@ -748,14 +885,14 @@ abstract class ZipAbstractEntry implements ZipEntry
*
* @return ZipEntry
*/
- public function setCompressionLevel($compressionLevel = ZipFileInterface::LEVEL_DEFAULT_COMPRESSION)
+ public function setCompressionLevel($compressionLevel = ZipFile::LEVEL_DEFAULT_COMPRESSION)
{
- if ($compressionLevel < ZipFileInterface::LEVEL_DEFAULT_COMPRESSION ||
- $compressionLevel > ZipFileInterface::LEVEL_BEST_COMPRESSION
+ if ($compressionLevel < ZipFile::LEVEL_DEFAULT_COMPRESSION ||
+ $compressionLevel > ZipFile::LEVEL_BEST_COMPRESSION
) {
throw new InvalidArgumentException(
'Invalid compression level. Minimum level ' .
- ZipFileInterface::LEVEL_DEFAULT_COMPRESSION . '. Maximum level ' . ZipFileInterface::LEVEL_BEST_COMPRESSION
+ ZipFile::LEVEL_DEFAULT_COMPRESSION . '. Maximum level ' . ZipFile::LEVEL_BEST_COMPRESSION
);
}
$this->compressionLevel = $compressionLevel;
diff --git a/src/PhpZip/Model/Entry/ZipChangesEntry.php b/src/PhpZip/Model/Entry/ZipChangesEntry.php
index f2f1b46..c17415f 100644
--- a/src/PhpZip/Model/Entry/ZipChangesEntry.php
+++ b/src/PhpZip/Model/Entry/ZipChangesEntry.php
@@ -10,6 +10,8 @@ use PhpZip\Exception\ZipException;
*
* @author Ne-Lexa alexey@nelexa.ru
* @license MIT
+ *
+ * @internal
*/
class ZipChangesEntry extends ZipAbstractEntry
{
diff --git a/src/PhpZip/Model/Entry/ZipNewEntry.php b/src/PhpZip/Model/Entry/ZipNewEntry.php
index 2f8a3f8..5930a74 100644
--- a/src/PhpZip/Model/Entry/ZipNewEntry.php
+++ b/src/PhpZip/Model/Entry/ZipNewEntry.php
@@ -3,7 +3,6 @@
namespace PhpZip\Model\Entry;
use PhpZip\Exception\InvalidArgumentException;
-use PhpZip\ZipFileInterface;
/**
* @author Ne-Lexa alexey@nelexa.ru
@@ -50,25 +49,6 @@ class ZipNewEntry extends ZipAbstractEntry
return $this->content;
}
- /**
- * Version needed to extract.
- *
- * @return int
- */
- public function getVersionNeededToExtract()
- {
- $method = $this->getMethod();
-
- return $method === self::METHOD_WINZIP_AES ? 51 :
- (
- $method === ZipFileInterface::METHOD_BZIP2 ? 46 :
- (
- $this->isZip64ExtensionsRequired() ? 45 :
- ($method === ZipFileInterface::METHOD_DEFLATED || $this->isDirectory() ? 20 : 10)
- )
- );
- }
-
/**
* Clone extra fields.
*/
diff --git a/src/PhpZip/Model/ZipEntry.php b/src/PhpZip/Model/ZipEntry.php
index 7f9ece0..1360a71 100644
--- a/src/PhpZip/Model/ZipEntry.php
+++ b/src/PhpZip/Model/ZipEntry.php
@@ -4,7 +4,7 @@ namespace PhpZip\Model;
use PhpZip\Exception\ZipException;
use PhpZip\Extra\ExtraFieldsCollection;
-use PhpZip\ZipFileInterface;
+use PhpZip\ZipFile;
/**
* ZIP file entry.
@@ -16,9 +16,6 @@ use PhpZip\ZipFileInterface;
*/
interface ZipEntry
{
- // Bit masks for initialized fields.
- const BIT_EXTERNAL_ATTR = 128;
-
/** The unknown value for numeric properties. */
const UNKNOWN = -1;
@@ -118,11 +115,31 @@ interface ZipEntry
/**
* @return int Get platform
+ *
+ * @deprecated Use {@see ZipEntry::getCreatedOS()}
*/
public function getPlatform();
/**
- * Set platform.
+ * @param int $platform
+ *
+ * @throws ZipException
+ *
+ * @return ZipEntry
+ *
+ * @deprecated Use {@see ZipEntry::setCreatedOS()}
+ */
+ public function setPlatform($platform);
+
+ /**
+ * Returns created OS.
+ *
+ * @return int Get platform
+ */
+ public function getCreatedOS();
+
+ /**
+ * Set created OS.
*
* @param int $platform
*
@@ -130,7 +147,35 @@ interface ZipEntry
*
* @return ZipEntry
*/
- public function setPlatform($platform);
+ public function setCreatedOS($platform);
+
+ /**
+ * @return int
+ */
+ public function getExtractedOS();
+
+ /**
+ * Set extracted OS.
+ *
+ * @param int $platform
+ *
+ * @throws ZipException
+ *
+ * @return ZipEntry
+ */
+ public function setExtractedOS($platform);
+
+ /**
+ * @return int
+ */
+ public function getSoftwareVersion();
+
+ /**
+ * @param int $softwareVersion
+ *
+ * @return ZipEntry
+ */
+ public function setSoftwareVersion($softwareVersion);
/**
* Version needed to extract.
@@ -323,6 +368,8 @@ interface ZipEntry
* @param int $dosTime
*
* @throws ZipException
+ *
+ * @return ZipEntry
*/
public function setDosTime($dosTime);
@@ -333,6 +380,24 @@ interface ZipEntry
*/
public function getExternalAttributes();
+ /**
+ * Sets the internal file attributes.
+ *
+ * @param int $attributes the internal file attributes
+ *
+ * @throws ZipException
+ *
+ * @return ZipEntry
+ */
+ public function setInternalAttributes($attributes);
+
+ /**
+ * Returns the internal file attributes.
+ *
+ * @return int the internal file attributes
+ */
+ public function getInternalAttributes();
+
/**
* Sets the external file attributes.
*
@@ -368,6 +433,8 @@ interface ZipEntry
* @param string $data the byte array holding the serialized Extra Fields
*
* @throws ZipException if the serialized Extra Fields exceed 64 KB
+ *
+ * @return ZipEntry
*/
public function setExtra($data);
@@ -439,10 +506,10 @@ interface ZipEntry
*
* @return ZipEntry
*
- * @see ZipFileInterface::ENCRYPTION_METHOD_WINZIP_AES_256
- * @see ZipFileInterface::ENCRYPTION_METHOD_TRADITIONAL
- * @see ZipFileInterface::ENCRYPTION_METHOD_WINZIP_AES_128
- * @see ZipFileInterface::ENCRYPTION_METHOD_WINZIP_AES_192
+ * @see ZipFile::ENCRYPTION_METHOD_WINZIP_AES_256
+ * @see ZipFile::ENCRYPTION_METHOD_TRADITIONAL
+ * @see ZipFile::ENCRYPTION_METHOD_WINZIP_AES_128
+ * @see ZipFile::ENCRYPTION_METHOD_WINZIP_AES_192
*/
public function setEncryptionMethod($encryptionMethod);
@@ -460,7 +527,7 @@ interface ZipEntry
*
* @return ZipEntry
*/
- public function setCompressionLevel($compressionLevel = ZipFileInterface::LEVEL_DEFAULT_COMPRESSION);
+ public function setCompressionLevel($compressionLevel = ZipFile::LEVEL_DEFAULT_COMPRESSION);
/**
* @return int
diff --git a/src/PhpZip/Model/ZipInfo.php b/src/PhpZip/Model/ZipInfo.php
index 19b90fa..0e959b2 100644
--- a/src/PhpZip/Model/ZipInfo.php
+++ b/src/PhpZip/Model/ZipInfo.php
@@ -6,7 +6,7 @@ use PhpZip\Exception\ZipException;
use PhpZip\Extra\Fields\NtfsExtraField;
use PhpZip\Extra\Fields\WinZipAesEntryExtraField;
use PhpZip\Util\FilesUtil;
-use PhpZip\ZipFileInterface;
+use PhpZip\ZipFile;
/**
* Zip info.
@@ -132,7 +132,7 @@ class ZipInfo
private static $valuesCompressionMethod = [
ZipEntry::UNKNOWN => 'unknown',
- ZipFileInterface::METHOD_STORED => 'no compression',
+ ZipFile::METHOD_STORED => 'no compression',
1 => 'shrink',
2 => 'reduce level 1',
3 => 'reduce level 2',
@@ -140,7 +140,7 @@ class ZipInfo
5 => 'reduce level 4',
6 => 'implode',
7 => 'reserved for Tokenizing compression algorithm',
- ZipFileInterface::METHOD_DEFLATED => 'deflate',
+ ZipFile::METHOD_DEFLATED => 'deflate',
9 => 'deflate64',
10 => 'PKWARE Data Compression Library Imploding (old IBM TERSE)',
11 => 'reserved by PKWARE',
@@ -252,10 +252,10 @@ class ZipInfo
$attributes = str_repeat(' ', 12);
$externalAttributes = $entry->getExternalAttributes();
$xattr = (($externalAttributes >> 16) & 0xFFFF);
- switch ($entry->getPlatform()) {
+ switch ($entry->getCreatedOS()) {
case self::MADE_BY_MS_DOS:
case self::MADE_BY_WINDOWS_NTFS:
- if ($entry->getPlatform() !== self::MADE_BY_MS_DOS ||
+ if ($entry->getCreatedOS() !== self::MADE_BY_MS_DOS ||
($xattr & self::UNX_IRWXU) !==
(self::UNX_IRUSR |
(!($externalAttributes & 1) << 7) |
@@ -420,8 +420,8 @@ class ZipInfo
*/
public static function getPlatformName(ZipEntry $entry)
{
- if (isset(self::$valuesMadeBy[$entry->getPlatform()])) {
- return self::$valuesMadeBy[$entry->getPlatform()];
+ if (isset(self::$valuesMadeBy[$entry->getCreatedOS()])) {
+ return self::$valuesMadeBy[$entry->getCreatedOS()];
}
return 'unknown';
diff --git a/src/PhpZip/Model/ZipModel.php b/src/PhpZip/Model/ZipModel.php
index 39fb999..7e5b0af 100644
--- a/src/PhpZip/Model/ZipModel.php
+++ b/src/PhpZip/Model/ZipModel.php
@@ -7,7 +7,7 @@ use PhpZip\Exception\ZipEntryNotFoundException;
use PhpZip\Exception\ZipException;
use PhpZip\Model\Entry\ZipChangesEntry;
use PhpZip\Model\Entry\ZipSourceEntry;
-use PhpZip\ZipFileInterface;
+use PhpZip\ZipFile;
/**
* Zip Model.
@@ -203,8 +203,8 @@ class ZipModel implements \Countable
/**
* @param string|ZipEntry $entry
*
- * @throws ZipException
* @throws ZipEntryNotFoundException
+ * @throws ZipException
*
* @return ZipChangesEntry|ZipEntry
*/
@@ -352,7 +352,7 @@ class ZipModel implements \Countable
/**
* @param int $encryptionMethod
*/
- public function setEncryptionMethod($encryptionMethod = ZipFileInterface::ENCRYPTION_METHOD_WINZIP_AES_256)
+ public function setEncryptionMethod($encryptionMethod = ZipFile::ENCRYPTION_METHOD_WINZIP_AES_256)
{
$this->matcher()->all()->setEncryptionMethod($encryptionMethod);
}
diff --git a/src/PhpZip/Stream/ZipInputStream.php b/src/PhpZip/Stream/ZipInputStream.php
index 1f42647..6d1779d 100644
--- a/src/PhpZip/Stream/ZipInputStream.php
+++ b/src/PhpZip/Stream/ZipInputStream.php
@@ -14,15 +14,13 @@ use PhpZip\Extra\ExtraFieldsCollection;
use PhpZip\Extra\ExtraFieldsFactory;
use PhpZip\Extra\Fields\ApkAlignmentExtraField;
use PhpZip\Extra\Fields\WinZipAesEntryExtraField;
-use PhpZip\Mapper\OffsetPositionMapper;
-use PhpZip\Mapper\PositionMapper;
use PhpZip\Model\EndOfCentralDirectory;
use PhpZip\Model\Entry\ZipSourceEntry;
use PhpZip\Model\ZipEntry;
use PhpZip\Model\ZipModel;
use PhpZip\Util\PackUtil;
use PhpZip\Util\StringUtil;
-use PhpZip\ZipFileInterface;
+use PhpZip\ZipFile;
/**
* Read zip file.
@@ -35,15 +33,6 @@ class ZipInputStream implements ZipInputStreamInterface
/** @var resource */
protected $in;
- /** @var PositionMapper */
- protected $mapper;
-
- /** @var int the number of bytes in the preamble of this ZIP file */
- protected $preamble = 0;
-
- /** @var int the number of bytes in the postamble of this ZIP file */
- protected $postamble = 0;
-
/** @var ZipModel */
protected $zipModel;
@@ -58,7 +47,6 @@ class ZipInputStream implements ZipInputStreamInterface
throw new RuntimeException('$in must be resource');
}
$this->in = $in;
- $this->mapper = new PositionMapper();
}
/**
@@ -95,8 +83,8 @@ class ZipInputStream implements ZipInputStreamInterface
if (
$signature !== ZipEntry::LOCAL_FILE_HEADER_SIG
- && $signature !== EndOfCentralDirectory::ZIP64_END_OF_CENTRAL_DIRECTORY_RECORD_SIG
- && $signature !== EndOfCentralDirectory::END_OF_CENTRAL_DIRECTORY_RECORD_SIG
+ && $signature !== EndOfCentralDirectory::ZIP64_END_OF_CD_RECORD_SIG
+ && $signature !== EndOfCentralDirectory::END_OF_CD_SIG
) {
throw new ZipException(
'Expected Local File Header or (ZIP64) End Of Central Directory Record! Signature: ' . $signature
@@ -111,145 +99,179 @@ class ZipInputStream implements ZipInputStreamInterface
*/
protected function readEndOfCentralDirectory()
{
+ if (!$this->findEndOfCentralDirectory()) {
+ throw new ZipException('Invalid zip file. The end of the central directory could not be found.');
+ }
+
+ $positionECD = ftell($this->in) - 4;
+ $buffer = fread($this->in, fstat($this->in)['size'] - $positionECD);
+
+ $unpack = unpack(
+ 'vdiskNo/vcdDiskNo/vcdEntriesDisk/' .
+ 'vcdEntries/VcdSize/VcdPos/vcommentLength',
+ substr($buffer, 0, 18)
+ );
+
+ if (
+ $unpack['diskNo'] !== 0 ||
+ $unpack['cdDiskNo'] !== 0 ||
+ $unpack['cdEntriesDisk'] !== $unpack['cdEntries']
+ ) {
+ throw new ZipException(
+ 'ZIP file spanning/splitting is not supported!'
+ );
+ }
+ // .ZIP file comment (variable sizeECD)
$comment = null;
- // Search for End of central directory record.
- $stats = fstat($this->in);
- $size = $stats['size'];
- $max = $size - EndOfCentralDirectory::END_OF_CENTRAL_DIRECTORY_RECORD_MIN_LEN;
+
+ if ($unpack['commentLength'] > 0) {
+ $comment = substr($buffer, 18, $unpack['commentLength']);
+ }
+
+ // Check for ZIP64 End Of Central Directory Locator exists.
+ $zip64ECDLocatorPosition = $positionECD - EndOfCentralDirectory::ZIP64_END_OF_CD_LOCATOR_LEN;
+ fseek($this->in, $zip64ECDLocatorPosition);
+ // zip64 end of central dir locator
+ // signature 4 bytes (0x07064b50)
+ if ($zip64ECDLocatorPosition > 0 && unpack(
+ 'V',
+ fread($this->in, 4)
+ )[1] === EndOfCentralDirectory::ZIP64_END_OF_CD_LOCATOR_SIG) {
+ $positionECD = $this->findZip64ECDPosition();
+ $endCentralDirectory = $this->readZip64EndOfCentralDirectory($positionECD);
+ $endCentralDirectory->setComment($comment);
+ } else {
+ $endCentralDirectory = new EndOfCentralDirectory(
+ $unpack['cdEntries'],
+ $unpack['cdPos'],
+ $unpack['cdSize'],
+ false,
+ $comment
+ );
+ }
+
+ return $endCentralDirectory;
+ }
+
+ /**
+ * @throws ZipException
+ *
+ * @return bool
+ */
+ protected function findEndOfCentralDirectory()
+ {
+ $max = fstat($this->in)['size'] - EndOfCentralDirectory::END_OF_CENTRAL_DIRECTORY_RECORD_MIN_LEN;
+
+ if ($max < 0) {
+ throw new ZipException('Too short to be a zip file');
+ }
$min = $max >= 0xffff ? $max - 0xffff : 0;
- for ($endOfCentralDirRecordPos = $max; $endOfCentralDirRecordPos >= $min; $endOfCentralDirRecordPos--) {
- fseek($this->in, $endOfCentralDirRecordPos, \SEEK_SET);
+ // Search for End of central directory record.
+ for ($position = $max; $position >= $min; $position--) {
+ fseek($this->in, $position);
// end of central dir signature 4 bytes (0x06054b50)
- if (unpack('V', fread($this->in, 4))[1] !== EndOfCentralDirectory::END_OF_CENTRAL_DIRECTORY_RECORD_SIG) {
+ if (unpack('V', fread($this->in, 4))[1] !== EndOfCentralDirectory::END_OF_CD_SIG) {
continue;
}
- // number of this disk - 2 bytes
- // number of the disk with the start of the
- // central directory - 2 bytes
- // total number of entries in the central
- // directory on this disk - 2 bytes
- // total number of entries in the central
- // directory - 2 bytes
- // size of the central directory - 4 bytes
- // offset of start of central directory with
- // respect to the starting disk number - 4 bytes
- // ZIP file comment length - 2 bytes
- $data = unpack(
- 'vdiskNo/vcdDiskNo/vcdEntriesDisk/vcdEntries/VcdSize/VcdPos/vcommentLength',
- fread($this->in, 18)
- );
-
- if ($data['diskNo'] !== 0 || $data['cdDiskNo'] !== 0 || $data['cdEntriesDisk'] !== $data['cdEntries']) {
- throw new ZipException(
- 'ZIP file spanning/splitting is not supported!'
- );
- }
- // .ZIP file comment (variable size)
- if ($data['commentLength'] > 0) {
- $comment = '';
- $offset = 0;
-
- while ($offset < $data['commentLength']) {
- $read = min(8192 /* chunk size */, $data['commentLength'] - $offset);
- $comment .= fread($this->in, $read);
- $offset += $read;
- }
- }
- $this->preamble = $endOfCentralDirRecordPos;
- $this->postamble = $size - ftell($this->in);
-
- // Check for ZIP64 End Of Central Directory Locator.
- $endOfCentralDirLocatorPos = $endOfCentralDirRecordPos - EndOfCentralDirectory::ZIP64_END_OF_CENTRAL_DIRECTORY_LOCATOR_LEN;
-
- fseek($this->in, $endOfCentralDirLocatorPos, \SEEK_SET);
- // zip64 end of central dir locator
- // signature 4 bytes (0x07064b50)
- if (
- $endOfCentralDirLocatorPos < 0 ||
- ftell($this->in) === $size ||
- unpack(
- 'V',
- fread($this->in, 4)
- )[1] !== EndOfCentralDirectory::ZIP64_END_OF_CENTRAL_DIRECTORY_LOCATOR_SIG
- ) {
- // Seek and check first CFH, probably requiring an offset mapper.
- $offset = $endOfCentralDirRecordPos - $data['cdSize'];
- fseek($this->in, $offset, \SEEK_SET);
- $offset -= $data['cdPos'];
-
- if ($offset !== 0) {
- $this->mapper = new OffsetPositionMapper($offset);
- }
- $entryCount = $data['cdEntries'];
-
- return new EndOfCentralDirectory($entryCount, $comment);
- }
-
- // number of the disk with the
- // start of the zip64 end of
- // central directory 4 bytes
- $zip64EndOfCentralDirectoryRecordDisk = unpack('V', fread($this->in, 4))[1];
- // relative offset of the zip64
- // end of central directory record 8 bytes
- $zip64EndOfCentralDirectoryRecordPos = PackUtil::unpackLongLE(fread($this->in, 8));
- // total number of disks 4 bytes
- $totalDisks = unpack('V', fread($this->in, 4))[1];
-
- if ($zip64EndOfCentralDirectoryRecordDisk !== 0 || $totalDisks !== 1) {
- throw new ZipException('ZIP file spanning/splitting is not supported!');
- }
- fseek($this->in, $zip64EndOfCentralDirectoryRecordPos, \SEEK_SET);
- // zip64 end of central dir
- // signature 4 bytes (0x06064b50)
- $zip64EndOfCentralDirSig = unpack('V', fread($this->in, 4))[1];
-
- if ($zip64EndOfCentralDirSig !== EndOfCentralDirectory::ZIP64_END_OF_CENTRAL_DIRECTORY_RECORD_SIG) {
- throw new ZipException('Expected ZIP64 End Of Central Directory Record!');
- }
- // size of zip64 end of central
- // directory record 8 bytes
- // version made by 2 bytes
- // version needed to extract 2 bytes
- fseek($this->in, 12, \SEEK_CUR);
- // number of this disk 4 bytes
- $diskNo = unpack('V', fread($this->in, 4))[1];
- // number of the disk with the
- // start of the central directory 4 bytes
- $cdDiskNo = unpack('V', fread($this->in, 4))[1];
- // total number of entries in the
- // central directory on this disk 8 bytes
- $cdEntriesDisk = PackUtil::unpackLongLE(fread($this->in, 8));
- // total number of entries in the
- // central directory 8 bytes
- $cdEntries = PackUtil::unpackLongLE(fread($this->in, 8));
-
- if ($diskNo !== 0 || $cdDiskNo !== 0 || $cdEntriesDisk !== $cdEntries) {
- throw new ZipException('ZIP file spanning/splitting is not supported!');
- }
-
- if ($cdEntries < 0 || $cdEntries > 0x7fffffff) {
- throw new ZipException('Total Number Of Entries In The Central Directory out of range!');
- }
- // size of the central directory 8 bytes
- fseek($this->in, 8, \SEEK_CUR);
- // offset of start of central
- // directory with respect to
- // the starting disk number 8 bytes
- $cdPos = PackUtil::unpackLongLE(fread($this->in, 8));
- // zip64 extensible data sector (variable size)
- fseek($this->in, $cdPos, \SEEK_SET);
- $this->preamble = $zip64EndOfCentralDirectoryRecordPos;
- $entryCount = $cdEntries;
- $zip64 = true;
-
- return new EndOfCentralDirectory($entryCount, $comment, $zip64);
+ return true;
}
- // Start recovering file entries from min.
- $this->preamble = $min;
- $this->postamble = $size - $min;
- return new EndOfCentralDirectory(0, $comment);
+ return false;
+ }
+
+ /**
+ * Read Zip64 end of central directory locator and returns
+ * Zip64 end of central directory position.
+ *
+ * number of the disk with the
+ * start of the zip64 end of
+ * central directory 4 bytes
+ * relative offset of the zip64
+ * end of central directory record 8 bytes
+ * total number of disks 4 bytes
+ *
+ * @throws ZipException
+ *
+ * @return int Zip64 End Of Central Directory position
+ */
+ protected function findZip64ECDPosition()
+ {
+ $diskNo = unpack('V', fread($this->in, 4))[1];
+ $zip64ECDPos = PackUtil::unpackLongLE(fread($this->in, 8));
+ $totalDisks = unpack('V', fread($this->in, 4))[1];
+
+ if ($diskNo !== 0 || $totalDisks > 1) {
+ throw new ZipException('ZIP file spanning/splitting is not supported!');
+ }
+
+ return $zip64ECDPos;
+ }
+
+ /**
+ * Read zip64 end of central directory locator and zip64 end
+ * of central directory record.
+ *
+ * zip64 end of central dir
+ * signature 4 bytes (0x06064b50)
+ * size of zip64 end of central
+ * directory record 8 bytes
+ * version made by 2 bytes
+ * version needed to extract 2 bytes
+ * number of this disk 4 bytes
+ * number of the disk with the
+ * start of the central directory 4 bytes
+ * total number of entries in the
+ * central directory on this disk 8 bytes
+ * total number of entries in the
+ * central directory 8 bytes
+ * size of the central directory 8 bytes
+ * offset of start of central
+ * directory with respect to
+ * the starting disk number 8 bytes
+ * zip64 extensible data sector (variable size)
+ *
+ * @param int $zip64ECDPosition
+ *
+ * @throws ZipException
+ *
+ * @return EndOfCentralDirectory
+ */
+ protected function readZip64EndOfCentralDirectory($zip64ECDPosition)
+ {
+ fseek($this->in, $zip64ECDPosition);
+
+ $buffer = fread($this->in, 56 /* zip64 end of cd rec length */);
+
+ if (unpack('V', $buffer)[1] !== EndOfCentralDirectory::ZIP64_END_OF_CD_RECORD_SIG) {
+ throw new ZipException('Expected ZIP64 End Of Central Directory Record!');
+ }
+
+ $data = unpack(
+ 'VdiskNo/VcdDiskNo',
+ substr($buffer, 16)
+ );
+ $cdEntriesDisk = PackUtil::unpackLongLE(substr($buffer, 24, 8));
+ $entryCount = PackUtil::unpackLongLE(substr($buffer, 32, 8));
+ $cdSize = PackUtil::unpackLongLE(substr($buffer, 40, 8));
+ $cdPos = PackUtil::unpackLongLE(substr($buffer, 48, 8));
+
+ if ($data['diskNo'] !== 0 || $data['cdDiskNo'] !== 0 || $entryCount !== $cdEntriesDisk) {
+ throw new ZipException('ZIP file spanning/splitting is not supported!');
+ }
+
+ if ($entryCount < 0 || $entryCount > 0x7fffffff) {
+ throw new ZipException('Total Number Of Entries In The Central Directory out of range!');
+ }
+
+ // skip zip64 extensible data sector (variable sizeEndCD)
+
+ return new EndOfCentralDirectory(
+ $entryCount,
+ $cdPos,
+ $cdSize,
+ true
+ );
}
/**
@@ -268,122 +290,108 @@ class ZipInputStream implements ZipInputStreamInterface
*/
protected function mountCentralDirectory(EndOfCentralDirectory $endOfCentralDirectory)
{
- $numEntries = $endOfCentralDirectory->getEntryCount();
$entries = [];
- for (; $numEntries > 0; $numEntries--) {
- $entry = $this->readEntry();
- // Re-load virtual offset after ZIP64 Extended Information
- // Extra Field may have been parsed, map it to the real
- // offset and conditionally update the preamble size from it.
- $lfhOff = $this->mapper->map($entry->getOffset());
+ fseek($this->in, $endOfCentralDirectory->getCdOffset());
- if ($lfhOff < $this->preamble) {
- $this->preamble = $lfhOff;
- }
+ if (!($cdStream = fopen('php://temp', 'w+b'))) {
+ throw new ZipException('Temp resource can not open from write');
+ }
+ stream_copy_to_stream($this->in, $cdStream, $endOfCentralDirectory->getCdSize());
+ rewind($cdStream);
+ for ($numEntries = $endOfCentralDirectory->getEntryCount(); $numEntries > 0; $numEntries--) {
+ $entry = $this->readCentralDirectoryEntry($cdStream);
$entries[$entry->getName()] = $entry;
}
-
- if (($numEntries % 0x10000) !== 0) {
- throw new ZipException(
- 'Expected ' . abs($numEntries) .
- ($numEntries > 0 ? ' more' : ' less') .
- ' entries in the Central Directory!'
- );
- }
-
- if ($this->preamble + $this->postamble >= fstat($this->in)['size']) {
- $this->checkZipFileSignature();
- }
+ fclose($cdStream);
return $entries;
}
/**
+ * Read central directory entry.
+ *
+ * central file header signature 4 bytes (0x02014b50)
+ * version made by 2 bytes
+ * version needed to extract 2 bytes
+ * general purpose bit flag 2 bytes
+ * compression method 2 bytes
+ * last mod file time 2 bytes
+ * last mod file date 2 bytes
+ * crc-32 4 bytes
+ * compressed size 4 bytes
+ * uncompressed size 4 bytes
+ * file name length 2 bytes
+ * extra field length 2 bytes
+ * file comment length 2 bytes
+ * disk number start 2 bytes
+ * internal file attributes 2 bytes
+ * external file attributes 4 bytes
+ * relative offset of local header 4 bytes
+ *
+ * file name (variable size)
+ * extra field (variable size)
+ * file comment (variable size)
+ *
+ * @param resource $stream
+ *
* @throws ZipException
*
* @return ZipEntry
*/
- public function readEntry()
+ public function readCentralDirectoryEntry($stream)
{
- // central file header signature 4 bytes (0x02014b50)
- $fileHeaderSig = unpack('V', fread($this->in, 4))[1];
-
- if ($fileHeaderSig !== ZipOutputStreamInterface::CENTRAL_FILE_HEADER_SIG) {
- throw new InvalidArgumentException('Corrupt zip file. Can not read zip entry.');
+ if (unpack('V', fread($stream, 4))[1] !== ZipOutputStreamInterface::CENTRAL_FILE_HEADER_SIG) {
+ throw new ZipException('Corrupt zip file. Cannot read central dir entry.');
}
- // version made by 2 bytes
- // version needed to extract 2 bytes
- // general purpose bit flag 2 bytes
- // compression method 2 bytes
- // last mod file time 2 bytes
- // last mod file date 2 bytes
- // crc-32 4 bytes
- // compressed size 4 bytes
- // uncompressed size 4 bytes
- // file name length 2 bytes
- // extra field length 2 bytes
- // file comment length 2 bytes
- // disk number start 2 bytes
- // internal file attributes 2 bytes
- // external file attributes 4 bytes
- // relative offset of local header 4 bytes
$data = unpack(
- 'vversionMadeBy/vversionNeededToExtract/vgpbf/' .
- 'vrawMethod/VrawTime/VrawCrc/VrawCompressedSize/' .
- 'VrawSize/vfileLength/vextraLength/vcommentLength/' .
- 'VrawInternalAttributes/VrawExternalAttributes/VlfhOff',
- fread($this->in, 42)
+ 'vversionMadeBy/vversionNeededToExtract/' .
+ 'vgeneralPurposeBitFlag/vcompressionMethod/' .
+ 'VlastModFile/Vcrc/VcompressedSize/' .
+ 'VuncompressedSize/vfileNameLength/vextraFieldLength/' .
+ 'vfileCommentLength/vdiskNumberStart/vinternalFileAttributes/' .
+ 'VexternalFileAttributes/VoffsetLocalHeader',
+ fread($stream, 42)
);
-// $utf8 = ($data['gpbf'] & ZipEntry::GPBF_UTF8) !== 0;
+ $createdOS = ($data['versionMadeBy'] & 0xFF00) >> 8;
+ $softwareVersion = $data['versionMadeBy'] & 0x00FF;
- // See appendix D of PKWARE's ZIP File Format Specification.
- $name = '';
- $offset = 0;
+ $extractOS = ($data['versionNeededToExtract'] & 0xFF00) >> 8;
+ $extractVersion = $data['versionNeededToExtract'] & 0x00FF;
- while ($offset < $data['fileLength']) {
- $read = min(8192 /* chunk size */, $data['fileLength'] - $offset);
- $name .= fread($this->in, $read);
- $offset += $read;
+ $name = fread($stream, $data['fileNameLength']);
+
+ $extra = '';
+
+ if ($data['extraFieldLength'] > 0) {
+ $extra = fread($stream, $data['extraFieldLength']);
+ }
+
+ $comment = null;
+
+ if ($data['fileCommentLength'] > 0) {
+ $comment = fread($stream, $data['fileCommentLength']);
}
$entry = new ZipSourceEntry($this);
$entry->setName($name);
- $entry->setVersionNeededToExtract($data['versionNeededToExtract']);
- $entry->setPlatform($data['versionMadeBy'] >> 8);
- $entry->setMethod($data['rawMethod']);
- $entry->setGeneralPurposeBitFlags($data['gpbf']);
- $entry->setDosTime($data['rawTime']);
- $entry->setCrc($data['rawCrc']);
- $entry->setCompressedSize($data['rawCompressedSize']);
- $entry->setSize($data['rawSize']);
- $entry->setExternalAttributes($data['rawExternalAttributes']);
- $entry->setOffset($data['lfhOff']); // must be unmapped!
- if ($data['extraLength'] > 0) {
- $extra = '';
- $offset = 0;
-
- while ($offset < $data['extraLength']) {
- $read = min(8192 /* chunk size */, $data['extraLength'] - $offset);
- $extra .= fread($this->in, $read);
- $offset += $read;
- }
- $entry->setExtra($extra);
- }
-
- if ($data['commentLength'] > 0) {
- $comment = '';
- $offset = 0;
-
- while ($offset < $data['commentLength']) {
- $read = min(8192 /* chunk size */, $data['commentLength'] - $offset);
- $comment .= fread($this->in, $read);
- $offset += $read;
- }
- $entry->setComment($comment);
- }
+ $entry->setCreatedOS($createdOS);
+ $entry->setSoftwareVersion($softwareVersion);
+ $entry->setVersionNeededToExtract($extractVersion);
+ $entry->setExtractedOS($extractOS);
+ $entry->setMethod($data['compressionMethod']);
+ $entry->setGeneralPurposeBitFlags($data['generalPurposeBitFlag']);
+ $entry->setDosTime($data['lastModFile']);
+ $entry->setCrc($data['crc']);
+ $entry->setCompressedSize($data['compressedSize']);
+ $entry->setSize($data['uncompressedSize']);
+ $entry->setInternalAttributes($data['internalFileAttributes']);
+ $entry->setExternalAttributes($data['externalFileAttributes']);
+ $entry->setOffset($data['offsetLocalHeader']);
+ $entry->setComment($comment);
+ $entry->setExtra($extra);
return $entry;
}
@@ -410,9 +418,8 @@ class ZipInputStream implements ZipInputStreamInterface
throw new ZipException('Can not password from entry ' . $entry->getName());
}
- $pos = $entry->getOffset();
+ $startPos = $pos = $entry->getOffset();
- $startPos = $pos = $this->mapper->map($pos);
fseek($this->in, $startPos);
// local file header signature 4 bytes (0x04034b50)
@@ -465,7 +472,7 @@ class ZipInputStream implements ZipInputStreamInterface
// Traditional PKWARE Decryption
$zipCryptoEngine = new TraditionalPkwareEncryptionEngine($entry);
$content = $zipCryptoEngine->decrypt($content);
- $entry->setEncryptionMethod(ZipFileInterface::ENCRYPTION_METHOD_TRADITIONAL);
+ $entry->setEncryptionMethod(ZipFile::ENCRYPTION_METHOD_TRADITIONAL);
}
if (!$skipCheckCrc) {
@@ -500,15 +507,15 @@ class ZipInputStream implements ZipInputStreamInterface
}
switch ($method) {
- case ZipFileInterface::METHOD_STORED:
+ case ZipFile::METHOD_STORED:
break;
- case ZipFileInterface::METHOD_DEFLATED:
+ case ZipFile::METHOD_DEFLATED:
/** @noinspection PhpUsageOfSilenceOperatorInspection */
$content = @gzinflate($content);
break;
- case ZipFileInterface::METHOD_BZIP2:
+ case ZipFile::METHOD_BZIP2:
if (!\extension_loaded('bz2')) {
throw new ZipException('Extension bzip2 not install');
}
@@ -589,8 +596,6 @@ class ZipInputStream implements ZipInputStreamInterface
throw new ZipException(sprintf('Missing local header offset for entry %s', $entry->getName()));
}
- $pos = $this->mapper->map($pos);
-
$nameLength = \strlen($entry->getName());
fseek($this->in, $pos + ZipEntry::LOCAL_FILE_HEADER_MIN_LEN - 2, \SEEK_SET);
@@ -625,7 +630,7 @@ class ZipInputStream implements ZipInputStreamInterface
if (
$this->zipModel->isZipAlign() &&
!$entry->isEncrypted() &&
- $entry->getMethod() === ZipFileInterface::METHOD_STORED
+ $entry->getMethod() === ZipFile::METHOD_STORED
) {
if (StringUtil::endsWith($entry->getName(), '.so')) {
$dataAlignmentMultiple = ApkAlignmentExtraField::ANDROID_COMMON_PAGE_ALIGNMENT_BYTES;
@@ -688,7 +693,6 @@ class ZipInputStream implements ZipInputStreamInterface
public function copyEntryData(ZipEntry $entry, ZipOutputStreamInterface $out)
{
$offset = $entry->getOffset();
- $offset = $this->mapper->map($offset);
$nameLength = \strlen($entry->getName());
fseek($this->in, $offset + ZipEntry::LOCAL_FILE_HEADER_MIN_LEN - 2, \SEEK_SET);
diff --git a/src/PhpZip/Stream/ZipInputStreamInterface.php b/src/PhpZip/Stream/ZipInputStreamInterface.php
index 5c21091..e4f2c9c 100644
--- a/src/PhpZip/Stream/ZipInputStreamInterface.php
+++ b/src/PhpZip/Stream/ZipInputStreamInterface.php
@@ -20,9 +20,15 @@ interface ZipInputStreamInterface
public function readZip();
/**
+ * Read central directory entry.
+ *
+ * @param resource $stream
+ *
+ * @throws ZipException
+ *
* @return ZipEntry
*/
- public function readEntry();
+ public function readCentralDirectoryEntry($stream);
/**
* @param ZipEntry $entry
diff --git a/src/PhpZip/Stream/ZipOutputStream.php b/src/PhpZip/Stream/ZipOutputStream.php
index 897b5d1..ae36c2b 100644
--- a/src/PhpZip/Stream/ZipOutputStream.php
+++ b/src/PhpZip/Stream/ZipOutputStream.php
@@ -19,7 +19,7 @@ use PhpZip\Model\ZipEntry;
use PhpZip\Model\ZipModel;
use PhpZip\Util\PackUtil;
use PhpZip\Util\StringUtil;
-use PhpZip\ZipFileInterface;
+use PhpZip\ZipFile;
/**
* Write zip file.
@@ -97,7 +97,7 @@ class ZipOutputStream implements ZipOutputStreamInterface
if (
$this->zipModel->isZipAlign() &&
!$entry->isEncrypted() &&
- $entry->getMethod() === ZipFileInterface::METHOD_STORED
+ $entry->getMethod() === ZipFile::METHOD_STORED
) {
$dataAlignmentMultiple = $this->zipModel->getZipAlign();
@@ -144,7 +144,7 @@ class ZipOutputStream implements ZipOutputStreamInterface
// local file header signature 4 bytes (0x04034b50)
ZipEntry::LOCAL_FILE_HEADER_SIG,
// version needed to extract 2 bytes
- $entry->getVersionNeededToExtract(),
+ ($entry->getExtractedOS() << 8) | $entry->getVersionNeededToExtract(),
// general purpose bit flag 2 bytes
$entry->getGeneralPurposeBitFlags(),
// compression method 2 bytes
@@ -221,8 +221,12 @@ class ZipOutputStream implements ZipOutputStreamInterface
*/
protected function entryCommitChangesAndReturnContent(ZipEntry $entry)
{
- if ($entry->getPlatform() === ZipEntry::UNKNOWN) {
- $entry->setPlatform(ZipEntry::PLATFORM_UNIX);
+ if ($entry->getCreatedOS() === ZipEntry::UNKNOWN) {
+ $entry->setCreatedOS(ZipEntry::PLATFORM_UNIX);
+ }
+
+ if ($entry->getExtractedOS() === ZipEntry::UNKNOWN) {
+ $entry->setExtractedOS(ZipEntry::PLATFORM_UNIX);
}
if ($entry->getTime() === ZipEntry::UNKNOWN) {
@@ -265,16 +269,15 @@ class ZipOutputStream implements ZipOutputStreamInterface
}
switch ($method) {
- case ZipFileInterface::METHOD_STORED:
+ case ZipFile::METHOD_STORED:
break;
- case ZipFileInterface::METHOD_DEFLATED:
+ case ZipFile::METHOD_DEFLATED:
$entryContent = gzdeflate($entryContent, $entry->getCompressionLevel());
break;
- case ZipFileInterface::METHOD_BZIP2:
- $compressionLevel = $entry->getCompressionLevel(
- ) === ZipFileInterface::LEVEL_DEFAULT_COMPRESSION ?
+ case ZipFile::METHOD_BZIP2:
+ $compressionLevel = $entry->getCompressionLevel() === ZipFile::LEVEL_DEFAULT_COMPRESSION ?
ZipEntry::LEVEL_DEFAULT_BZIP2_COMPRESSION :
$entry->getCompressionLevel();
/** @noinspection PhpComposerExtensionStubsInspection */
@@ -294,19 +297,19 @@ class ZipOutputStream implements ZipOutputStreamInterface
throw new ZipException($entry->getName() . ' (unsupported compression method ' . $method . ')');
}
- if ($method === ZipFileInterface::METHOD_DEFLATED) {
+ if ($method === ZipFile::METHOD_DEFLATED) {
$bit1 = false;
$bit2 = false;
switch ($entry->getCompressionLevel()) {
- case ZipFileInterface::LEVEL_BEST_COMPRESSION:
+ case ZipFile::LEVEL_BEST_COMPRESSION:
$bit1 = true;
break;
- case ZipFileInterface::LEVEL_FAST:
+ case ZipFile::LEVEL_FAST:
$bit2 = true;
break;
- case ZipFileInterface::LEVEL_SUPER_FAST:
+ case ZipFile::LEVEL_SUPER_FAST:
$bit1 = true;
$bit2 = true;
break;
@@ -320,9 +323,9 @@ class ZipOutputStream implements ZipOutputStreamInterface
if (\in_array(
$entry->getEncryptionMethod(),
[
- ZipFileInterface::ENCRYPTION_METHOD_WINZIP_AES_128,
- ZipFileInterface::ENCRYPTION_METHOD_WINZIP_AES_192,
- ZipFileInterface::ENCRYPTION_METHOD_WINZIP_AES_256,
+ ZipFile::ENCRYPTION_METHOD_WINZIP_AES_128,
+ ZipFile::ENCRYPTION_METHOD_WINZIP_AES_192,
+ ZipFile::ENCRYPTION_METHOD_WINZIP_AES_256,
],
true
)) {
@@ -334,7 +337,7 @@ class ZipOutputStream implements ZipOutputStreamInterface
$field->setMethod($method);
$size = $entry->getSize();
- if ($size >= 20 && $method !== ZipFileInterface::METHOD_BZIP2) {
+ if ($size >= 20 && $method !== ZipFile::METHOD_BZIP2) {
$field->setVendorVersion(WinZipAesEntryExtraField::VV_AE_1);
} else {
$field->setVendorVersion(WinZipAesEntryExtraField::VV_AE_2);
@@ -345,7 +348,7 @@ class ZipOutputStream implements ZipOutputStreamInterface
$winZipAesEngine = new WinZipAesEngine($entry);
$entryContent = $winZipAesEngine->encrypt($entryContent);
- } elseif ($entry->getEncryptionMethod() === ZipFileInterface::ENCRYPTION_METHOD_TRADITIONAL) {
+ } elseif ($entry->getEncryptionMethod() === ZipFile::ENCRYPTION_METHOD_TRADITIONAL) {
$zipCryptoEngine = new TraditionalPkwareEncryptionEngine($entry);
$entryContent = $zipCryptoEngine->encrypt($entryContent);
}
@@ -382,11 +385,11 @@ class ZipOutputStream implements ZipOutputStreamInterface
$entryContent = gzdeflate($content, $entry->getCompressionLevel());
if (\strlen($entryContent) < \strlen($content)) {
- $entry->setMethod(ZipFileInterface::METHOD_DEFLATED);
+ $entry->setMethod(ZipFile::METHOD_DEFLATED);
return $entryContent;
}
- $entry->setMethod(ZipFileInterface::METHOD_STORED);
+ $entry->setMethod(ZipFile::METHOD_STORED);
}
return $content;
@@ -418,9 +421,9 @@ class ZipOutputStream implements ZipOutputStreamInterface
// central file header signature 4 bytes (0x02014b50)
self::CENTRAL_FILE_HEADER_SIG,
// version made by 2 bytes
- ($entry->getPlatform() << 8) | 63,
+ ($entry->getCreatedOS() << 8) | $entry->getSoftwareVersion(),
// version needed to extract 2 bytes
- $entry->getVersionNeededToExtract(),
+ ($entry->getExtractedOS() << 8) | $entry->getVersionNeededToExtract(),
// general purpose bit flag 2 bytes
$entry->getGeneralPurposeBitFlags(),
// compression method 2 bytes
@@ -442,7 +445,7 @@ class ZipOutputStream implements ZipOutputStreamInterface
// disk number start 2 bytes
0,
// internal file attributes 2 bytes
- 0,
+ $entry->getInternalAttributes(),
// external file attributes 4 bytes
$entry->getExternalAttributes(),
// relative offset of local header 4 bytes
@@ -468,75 +471,99 @@ class ZipOutputStream implements ZipOutputStreamInterface
*/
protected function writeEndOfCentralDirectoryRecord($centralDirectoryOffset)
{
- $centralDirectoryOffset = (int) $centralDirectoryOffset;
- $centralDirectoryEntriesCount = \count($this->zipModel);
+ $cdEntriesCount = \count($this->zipModel);
+
$position = ftell($this->out);
$centralDirectorySize = $position - $centralDirectoryOffset;
- $centralDirectoryEntriesZip64 = $centralDirectoryEntriesCount > 0xffff;
- $centralDirectorySizeZip64 = $centralDirectorySize > 0xffffffff;
- $centralDirectoryOffsetZip64 = $centralDirectoryOffset > 0xffffffff;
- $centralDirectoryEntries16 = $centralDirectoryEntriesZip64 ? 0xffff : $centralDirectoryEntriesCount;
- $centralDirectorySize32 = $centralDirectorySizeZip64 ? 0xffffffff : $centralDirectorySize;
- $centralDirectoryOffset32 = $centralDirectoryOffsetZip64 ? 0xffffffff : $centralDirectoryOffset;
- $zip64 // ZIP64 extensions?
- = $centralDirectoryEntriesZip64
- || $centralDirectorySizeZip64
- || $centralDirectoryOffsetZip64;
- if ($zip64) {
- // [zip64 end of central directory record]
- // relative offset of the zip64 end of central directory record
- $zip64EndOfCentralDirectoryOffset = $position;
- // zip64 end of central dir
+ $cdEntriesZip64 = $cdEntriesCount > 0xFFFF;
+ $cdSizeZip64 = $centralDirectorySize > 0xFFFFFFFF;
+ $cdOffsetZip64 = $centralDirectoryOffset > 0xFFFFFFFF;
+
+ $zip64Required = $cdEntriesZip64 || $cdSizeZip64 || $cdOffsetZip64;
+
+ if ($zip64Required) {
+ $zip64EndOfCentralDirectoryOffset = ftell($this->out);
+
+ // find max software version, version needed to extract and most common platform
+ list($softwareVersion, $versionNeededToExtract) = array_reduce(
+ $this->zipModel->getEntries(),
+ static function (array $carry, ZipEntry $entry) {
+ $carry[0] = max($carry[0], $entry->getSoftwareVersion() & 0xFF);
+ $carry[1] = max($carry[1], $entry->getVersionNeededToExtract() & 0xFF);
+
+ return $carry;
+ },
+ [10 /* simple file min ver */, 45 /* zip64 ext min ver */]
+ );
+
+ $createdOS = $extractedOS = ZipEntry::PLATFORM_FAT;
+ $versionMadeBy = ($createdOS << 8) | max($softwareVersion, 45 /* zip64 ext min ver */);
+ $versionExtractedBy = ($extractedOS << 8) | max($versionNeededToExtract, 45 /* zip64 ext min ver */);
+
// signature 4 bytes (0x06064b50)
- fwrite($this->out, pack('V', EndOfCentralDirectory::ZIP64_END_OF_CENTRAL_DIRECTORY_RECORD_SIG));
+ fwrite($this->out, pack('V', EndOfCentralDirectory::ZIP64_END_OF_CD_RECORD_SIG));
// size of zip64 end of central
// directory record 8 bytes
+ fwrite($this->out, PackUtil::packLongLE(44));
fwrite(
$this->out,
- PackUtil::packLongLE(EndOfCentralDirectory::ZIP64_END_OF_CENTRAL_DIRECTORY_RECORD_MIN_LEN - 12)
+ pack(
+ 'vvVV',
+ // version made by 2 bytes
+ $versionMadeBy & 0xFFFF,
+ // version needed to extract 2 bytes
+ $versionExtractedBy & 0xFFFF,
+ // number of this disk 4 bytes
+ 0,
+ // number of the disk with the
+ // start of the central directory 4 bytes
+ 0
+ )
);
- // version made by 2 bytes
- // version needed to extract 2 bytes
- // due to potential use of BZIP2 compression
- // number of this disk 4 bytes
- // number of the disk with the
- // start of the central directory 4 bytes
- fwrite($this->out, pack('vvVV', 63, 46, 0, 0));
// total number of entries in the
// central directory on this disk 8 bytes
- fwrite($this->out, PackUtil::packLongLE($centralDirectoryEntriesCount));
+ fwrite($this->out, PackUtil::packLongLE($cdEntriesCount));
// total number of entries in the
// central directory 8 bytes
- fwrite($this->out, PackUtil::packLongLE($centralDirectoryEntriesCount));
+ fwrite($this->out, PackUtil::packLongLE($cdEntriesCount));
// size of the central directory 8 bytes
fwrite($this->out, PackUtil::packLongLE($centralDirectorySize));
// offset of start of central
// directory with respect to
// the starting disk number 8 bytes
fwrite($this->out, PackUtil::packLongLE($centralDirectoryOffset));
- // zip64 extensible data sector (variable size)
- // [zip64 end of central directory locator]
- // signature 4 bytes (0x07064b50)
- // number of the disk with the
- // start of the zip64 end of
- // central directory 4 bytes
- fwrite($this->out, pack('VV', EndOfCentralDirectory::ZIP64_END_OF_CENTRAL_DIRECTORY_LOCATOR_SIG, 0));
+ // write zip64 end of central directory locator
+ fwrite(
+ $this->out,
+ pack(
+ 'VV',
+ // zip64 end of central dir locator
+ // signature 4 bytes (0x07064b50)
+ EndOfCentralDirectory::ZIP64_END_OF_CD_LOCATOR_SIG,
+ // number of the disk with the
+ // start of the zip64 end of
+ // central directory 4 bytes
+ 0
+ )
+ );
// relative offset of the zip64
// end of central directory record 8 bytes
fwrite($this->out, PackUtil::packLongLE($zip64EndOfCentralDirectoryOffset));
// total number of disks 4 bytes
fwrite($this->out, pack('V', 1));
}
+
$comment = $this->zipModel->getArchiveComment();
- $commentLength = \strlen($comment);
+ $commentLength = $comment !== null ? \strlen($comment) : 0;
+
fwrite(
$this->out,
pack(
'VvvvvVVv',
// end of central dir signature 4 bytes (0x06054b50)
- EndOfCentralDirectory::END_OF_CENTRAL_DIRECTORY_RECORD_SIG,
+ EndOfCentralDirectory::END_OF_CD_SIG,
// number of this disk 2 bytes
0,
// number of the disk with the
@@ -544,16 +571,16 @@ class ZipOutputStream implements ZipOutputStreamInterface
0,
// total number of entries in the
// central directory on this disk 2 bytes
- $centralDirectoryEntries16,
+ $cdEntriesZip64 ? 0xFFFF : $cdEntriesCount,
// total number of entries in
// the central directory 2 bytes
- $centralDirectoryEntries16,
+ $cdEntriesZip64 ? 0xFFFF : $cdEntriesCount,
// size of the central directory 4 bytes
- $centralDirectorySize32,
+ $cdSizeZip64 ? 0xFFFFFFFF : $centralDirectorySize,
// offset of start of central
// directory with respect to
// the starting disk number 4 bytes
- $centralDirectoryOffset32,
+ $cdOffsetZip64 ? 0xFFFFFFFF : $centralDirectoryOffset,
// .ZIP file comment length 2 bytes
$commentLength
)
diff --git a/src/PhpZip/ZipFile.php b/src/PhpZip/ZipFile.php
index 2a3aba4..52969f9 100644
--- a/src/PhpZip/ZipFile.php
+++ b/src/PhpZip/ZipFile.php
@@ -234,8 +234,8 @@ class ZipFile implements ZipFileInterface
* @param string $entryName
* @param string|null $comment
*
- * @throws ZipEntryNotFoundException
* @throws ZipException
+ * @throws ZipEntryNotFoundException
*
* @return ZipFileInterface
*/
@@ -277,8 +277,8 @@ class ZipFile implements ZipFileInterface
*
* @param string|ZipEntry $entryName
*
- * @throws ZipException
* @throws ZipEntryNotFoundException
+ * @throws ZipException
*
* @return ZipInfo
*/
@@ -398,9 +398,9 @@ class ZipFile implements ZipFileInterface
*
* @return ZipFileInterface
*
- * @see ZipFileInterface::METHOD_STORED
- * @see ZipFileInterface::METHOD_DEFLATED
- * @see ZipFileInterface::METHOD_BZIP2
+ * @see ZipFile::METHOD_STORED
+ * @see ZipFile::METHOD_DEFLATED
+ * @see ZipFile::METHOD_BZIP2
*/
public function addFromString($localName, $contents, $compressionMethod = null)
{
@@ -454,9 +454,9 @@ class ZipFile implements ZipFileInterface
*
* @return ZipFileInterface
*
- * @see ZipFileInterface::METHOD_STORED
- * @see ZipFileInterface::METHOD_DEFLATED
- * @see ZipFileInterface::METHOD_BZIP2
+ * @see ZipFile::METHOD_STORED
+ * @see ZipFile::METHOD_DEFLATED
+ * @see ZipFile::METHOD_BZIP2
*/
public function addFile($filename, $localName = null, $compressionMethod = null)
{
@@ -520,9 +520,9 @@ class ZipFile implements ZipFileInterface
*
* @return ZipFileInterface
*
- * @see ZipFileInterface::METHOD_STORED
- * @see ZipFileInterface::METHOD_DEFLATED
- * @see ZipFileInterface::METHOD_BZIP2
+ * @see ZipFile::METHOD_STORED
+ * @see ZipFile::METHOD_DEFLATED
+ * @see ZipFile::METHOD_BZIP2
*/
public function addFromStream($stream, $localName, $compressionMethod = null)
{
@@ -655,9 +655,9 @@ class ZipFile implements ZipFileInterface
*
* @return ZipFileInterface
*
- * @see ZipFileInterface::METHOD_STORED
- * @see ZipFileInterface::METHOD_DEFLATED
- * @see ZipFileInterface::METHOD_BZIP2
+ * @see ZipFile::METHOD_STORED
+ * @see ZipFile::METHOD_DEFLATED
+ * @see ZipFile::METHOD_BZIP2
*/
public function addDirRecursive($inputDir, $localPath = '/', $compressionMethod = null)
{
@@ -693,9 +693,9 @@ class ZipFile implements ZipFileInterface
*
* @return ZipFileInterface
*
- * @see ZipFileInterface::METHOD_STORED
- * @see ZipFileInterface::METHOD_DEFLATED
- * @see ZipFileInterface::METHOD_BZIP2
+ * @see ZipFile::METHOD_STORED
+ * @see ZipFile::METHOD_DEFLATED
+ * @see ZipFile::METHOD_BZIP2
*/
public function addFilesFromIterator(
\Iterator $iterator,
@@ -1091,10 +1091,10 @@ class ZipFile implements ZipFileInterface
*
* @return ZipFileInterface
*
- * @see ZipFileInterface::LEVEL_DEFAULT_COMPRESSION
- * @see ZipFileInterface::LEVEL_SUPER_FAST
- * @see ZipFileInterface::LEVEL_FAST
- * @see ZipFileInterface::LEVEL_BEST_COMPRESSION
+ * @see ZipFile::LEVEL_DEFAULT_COMPRESSION
+ * @see ZipFile::LEVEL_SUPER_FAST
+ * @see ZipFile::LEVEL_FAST
+ * @see ZipFile::LEVEL_BEST_COMPRESSION
*/
public function setCompressionLevel($compressionLevel = self::LEVEL_DEFAULT_COMPRESSION)
{
@@ -1123,16 +1123,16 @@ class ZipFile implements ZipFileInterface
*
* @return ZipFileInterface
*
- * @see ZipFileInterface::LEVEL_DEFAULT_COMPRESSION
- * @see ZipFileInterface::LEVEL_SUPER_FAST
- * @see ZipFileInterface::LEVEL_FAST
- * @see ZipFileInterface::LEVEL_BEST_COMPRESSION
+ * @see ZipFile::LEVEL_DEFAULT_COMPRESSION
+ * @see ZipFile::LEVEL_SUPER_FAST
+ * @see ZipFile::LEVEL_FAST
+ * @see ZipFile::LEVEL_BEST_COMPRESSION
*/
public function setCompressionLevelEntry($entryName, $compressionLevel)
{
if ($compressionLevel !== null) {
- if ($compressionLevel < ZipFileInterface::LEVEL_DEFAULT_COMPRESSION ||
- $compressionLevel > ZipFileInterface::LEVEL_BEST_COMPRESSION
+ if ($compressionLevel < self::LEVEL_DEFAULT_COMPRESSION ||
+ $compressionLevel > self::LEVEL_BEST_COMPRESSION
) {
throw new InvalidArgumentException(
'Invalid compression level. Minimum level ' .
@@ -1158,9 +1158,9 @@ class ZipFile implements ZipFileInterface
*
* @return ZipFileInterface
*
- * @see ZipFileInterface::METHOD_STORED
- * @see ZipFileInterface::METHOD_DEFLATED
- * @see ZipFileInterface::METHOD_BZIP2
+ * @see ZipFile::METHOD_STORED
+ * @see ZipFile::METHOD_DEFLATED
+ * @see ZipFile::METHOD_BZIP2
*/
public function setCompressionMethodEntry($entryName, $compressionMethod)
{
@@ -1204,7 +1204,7 @@ class ZipFile implements ZipFileInterface
*
* @return ZipFileInterface
*
- * @deprecated using ZipFileInterface::setReadPassword()
+ * @deprecated using ZipFile::setReadPassword()
*/
public function withReadPassword($password)
{
@@ -1254,7 +1254,7 @@ class ZipFile implements ZipFileInterface
*
* @return ZipFileInterface
*
- * @deprecated using ZipFileInterface::setPassword()
+ * @deprecated using ZipFile::setPassword()
*/
public function withNewPassword($password, $encryptionMethod = self::ENCRYPTION_METHOD_WINZIP_AES_256)
{
@@ -1311,7 +1311,7 @@ class ZipFile implements ZipFileInterface
*
* @return ZipFileInterface
*
- * @deprecated using ZipFileInterface::disableEncryption()
+ * @deprecated using ZipFile::disableEncryption()
*/
public function withoutPassword()
{
diff --git a/src/PhpZip/ZipFileInterface.php b/src/PhpZip/ZipFileInterface.php
index b876cc4..c17db22 100644
--- a/src/PhpZip/ZipFileInterface.php
+++ b/src/PhpZip/ZipFileInterface.php
@@ -233,9 +233,9 @@ interface ZipFileInterface extends \Countable, \ArrayAccess, \Iterator
*
* @return ZipFileInterface
*
- * @see ZipFileInterface::METHOD_STORED
- * @see ZipFileInterface::METHOD_DEFLATED
- * @see ZipFileInterface::METHOD_BZIP2
+ * @see ZipFile::METHOD_STORED
+ * @see ZipFile::METHOD_DEFLATED
+ * @see ZipFile::METHOD_BZIP2
*/
public function addFromString($localName, $contents, $compressionMethod = null);
@@ -250,9 +250,9 @@ interface ZipFileInterface extends \Countable, \ArrayAccess, \Iterator
*
* @return ZipFileInterface
*
- * @see ZipFileInterface::METHOD_STORED
- * @see ZipFileInterface::METHOD_DEFLATED
- * @see ZipFileInterface::METHOD_BZIP2
+ * @see ZipFile::METHOD_STORED
+ * @see ZipFile::METHOD_DEFLATED
+ * @see ZipFile::METHOD_BZIP2
*/
public function addFile($filename, $localName = null, $compressionMethod = null);
@@ -267,9 +267,9 @@ interface ZipFileInterface extends \Countable, \ArrayAccess, \Iterator
*
* @return ZipFileInterface
*
- * @see ZipFileInterface::METHOD_STORED
- * @see ZipFileInterface::METHOD_DEFLATED
- * @see ZipFileInterface::METHOD_BZIP2
+ * @see ZipFile::METHOD_STORED
+ * @see ZipFile::METHOD_DEFLATED
+ * @see ZipFile::METHOD_BZIP2
*/
public function addFromStream($stream, $localName, $compressionMethod = null);
@@ -306,9 +306,9 @@ interface ZipFileInterface extends \Countable, \ArrayAccess, \Iterator
*
* @return ZipFileInterface
*
- * @see ZipFileInterface::METHOD_STORED
- * @see ZipFileInterface::METHOD_DEFLATED
- * @see ZipFileInterface::METHOD_BZIP2
+ * @see ZipFile::METHOD_STORED
+ * @see ZipFile::METHOD_DEFLATED
+ * @see ZipFile::METHOD_BZIP2
*/
public function addDirRecursive($inputDir, $localPath = '/', $compressionMethod = null);
@@ -323,9 +323,9 @@ interface ZipFileInterface extends \Countable, \ArrayAccess, \Iterator
*
* @return ZipFileInterface
*
- * @see ZipFileInterface::METHOD_STORED
- * @see ZipFileInterface::METHOD_DEFLATED
- * @see ZipFileInterface::METHOD_BZIP2
+ * @see ZipFile::METHOD_STORED
+ * @see ZipFile::METHOD_DEFLATED
+ * @see ZipFile::METHOD_BZIP2
*/
public function addFilesFromIterator(\Iterator $iterator, $localPath = '/', $compressionMethod = null);
@@ -456,10 +456,10 @@ interface ZipFileInterface extends \Countable, \ArrayAccess, \Iterator
*
* @return ZipFileInterface
*
- * @see ZipFileInterface::LEVEL_SUPER_FAST
- * @see ZipFileInterface::LEVEL_FAST
- * @see ZipFileInterface::LEVEL_BEST_COMPRESSION
- * @see ZipFileInterface::LEVEL_DEFAULT_COMPRESSION
+ * @see ZipFile::LEVEL_SUPER_FAST
+ * @see ZipFile::LEVEL_FAST
+ * @see ZipFile::LEVEL_BEST_COMPRESSION
+ * @see ZipFile::LEVEL_DEFAULT_COMPRESSION
*/
public function setCompressionLevel($compressionLevel = self::LEVEL_DEFAULT_COMPRESSION);
@@ -471,10 +471,10 @@ interface ZipFileInterface extends \Countable, \ArrayAccess, \Iterator
*
* @return ZipFileInterface
*
- * @see ZipFileInterface::LEVEL_DEFAULT_COMPRESSION
- * @see ZipFileInterface::LEVEL_SUPER_FAST
- * @see ZipFileInterface::LEVEL_FAST
- * @see ZipFileInterface::LEVEL_BEST_COMPRESSION
+ * @see ZipFile::LEVEL_DEFAULT_COMPRESSION
+ * @see ZipFile::LEVEL_SUPER_FAST
+ * @see ZipFile::LEVEL_FAST
+ * @see ZipFile::LEVEL_BEST_COMPRESSION
*/
public function setCompressionLevelEntry($entryName, $compressionLevel);
@@ -486,9 +486,9 @@ interface ZipFileInterface extends \Countable, \ArrayAccess, \Iterator
*
* @return ZipFileInterface
*
- * @see ZipFileInterface::METHOD_STORED
- * @see ZipFileInterface::METHOD_DEFLATED
- * @see ZipFileInterface::METHOD_BZIP2
+ * @see ZipFile::METHOD_STORED
+ * @see ZipFile::METHOD_DEFLATED
+ * @see ZipFile::METHOD_BZIP2
*/
public function setCompressionMethodEntry($entryName, $compressionMethod);
@@ -510,7 +510,7 @@ interface ZipFileInterface extends \Countable, \ArrayAccess, \Iterator
*
* @return ZipFileInterface
*
- * @deprecated using ZipFileInterface::setReadPassword()
+ * @deprecated using ZipFile::setReadPassword()
*/
public function withReadPassword($password);
@@ -541,7 +541,7 @@ interface ZipFileInterface extends \Countable, \ArrayAccess, \Iterator
*
* @return ZipFileInterface
*
- * @deprecated using ZipFileInterface::setPassword()
+ * @deprecated using ZipFile::setPassword()
*/
public function withNewPassword($password, $encryptionMethod = self::ENCRYPTION_METHOD_WINZIP_AES_256);
@@ -571,7 +571,7 @@ interface ZipFileInterface extends \Countable, \ArrayAccess, \Iterator
*
* @return ZipFileInterface
*
- * @deprecated using ZipFileInterface::disableEncryption()
+ * @deprecated using ZipFile::disableEncryption()
*/
public function withoutPassword();
diff --git a/tests/PhpZip/PhpZipExtResourceTest.php b/tests/PhpZip/PhpZipExtResourceTest.php
index 1c1ee9a..859ebe5 100644
--- a/tests/PhpZip/PhpZipExtResourceTest.php
+++ b/tests/PhpZip/PhpZipExtResourceTest.php
@@ -127,7 +127,10 @@ class PhpZipExtResourceTest extends ZipTestCase
public function testBug70752()
{
if (\PHP_INT_SIZE === 4) { // php 32 bit
- $this->setExpectedException(RuntimeException::class, 'Traditional PKWARE Encryption is not supported in 32-bit PHP.');
+ $this->setExpectedException(
+ RuntimeException::class,
+ 'Traditional PKWARE Encryption is not supported in 32-bit PHP.'
+ );
} else { // php 64 bit
$this->setExpectedException(
ZipAuthenticationException::class,
@@ -163,19 +166,11 @@ class PhpZipExtResourceTest extends ZipTestCase
*/
public function testPecl12414()
{
- $filename = __DIR__ . '/php-zip-ext-test-resources/pecl12414.zip';
+ $this->setExpectedException(ZipException::class, 'Corrupt zip file. Cannot read central dir entry.');
- $entryName = 'MYLOGOV2.GFX';
+ $filename = __DIR__ . '/php-zip-ext-test-resources/pecl12414.zip';
$zipFile = new ZipFile();
$zipFile->openFile($filename);
-
- $info = $zipFile->getEntryInfo($entryName);
- static::assertTrue($info->getSize() > 0);
-
- $contents = $zipFile[$entryName];
- static::assertSame(\strlen($contents), $info->getSize());
-
- $zipFile->close();
}
}
diff --git a/tests/PhpZip/ZipAlignTest.php b/tests/PhpZip/ZipAlignTest.php
index 177f0a9..8201b83 100644
--- a/tests/PhpZip/ZipAlignTest.php
+++ b/tests/PhpZip/ZipAlignTest.php
@@ -54,7 +54,7 @@ class ZipAlignTest extends ZipTestCase
$zipFile->addFromString(
'entry' . $i . '.txt',
CryptoUtil::randomBytes(mt_rand(100, 4096)),
- ZipFileInterface::METHOD_STORED
+ ZipFile::METHOD_STORED
);
}
$zipFile->saveAsFile($this->outputFilename);
@@ -95,7 +95,7 @@ class ZipAlignTest extends ZipTestCase
$zipFile->addFromString(
'entry' . $i . '.txt',
CryptoUtil::randomBytes(mt_rand(100, 4096)),
- ZipFileInterface::METHOD_STORED
+ ZipFile::METHOD_STORED
);
}
$zipFile->setZipAlign(4);
@@ -123,7 +123,7 @@ class ZipAlignTest extends ZipTestCase
$zipFile->addFromString(
'entry' . $i . '.txt',
CryptoUtil::randomBytes(mt_rand(100, 4096)),
- ZipFileInterface::METHOD_STORED
+ ZipFile::METHOD_STORED
);
}
$zipFile->saveAsFile($this->outputFilename);
@@ -149,8 +149,8 @@ class ZipAlignTest extends ZipTestCase
'entry_new_' . ($isStored ? 'stored' : 'deflated') . '_' . $i . '.txt',
CryptoUtil::randomBytes(mt_rand(100, 4096)),
$isStored ?
- ZipFileInterface::METHOD_STORED :
- ZipFileInterface::METHOD_DEFLATED
+ ZipFile::METHOD_STORED :
+ ZipFile::METHOD_DEFLATED
);
}
$zipFile->setZipAlign(4);
diff --git a/tests/PhpZip/ZipFileTest.php b/tests/PhpZip/ZipFileTest.php
index fa97374..5f80f95 100644
--- a/tests/PhpZip/ZipFileTest.php
+++ b/tests/PhpZip/ZipFileTest.php
@@ -909,12 +909,12 @@ class ZipFileTest extends ZipTestCase
$entries = [
'1' => [
'data' => CryptoUtil::randomBytes(255),
- 'method' => ZipFileInterface::METHOD_STORED,
+ 'method' => ZipFile::METHOD_STORED,
'expected' => 'No compression',
],
'2' => [
'data' => CryptoUtil::randomBytes(255),
- 'method' => ZipFileInterface::METHOD_DEFLATED,
+ 'method' => ZipFile::METHOD_DEFLATED,
'expected' => 'Deflate',
],
];
@@ -922,7 +922,7 @@ class ZipFileTest extends ZipTestCase
if (\extension_loaded('bz2')) {
$entries['3'] = [
'data' => CryptoUtil::randomBytes(255),
- 'method' => ZipFileInterface::METHOD_BZIP2,
+ 'method' => ZipFile::METHOD_BZIP2,
'expected' => 'Bzip2',
];
}
@@ -938,7 +938,7 @@ class ZipFileTest extends ZipTestCase
static::assertCorrectZipArchive($this->outputFilename);
$zipFile->openFile($this->outputFilename);
- $zipFile->setCompressionLevel(ZipFileInterface::LEVEL_BEST_COMPRESSION);
+ $zipFile->setCompressionLevel(ZipFile::LEVEL_BEST_COMPRESSION);
$zipAllInfo = $zipFile->getAllInfo();
foreach ($zipAllInfo as $entryName => $info) {
@@ -1693,14 +1693,14 @@ class ZipFileTest extends ZipTestCase
$files['file' . $i . '.txt'] = CryptoUtil::randomBytes(255);
}
- $methods = [ZipFileInterface::METHOD_STORED, ZipFileInterface::METHOD_DEFLATED];
+ $methods = [ZipFile::METHOD_STORED, ZipFile::METHOD_DEFLATED];
if (\extension_loaded('bz2')) {
- $methods[] = ZipFileInterface::METHOD_BZIP2;
+ $methods[] = ZipFile::METHOD_BZIP2;
}
$zipFile = new ZipFile();
- $zipFile->setCompressionLevel(ZipFileInterface::LEVEL_BEST_SPEED);
+ $zipFile->setCompressionLevel(ZipFile::LEVEL_BEST_SPEED);
foreach ($files as $entryName => $content) {
$zipFile->addFromString($entryName, $content, $methods[array_rand($methods)]);
@@ -1985,14 +1985,14 @@ class ZipFileTest extends ZipTestCase
{
$zipFile = new ZipFile();
$zipFile
- ->addFromString('file', 'content', ZipFileInterface::METHOD_DEFLATED)
- ->setCompressionLevelEntry('file', ZipFileInterface::LEVEL_BEST_COMPRESSION)
- ->addFromString('file2', 'content', ZipFileInterface::METHOD_DEFLATED)
- ->setCompressionLevelEntry('file2', ZipFileInterface::LEVEL_FAST)
- ->addFromString('file3', 'content', ZipFileInterface::METHOD_DEFLATED)
- ->setCompressionLevelEntry('file3', ZipFileInterface::LEVEL_SUPER_FAST)
- ->addFromString('file4', 'content', ZipFileInterface::METHOD_DEFLATED)
- ->setCompressionLevelEntry('file4', ZipFileInterface::LEVEL_DEFAULT_COMPRESSION)
+ ->addFromString('file', 'content', ZipFile::METHOD_DEFLATED)
+ ->setCompressionLevelEntry('file', ZipFile::LEVEL_BEST_COMPRESSION)
+ ->addFromString('file2', 'content', ZipFile::METHOD_DEFLATED)
+ ->setCompressionLevelEntry('file2', ZipFile::LEVEL_FAST)
+ ->addFromString('file3', 'content', ZipFile::METHOD_DEFLATED)
+ ->setCompressionLevelEntry('file3', ZipFile::LEVEL_SUPER_FAST)
+ ->addFromString('file4', 'content', ZipFile::METHOD_DEFLATED)
+ ->setCompressionLevelEntry('file4', ZipFile::LEVEL_DEFAULT_COMPRESSION)
->saveAsFile($this->outputFilename)
->close()
;
@@ -2003,22 +2003,22 @@ class ZipFileTest extends ZipTestCase
static::assertSame(
$zipFile->getEntryInfo('file')
->getCompressionLevel(),
- ZipFileInterface::LEVEL_BEST_COMPRESSION
+ ZipFile::LEVEL_BEST_COMPRESSION
);
static::assertSame(
$zipFile->getEntryInfo('file2')
->getCompressionLevel(),
- ZipFileInterface::LEVEL_FAST
+ ZipFile::LEVEL_FAST
);
static::assertSame(
$zipFile->getEntryInfo('file3')
->getCompressionLevel(),
- ZipFileInterface::LEVEL_SUPER_FAST
+ ZipFile::LEVEL_SUPER_FAST
);
static::assertSame(
$zipFile->getEntryInfo('file4')
->getCompressionLevel(),
- ZipFileInterface::LEVEL_DEFAULT_COMPRESSION
+ ZipFile::LEVEL_DEFAULT_COMPRESSION
);
$zipFile->close();
}
@@ -2054,10 +2054,10 @@ class ZipFileTest extends ZipTestCase
{
$zipFile = new ZipFile();
for ($i = 0; $i < 10; $i++) {
- $zipFile->addFromString('file' . $i, 'content', ZipFileInterface::METHOD_DEFLATED);
+ $zipFile->addFromString('file' . $i, 'content', ZipFile::METHOD_DEFLATED);
}
$zipFile
- ->setCompressionLevel(ZipFileInterface::LEVEL_BEST_SPEED)
+ ->setCompressionLevel(ZipFile::LEVEL_BEST_SPEED)
->saveAsFile($this->outputFilename)
->close()
;
@@ -2069,7 +2069,7 @@ class ZipFileTest extends ZipTestCase
array_walk(
$infoList,
function (ZipInfo $zipInfo) {
- $this->assertSame($zipInfo->getCompressionLevel(), ZipFileInterface::LEVEL_BEST_SPEED);
+ $this->assertSame($zipInfo->getCompressionLevel(), ZipFile::LEVEL_BEST_SPEED);
}
);
$zipFile->close();
@@ -2082,13 +2082,13 @@ class ZipFileTest extends ZipTestCase
public function testCompressionMethodEntry()
{
$zipFile = new ZipFile();
- $zipFile->addFromString('file', 'content', ZipFileInterface::METHOD_STORED);
+ $zipFile->addFromString('file', 'content', ZipFile::METHOD_STORED);
$zipFile->saveAsFile($this->outputFilename);
$zipFile->close();
$zipFile->openFile($this->outputFilename);
static::assertSame($zipFile->getEntryInfo('file')->getMethodName(), 'No compression');
- $zipFile->setCompressionMethodEntry('file', ZipFileInterface::METHOD_DEFLATED);
+ $zipFile->setCompressionMethodEntry('file', ZipFile::METHOD_DEFLATED);
static::assertSame($zipFile->getEntryInfo('file')->getMethodName(), 'Deflate');
$zipFile->rewrite();
@@ -2103,7 +2103,7 @@ class ZipFileTest extends ZipTestCase
$this->setExpectedException(ZipUnsupportMethodException::class, 'Unsupported method');
$zipFile = new ZipFile();
- $zipFile->addFromString('file', 'content', ZipFileInterface::METHOD_STORED);
+ $zipFile->addFromString('file', 'content', ZipFile::METHOD_STORED);
$zipFile->setCompressionMethodEntry('file', 99);
}
diff --git a/tests/PhpZip/ZipMatcherTest.php b/tests/PhpZip/ZipMatcherTest.php
index debf574..11d8fc7 100644
--- a/tests/PhpZip/ZipMatcherTest.php
+++ b/tests/PhpZip/ZipMatcherTest.php
@@ -38,8 +38,16 @@ class ZipMatcherTest extends TestCase
$matcher->match('~^[2][1-5]|[3][6-9]|40$~s');
static::assertCount(10, $matcher);
$actualMatches = [
- '21', '22', '23', '24', '25',
- '36', '37', '38', '39', '40',
+ '21',
+ '22',
+ '23',
+ '24',
+ '25',
+ '36',
+ '37',
+ '38',
+ '39',
+ '40',
];
static::assertSame($matcher->getMatches(), $actualMatches);
$matcher->setPassword('qwerty');
diff --git a/tests/PhpZip/ZipPasswordTest.php b/tests/PhpZip/ZipPasswordTest.php
index dc00b26..b147b70 100644
--- a/tests/PhpZip/ZipPasswordTest.php
+++ b/tests/PhpZip/ZipPasswordTest.php
@@ -22,11 +22,15 @@ class ZipPasswordTest extends ZipFileAddDirTest
* Test archive password.
*
* @throws ZipException
+ * @noinspection PhpRedundantCatchClauseInspection
*/
public function testSetPassword()
{
if (\PHP_INT_SIZE === 4) { // php 32 bit
- $this->setExpectedException(RuntimeException::class, 'Traditional PKWARE Encryption is not supported in 32-bit PHP.');
+ $this->setExpectedException(
+ RuntimeException::class,
+ 'Traditional PKWARE Encryption is not supported in 32-bit PHP.'
+ );
}
$password = base64_encode(CryptoUtil::randomBytes(100));
@@ -35,7 +39,7 @@ class ZipPasswordTest extends ZipFileAddDirTest
// create encryption password with ZipCrypto
$zipFile = new ZipFile();
$zipFile->addDir(__DIR__);
- $zipFile->setPassword($password, ZipFileInterface::ENCRYPTION_METHOD_TRADITIONAL);
+ $zipFile->setPassword($password, ZipFile::ENCRYPTION_METHOD_TRADITIONAL);
$zipFile->saveAsFile($this->outputFilename);
$zipFile->close();
@@ -66,7 +70,7 @@ class ZipPasswordTest extends ZipFileAddDirTest
}
// change encryption method to WinZip Aes and update file
- $zipFile->setPassword($password, ZipFileInterface::ENCRYPTION_METHOD_WINZIP_AES);
+ $zipFile->setPassword($password, ZipFile::ENCRYPTION_METHOD_WINZIP_AES);
$zipFile->saveAsFile($this->outputFilename);
$zipFile->close();
@@ -121,14 +125,17 @@ class ZipPasswordTest extends ZipFileAddDirTest
public function testTraditionalEncryption()
{
if (\PHP_INT_SIZE === 4) { // php 32 bit
- $this->setExpectedException(RuntimeException::class, 'Traditional PKWARE Encryption is not supported in 32-bit PHP.');
+ $this->setExpectedException(
+ RuntimeException::class,
+ 'Traditional PKWARE Encryption is not supported in 32-bit PHP.'
+ );
}
$password = base64_encode(CryptoUtil::randomBytes(50));
$zip = new ZipFile();
$zip->addDirRecursive($this->outputDirname);
- $zip->setPassword($password, ZipFileInterface::ENCRYPTION_METHOD_TRADITIONAL);
+ $zip->setPassword($password, ZipFile::ENCRYPTION_METHOD_TRADITIONAL);
$zip->saveAsFile($this->outputFilename);
$zip->close();
@@ -187,10 +194,10 @@ class ZipPasswordTest extends ZipFileAddDirTest
public function winZipKeyStrengthProvider()
{
return [
- [ZipFileInterface::ENCRYPTION_METHOD_WINZIP_AES_128, 128],
- [ZipFileInterface::ENCRYPTION_METHOD_WINZIP_AES_192, 192],
- [ZipFileInterface::ENCRYPTION_METHOD_WINZIP_AES, 256],
- [ZipFileInterface::ENCRYPTION_METHOD_WINZIP_AES_256, 256],
+ [ZipFile::ENCRYPTION_METHOD_WINZIP_AES_128, 128],
+ [ZipFile::ENCRYPTION_METHOD_WINZIP_AES_192, 192],
+ [ZipFile::ENCRYPTION_METHOD_WINZIP_AES, 256],
+ [ZipFile::ENCRYPTION_METHOD_WINZIP_AES_256, 256],
];
}
@@ -201,7 +208,10 @@ class ZipPasswordTest extends ZipFileAddDirTest
public function testEncryptionEntries()
{
if (\PHP_INT_SIZE === 4) { // php 32 bit
- $this->setExpectedException(RuntimeException::class, 'Traditional PKWARE Encryption is not supported in 32-bit PHP.');
+ $this->setExpectedException(
+ RuntimeException::class,
+ 'Traditional PKWARE Encryption is not supported in 32-bit PHP.'
+ );
}
$password1 = '353442434235424234';
@@ -209,8 +219,8 @@ class ZipPasswordTest extends ZipFileAddDirTest
$zip = new ZipFile();
$zip->addDir($this->outputDirname);
- $zip->setPasswordEntry('.hidden', $password1, ZipFileInterface::ENCRYPTION_METHOD_TRADITIONAL);
- $zip->setPasswordEntry('text file.txt', $password2, ZipFileInterface::ENCRYPTION_METHOD_WINZIP_AES);
+ $zip->setPasswordEntry('.hidden', $password1, ZipFile::ENCRYPTION_METHOD_TRADITIONAL);
+ $zip->setPasswordEntry('text file.txt', $password2, ZipFile::ENCRYPTION_METHOD_WINZIP_AES);
$zip->saveAsFile($this->outputFilename);
$zip->close();
@@ -248,7 +258,10 @@ class ZipPasswordTest extends ZipFileAddDirTest
public function testEncryptionEntriesWithDefaultPassword()
{
if (\PHP_INT_SIZE === 4) { // php 32 bit
- $this->setExpectedException(RuntimeException::class, 'Traditional PKWARE Encryption is not supported in 32-bit PHP.');
+ $this->setExpectedException(
+ RuntimeException::class,
+ 'Traditional PKWARE Encryption is not supported in 32-bit PHP.'
+ );
}
$password1 = '353442434235424234';
@@ -258,8 +271,8 @@ class ZipPasswordTest extends ZipFileAddDirTest
$zip = new ZipFile();
$zip->addDir($this->outputDirname);
$zip->setPassword($defaultPassword);
- $zip->setPasswordEntry('.hidden', $password1, ZipFileInterface::ENCRYPTION_METHOD_TRADITIONAL);
- $zip->setPasswordEntry('text file.txt', $password2, ZipFileInterface::ENCRYPTION_METHOD_WINZIP_AES);
+ $zip->setPasswordEntry('.hidden', $password1, ZipFile::ENCRYPTION_METHOD_TRADITIONAL);
+ $zip->setPasswordEntry('text file.txt', $password2, ZipFile::ENCRYPTION_METHOD_WINZIP_AES);
$zip->saveAsFile($this->outputFilename);
$zip->close();
@@ -350,7 +363,7 @@ class ZipPasswordTest extends ZipFileAddDirTest
$this->setExpectedException(ZipException::class, 'Invalid encryption method');
$zipFile = new ZipFile();
- $zipFile->addFromString('file', 'content', ZipFileInterface::METHOD_STORED);
+ $zipFile->addFromString('file', 'content', ZipFile::METHOD_STORED);
$zipFile->setPasswordEntry('file', 'pass', 99);
}
diff --git a/tests/PhpZip/ZipTestCase.php b/tests/PhpZip/ZipTestCase.php
index 5dfd400..a00e172 100644
--- a/tests/PhpZip/ZipTestCase.php
+++ b/tests/PhpZip/ZipTestCase.php
@@ -129,7 +129,7 @@ abstract class ZipTestCase extends TestCase
static::assertContains('Empty zipfile', $output);
}
- $actualEmptyZipData = pack('VVVVVv', EndOfCentralDirectory::END_OF_CENTRAL_DIRECTORY_RECORD_SIG, 0, 0, 0, 0, 0);
+ $actualEmptyZipData = pack('VVVVVv', EndOfCentralDirectory::END_OF_CD_SIG, 0, 0, 0, 0, 0);
static::assertStringEqualsFile($filename, $actualEmptyZipData);
}
From a20e9e054dc76b79ca349d05d14ade3cc49e671a Mon Sep 17 00:00:00 2001
From: wapplay
Date: Fri, 6 Dec 2019 23:23:44 +0300
Subject: [PATCH 6/8] use random_compat
---
.travis.yml | 6 --
composer.json | 3 +-
.../TraditionalPkwareEncryptionEngine.php | 8 ++-
src/PhpZip/Crypto/WinZipAesEngine.php | 7 ++-
src/PhpZip/Util/CryptoUtil.php | 26 +++-----
tests/PhpZip/Issue24Test.php | 4 +-
tests/PhpZip/ZipAlignTest.php | 11 ++--
tests/PhpZip/ZipFileTest.php | 60 +++++++++++--------
tests/PhpZip/ZipMatcherTest.php | 6 +-
tests/PhpZip/ZipPasswordTest.php | 13 ++--
tests/PhpZip/ZipTestCase.php | 1 +
11 files changed, 75 insertions(+), 70 deletions(-)
diff --git a/.travis.yml b/.travis.yml
index 07dc34d..a3328f5 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -10,12 +10,6 @@ php:
- '7.3'
- '7.4'
-# cache vendor dirs
-cache:
- directories:
- - vendor
- - $HOME/.composer/cache
-
install:
- travis_retry composer self-update && composer --version
- travis_retry composer install --no-interaction
diff --git a/composer.json b/composer.json
index 6f0c4dc..b0a938f 100644
--- a/composer.json
+++ b/composer.json
@@ -23,7 +23,8 @@
"require": {
"php": "^5.5 || ^7.0",
"ext-zlib": "*",
- "psr/http-message": "^1.0"
+ "psr/http-message": "^1.0",
+ "paragonie/random_compat": ">=1 <9.99"
},
"require-dev": {
"phpunit/phpunit": "^4.8|^5.7",
diff --git a/src/PhpZip/Crypto/TraditionalPkwareEncryptionEngine.php b/src/PhpZip/Crypto/TraditionalPkwareEncryptionEngine.php
index a90dff5..bc8ab45 100644
--- a/src/PhpZip/Crypto/TraditionalPkwareEncryptionEngine.php
+++ b/src/PhpZip/Crypto/TraditionalPkwareEncryptionEngine.php
@@ -6,7 +6,6 @@ use PhpZip\Exception\RuntimeException;
use PhpZip\Exception\ZipAuthenticationException;
use PhpZip\Exception\ZipCryptoException;
use PhpZip\Model\ZipEntry;
-use PhpZip\Util\CryptoUtil;
use PhpZip\Util\PackUtil;
/**
@@ -430,7 +429,12 @@ class TraditionalPkwareEncryptionEngine implements ZipEncryptionEngine
$crc = $this->entry->isDataDescriptorRequired() ?
($this->entry->getDosTime() & 0x0000ffff) << 16 :
$this->entry->getCrc();
- $headerBytes = CryptoUtil::randomBytes(self::STD_DEC_HDR_SIZE);
+
+ try {
+ $headerBytes = random_bytes(self::STD_DEC_HDR_SIZE);
+ } catch (\Exception $e) {
+ throw new \RuntimeException('Oops, our server is bust and cannot generate any random data.', 1, $e);
+ }
// Initialize again since the generated bytes were encrypted.
$password = $this->entry->getPassword();
diff --git a/src/PhpZip/Crypto/WinZipAesEngine.php b/src/PhpZip/Crypto/WinZipAesEngine.php
index d050fca..97d8e44 100644
--- a/src/PhpZip/Crypto/WinZipAesEngine.php
+++ b/src/PhpZip/Crypto/WinZipAesEngine.php
@@ -8,7 +8,6 @@ use PhpZip\Exception\ZipCryptoException;
use PhpZip\Exception\ZipException;
use PhpZip\Extra\Fields\WinZipAesEntryExtraField;
use PhpZip\Model\ZipEntry;
-use PhpZip\Util\CryptoUtil;
/**
* WinZip Aes Encryption Engine.
@@ -262,7 +261,11 @@ class WinZipAesEngine implements ZipEncryptionEngine
);
$keyStrengthBytes = $keyStrengthBits / 8;
- $salt = CryptoUtil::randomBytes($keyStrengthBytes / 2);
+ try {
+ $salt = random_bytes($keyStrengthBytes / 2);
+ } catch (\Exception $e) {
+ throw new \RuntimeException('Oops, our server is bust and cannot generate any random data.', 1, $e);
+ }
$keyParam = hash_pbkdf2(
'sha1',
diff --git a/src/PhpZip/Util/CryptoUtil.php b/src/PhpZip/Util/CryptoUtil.php
index 0d7958b..d2da78f 100644
--- a/src/PhpZip/Util/CryptoUtil.php
+++ b/src/PhpZip/Util/CryptoUtil.php
@@ -2,10 +2,10 @@
namespace PhpZip\Util;
-use PhpZip\Exception\RuntimeException;
-
/**
* Crypto Utils.
+ *
+ * @deprecated
*/
class CryptoUtil
{
@@ -14,26 +14,14 @@ class CryptoUtil
*
* @param int $length
*
+ * @throws \Exception
+ *
* @return string
+ *
+ * @deprecated Use random_bytes()
*/
final public static function randomBytes($length)
{
- $length = (int) $length;
-
- if (\function_exists('random_bytes')) {
- try {
- return random_bytes($length);
- } catch (\Exception $e) {
- throw new \RuntimeException('Could not generate a random string.');
- }
- } elseif (\function_exists('openssl_random_pseudo_bytes')) {
- /** @noinspection PhpComposerExtensionStubsInspection */
- return openssl_random_pseudo_bytes($length);
- } elseif (\function_exists('mcrypt_create_iv')) {
- /** @noinspection PhpComposerExtensionStubsInspection */
- return mcrypt_create_iv($length);
- } else {
- throw new RuntimeException('Extension openssl or mcrypt not loaded');
- }
+ return random_bytes($length);
}
}
diff --git a/tests/PhpZip/Issue24Test.php b/tests/PhpZip/Issue24Test.php
index 710935d..6e33163 100644
--- a/tests/PhpZip/Issue24Test.php
+++ b/tests/PhpZip/Issue24Test.php
@@ -3,7 +3,6 @@
namespace PhpZip;
use PhpZip\Exception\ZipException;
-use PhpZip\Util\CryptoUtil;
/**
* @internal
@@ -22,10 +21,11 @@ class Issue24Test extends ZipTestCase
/**
* @throws ZipException
+ * @throws \Exception
*/
public function testDummyFS()
{
- $fileContents = str_repeat(base64_encode(CryptoUtil::randomBytes(12000)), 100);
+ $fileContents = str_repeat(base64_encode(random_bytes(12000)), 100);
// create zip file
$zip = new ZipFile();
diff --git a/tests/PhpZip/ZipAlignTest.php b/tests/PhpZip/ZipAlignTest.php
index 8201b83..f6b8f4f 100644
--- a/tests/PhpZip/ZipAlignTest.php
+++ b/tests/PhpZip/ZipAlignTest.php
@@ -3,7 +3,6 @@
namespace PhpZip;
use PhpZip\Exception\ZipException;
-use PhpZip\Util\CryptoUtil;
/**
* Test ZipAlign.
@@ -53,7 +52,7 @@ class ZipAlignTest extends ZipTestCase
for ($i = 0; $i < 100; $i++) {
$zipFile->addFromString(
'entry' . $i . '.txt',
- CryptoUtil::randomBytes(mt_rand(100, 4096)),
+ random_bytes(mt_rand(100, 4096)),
ZipFile::METHOD_STORED
);
}
@@ -87,6 +86,7 @@ class ZipAlignTest extends ZipTestCase
/**
* @throws ZipException
+ * @throws \Exception
*/
public function testZipAlignNewFiles()
{
@@ -94,7 +94,7 @@ class ZipAlignTest extends ZipTestCase
for ($i = 0; $i < 100; $i++) {
$zipFile->addFromString(
'entry' . $i . '.txt',
- CryptoUtil::randomBytes(mt_rand(100, 4096)),
+ random_bytes(mt_rand(100, 4096)),
ZipFile::METHOD_STORED
);
}
@@ -115,6 +115,7 @@ class ZipAlignTest extends ZipTestCase
/**
* @throws ZipException
+ * @throws \Exception
*/
public function testZipAlignFromModifiedZipArchive()
{
@@ -122,7 +123,7 @@ class ZipAlignTest extends ZipTestCase
for ($i = 0; $i < 100; $i++) {
$zipFile->addFromString(
'entry' . $i . '.txt',
- CryptoUtil::randomBytes(mt_rand(100, 4096)),
+ random_bytes(mt_rand(100, 4096)),
ZipFile::METHOD_STORED
);
}
@@ -147,7 +148,7 @@ class ZipAlignTest extends ZipTestCase
$zipFile->addFromString(
'entry_new_' . ($isStored ? 'stored' : 'deflated') . '_' . $i . '.txt',
- CryptoUtil::randomBytes(mt_rand(100, 4096)),
+ random_bytes(mt_rand(100, 4096)),
$isStored ?
ZipFile::METHOD_STORED :
ZipFile::METHOD_DEFLATED
diff --git a/tests/PhpZip/ZipFileTest.php b/tests/PhpZip/ZipFileTest.php
index 5f80f95..3ad1b22 100644
--- a/tests/PhpZip/ZipFileTest.php
+++ b/tests/PhpZip/ZipFileTest.php
@@ -8,7 +8,6 @@ use PhpZip\Exception\ZipException;
use PhpZip\Exception\ZipUnsupportMethodException;
use PhpZip\Model\ZipEntry;
use PhpZip\Model\ZipInfo;
-use PhpZip\Util\CryptoUtil;
use PhpZip\Util\FilesUtil;
use Psr\Http\Message\ResponseInterface;
use Zend\Diactoros\Response;
@@ -68,6 +67,7 @@ class ZipFileTest extends ZipTestCase
/**
* @throws ZipException
+ * @throws \Exception
*/
public function testOpenFileInvalidZip()
{
@@ -76,7 +76,7 @@ class ZipFileTest extends ZipTestCase
'Expected Local File Header or (ZIP64) End Of Central Directory Record'
);
- static::assertNotFalse(file_put_contents($this->outputFilename, CryptoUtil::randomBytes(255)));
+ static::assertNotFalse(file_put_contents($this->outputFilename, random_bytes(255)));
$zipFile = new ZipFile();
$zipFile->openFile($this->outputFilename);
}
@@ -105,6 +105,7 @@ class ZipFileTest extends ZipTestCase
/**
* @throws ZipException
+ * @throws \Exception
*/
public function testOpenFromStringInvalidZip()
{
@@ -114,7 +115,7 @@ class ZipFileTest extends ZipTestCase
);
$zipFile = new ZipFile();
- $zipFile->openFromString(CryptoUtil::randomBytes(255));
+ $zipFile->openFromString(random_bytes(255));
}
/**
@@ -224,6 +225,7 @@ class ZipFileTest extends ZipTestCase
/**
* @throws ZipException
+ * @throws \Exception
*/
public function testOpenFromStreamInvalidZip()
{
@@ -233,7 +235,7 @@ class ZipFileTest extends ZipTestCase
);
$fp = fopen($this->outputFilename, 'w+b');
- fwrite($fp, CryptoUtil::randomBytes(255));
+ fwrite($fp, random_bytes(255));
$zipFile = new ZipFile();
$zipFile->openFromStream($fp);
}
@@ -800,32 +802,33 @@ class ZipFileTest extends ZipTestCase
* Test zip entry comment.
*
* @throws ZipException
+ * @throws \Exception
*/
public function testEntryComment()
{
$entries = [
'文件1.txt' => [
- 'data' => CryptoUtil::randomBytes(255),
+ 'data' => random_bytes(255),
'comment' => '這是註釋的條目。',
],
'file2.txt' => [
- 'data' => CryptoUtil::randomBytes(255),
+ 'data' => random_bytes(255),
'comment' => null,
],
'file3.txt' => [
- 'data' => CryptoUtil::randomBytes(255),
- 'comment' => CryptoUtil::randomBytes(255),
+ 'data' => random_bytes(255),
+ 'comment' => random_bytes(255),
],
'file4.txt' => [
- 'data' => CryptoUtil::randomBytes(255),
+ 'data' => random_bytes(255),
'comment' => 'Комментарий файла',
],
'file5.txt' => [
- 'data' => CryptoUtil::randomBytes(255),
+ 'data' => random_bytes(255),
'comment' => 'ไฟล์แสดงความคิดเห็น',
],
'file6 emoji 🙍🏼.txt' => [
- 'data' => CryptoUtil::randomBytes(255),
+ 'data' => random_bytes(255),
'comment' => 'Emoji comment file - 😀 ⛈ ❤️ 🤴🏽',
],
];
@@ -903,17 +906,18 @@ class ZipFileTest extends ZipTestCase
* Test all available support compression methods.
*
* @throws ZipException
+ * @throws \Exception
*/
public function testCompressionMethod()
{
$entries = [
'1' => [
- 'data' => CryptoUtil::randomBytes(255),
+ 'data' => random_bytes(255),
'method' => ZipFile::METHOD_STORED,
'expected' => 'No compression',
],
'2' => [
- 'data' => CryptoUtil::randomBytes(255),
+ 'data' => random_bytes(255),
'method' => ZipFile::METHOD_DEFLATED,
'expected' => 'Deflate',
],
@@ -921,7 +925,7 @@ class ZipFileTest extends ZipTestCase
if (\extension_loaded('bz2')) {
$entries['3'] = [
- 'data' => CryptoUtil::randomBytes(255),
+ 'data' => random_bytes(255),
'method' => ZipFile::METHOD_BZIP2,
'expected' => 'Bzip2',
];
@@ -976,13 +980,14 @@ class ZipFileTest extends ZipTestCase
* Test extract all files.
*
* @throws ZipException
+ * @throws \Exception
*/
public function testExtract()
{
$entries = [
- 'test1.txt' => CryptoUtil::randomBytes(255),
- 'test2.txt' => CryptoUtil::randomBytes(255),
- 'test/test 2/test3.txt' => CryptoUtil::randomBytes(255),
+ 'test1.txt' => random_bytes(255),
+ 'test2.txt' => random_bytes(255),
+ 'test/test 2/test3.txt' => random_bytes(255),
'test empty/dir' => null,
];
@@ -1022,17 +1027,18 @@ class ZipFileTest extends ZipTestCase
* Test extract some files.
*
* @throws ZipException
+ * @throws \Exception
*/
public function testExtractSomeFiles()
{
$entries = [
- 'test1.txt' => CryptoUtil::randomBytes(255),
- 'test2.txt' => CryptoUtil::randomBytes(255),
- 'test3.txt' => CryptoUtil::randomBytes(255),
- 'test4.txt' => CryptoUtil::randomBytes(255),
- 'test5.txt' => CryptoUtil::randomBytes(255),
- 'test/test/test.txt' => CryptoUtil::randomBytes(255),
- 'test/test/test 2.txt' => CryptoUtil::randomBytes(255),
+ 'test1.txt' => random_bytes(255),
+ 'test2.txt' => random_bytes(255),
+ 'test3.txt' => random_bytes(255),
+ 'test4.txt' => random_bytes(255),
+ 'test5.txt' => random_bytes(255),
+ 'test/test/test.txt' => random_bytes(255),
+ 'test/test/test 2.txt' => random_bytes(255),
'test empty/dir/' => null,
'test empty/dir2/' => null,
];
@@ -1684,13 +1690,14 @@ class ZipFileTest extends ZipTestCase
* Test `ZipFile` implemented \ArrayAccess, \Countable and |iterator.
*
* @throws ZipException
+ * @throws \Exception
*/
public function testZipFileArrayAccessAndCountableAndIterator()
{
$files = [];
$numFiles = mt_rand(20, 100);
for ($i = 0; $i < $numFiles; $i++) {
- $files['file' . $i . '.txt'] = CryptoUtil::randomBytes(255);
+ $files['file' . $i . '.txt'] = random_bytes(255);
}
$methods = [ZipFile::METHOD_STORED, ZipFile::METHOD_DEFLATED];
@@ -1799,13 +1806,14 @@ class ZipFileTest extends ZipTestCase
/**
* @throws Exception\ZipEntryNotFoundException
* @throws ZipException
+ * @throws \Exception
*/
public function testUnknownCompressionMethod()
{
$zipFile = new ZipFile();
$zipFile->addFromString('file', 'content', ZipEntry::UNKNOWN);
- $zipFile->addFromString('file2', base64_encode(CryptoUtil::randomBytes(512)), ZipEntry::UNKNOWN);
+ $zipFile->addFromString('file2', base64_encode(random_bytes(512)), ZipEntry::UNKNOWN);
static::assertSame($zipFile->getEntryInfo('file')->getMethodName(), 'Unknown');
static::assertSame($zipFile->getEntryInfo('file2')->getMethodName(), 'Unknown');
diff --git a/tests/PhpZip/ZipMatcherTest.php b/tests/PhpZip/ZipMatcherTest.php
index 11d8fc7..345fa3d 100644
--- a/tests/PhpZip/ZipMatcherTest.php
+++ b/tests/PhpZip/ZipMatcherTest.php
@@ -5,7 +5,6 @@ namespace PhpZip;
use PHPUnit\Framework\TestCase;
use PhpZip\Model\ZipEntryMatcher;
use PhpZip\Model\ZipInfo;
-use PhpZip\Util\CryptoUtil;
/**
* @internal
@@ -73,11 +72,14 @@ class ZipMatcherTest extends TestCase
$zipFile->close();
}
+ /**
+ * @throws \Exception
+ */
public function testDocsExample()
{
$zipFile = new ZipFile();
for ($i = 0; $i < 100; $i++) {
- $zipFile['file_' . $i . '.jpg'] = CryptoUtil::randomBytes(100);
+ $zipFile['file_' . $i . '.jpg'] = random_bytes(100);
}
$renameEntriesArray = [
diff --git a/tests/PhpZip/ZipPasswordTest.php b/tests/PhpZip/ZipPasswordTest.php
index b147b70..7ab39d7 100644
--- a/tests/PhpZip/ZipPasswordTest.php
+++ b/tests/PhpZip/ZipPasswordTest.php
@@ -7,7 +7,6 @@ use PhpZip\Exception\ZipAuthenticationException;
use PhpZip\Exception\ZipEntryNotFoundException;
use PhpZip\Exception\ZipException;
use PhpZip\Model\ZipInfo;
-use PhpZip\Util\CryptoUtil;
/**
* Tests with zip password.
@@ -22,6 +21,7 @@ class ZipPasswordTest extends ZipFileAddDirTest
* Test archive password.
*
* @throws ZipException
+ * @throws \Exception
* @noinspection PhpRedundantCatchClauseInspection
*/
public function testSetPassword()
@@ -33,7 +33,7 @@ class ZipPasswordTest extends ZipFileAddDirTest
);
}
- $password = base64_encode(CryptoUtil::randomBytes(100));
+ $password = base64_encode(random_bytes(100));
$badPassword = 'bad password';
// create encryption password with ZipCrypto
@@ -121,6 +121,7 @@ class ZipPasswordTest extends ZipFileAddDirTest
/**
* @throws ZipException
+ * @throws \Exception
*/
public function testTraditionalEncryption()
{
@@ -131,7 +132,7 @@ class ZipPasswordTest extends ZipFileAddDirTest
);
}
- $password = base64_encode(CryptoUtil::randomBytes(50));
+ $password = base64_encode(random_bytes(50));
$zip = new ZipFile();
$zip->addDirRecursive($this->outputDirname);
@@ -161,10 +162,11 @@ class ZipPasswordTest extends ZipFileAddDirTest
* @param int $bitSize
*
* @throws ZipException
+ * @throws \Exception
*/
public function testWinZipAesEncryption($encryptionMethod, $bitSize)
{
- $password = base64_encode(CryptoUtil::randomBytes(50));
+ $password = base64_encode(random_bytes(50));
$zip = new ZipFile();
$zip->addDirRecursive($this->outputDirname);
@@ -415,11 +417,12 @@ class ZipPasswordTest extends ZipFileAddDirTest
* @see https://github.com/Ne-Lexa/php-zip/issues/9
*
* @throws ZipException
+ * @throws \Exception
*/
public function testIssues9()
{
$contents = str_pad('', 1000, 'test;test2;test3' . \PHP_EOL, \STR_PAD_RIGHT);
- $password = base64_encode(CryptoUtil::randomBytes(20));
+ $password = base64_encode(random_bytes(20));
$encryptMethod = ZipFile::ENCRYPTION_METHOD_WINZIP_AES_256;
$zipFile = new ZipFile();
diff --git a/tests/PhpZip/ZipTestCase.php b/tests/PhpZip/ZipTestCase.php
index a00e172..3710459 100644
--- a/tests/PhpZip/ZipTestCase.php
+++ b/tests/PhpZip/ZipTestCase.php
@@ -63,6 +63,7 @@ abstract class ZipTestCase extends TestCase
$command .= ' -P ' . escapeshellarg($password);
}
$command .= ' -t ' . escapeshellarg($filename);
+ $command .= ' 2>&1';
exec($command, $output, $returnCode);
$output = implode(\PHP_EOL, $output);
From f82a57e662c80aa8505b44215316648604febbf7 Mon Sep 17 00:00:00 2001
From: wapplay
Date: Sat, 7 Dec 2019 19:40:36 +0300
Subject: [PATCH 7/8] fix duplicates
---
.../TraditionalPkwareEncryptionEngine.php | 6 +-
src/PhpZip/Model/Entry/ZipAbstractEntry.php | 6 +-
src/PhpZip/Model/ZipInfo.php | 19 ++-
.../IgnoreFilesRecursiveFilterIterator.php | 1 +
src/PhpZip/ZipFile.php | 134 +++++++++---------
tests/PhpZip/Issue24Test.php | 2 +
tests/PhpZip/ZipAlignTest.php | 1 +
tests/PhpZip/ZipTestCase.php | 2 +
8 files changed, 91 insertions(+), 80 deletions(-)
diff --git a/src/PhpZip/Crypto/TraditionalPkwareEncryptionEngine.php b/src/PhpZip/Crypto/TraditionalPkwareEncryptionEngine.php
index bc8ab45..4045545 100644
--- a/src/PhpZip/Crypto/TraditionalPkwareEncryptionEngine.php
+++ b/src/PhpZip/Crypto/TraditionalPkwareEncryptionEngine.php
@@ -366,9 +366,9 @@ class TraditionalPkwareEncryptionEngine implements ZipEncryptionEngine
$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);
+ for ($i = 0; $i < self::STD_DEC_HDR_SIZE; $i++) {
+ $headerBytes[$i] = ($headerBytes[$i] ^ $this->decryptByte()) & 0xff;
+ $this->updateKeys($headerBytes[$i]);
}
if ($this->entry->getGeneralPurposeBitFlag(ZipEntry::GPBF_DATA_DESCRIPTOR)) {
diff --git a/src/PhpZip/Model/Entry/ZipAbstractEntry.php b/src/PhpZip/Model/Entry/ZipAbstractEntry.php
index f8dcc1a..8736baa 100644
--- a/src/PhpZip/Model/Entry/ZipAbstractEntry.php
+++ b/src/PhpZip/Model/Entry/ZipAbstractEntry.php
@@ -187,6 +187,7 @@ abstract class ZipAbstractEntry implements ZipEntry
* @return int Get platform
*
* @deprecated Use {@see ZipEntry::getCreatedOS()}
+ * @noinspection PhpUsageOfSilenceOperatorInspection
*/
public function getPlatform()
{
@@ -198,11 +199,12 @@ abstract class ZipAbstractEntry implements ZipEntry
/**
* @param int $platform
*
- * @throws ZipException
- *
* @return ZipEntry
*
+ * @throws ZipException
+ *
* @deprecated Use {@see ZipEntry::setCreatedOS()}
+ * @noinspection PhpUsageOfSilenceOperatorInspection
*/
public function setPlatform($platform)
{
diff --git a/src/PhpZip/Model/ZipInfo.php b/src/PhpZip/Model/ZipInfo.php
index 0e959b2..235efef 100644
--- a/src/PhpZip/Model/ZipInfo.php
+++ b/src/PhpZip/Model/ZipInfo.php
@@ -107,7 +107,7 @@ class ZipInfo
const UNX_IXOTH = 00001; // Unix execute permission: other
- private static $valuesMadeBy = [
+ private static $platformNames = [
self::MADE_BY_MS_DOS => 'FAT',
self::MADE_BY_AMIGA => 'Amiga',
self::MADE_BY_OPEN_VMS => 'OpenVMS',
@@ -130,7 +130,7 @@ class ZipInfo
self::MADE_BY_OS_X => 'Mac OS X',
];
- private static $valuesCompressionMethod = [
+ private static $compressionMethodNames = [
ZipEntry::UNKNOWN => 'unknown',
ZipFile::METHOD_STORED => 'no compression',
1 => 'shrink',
@@ -214,6 +214,7 @@ class ZipInfo
* @param ZipEntry $entry
*
* @throws ZipException
+ * @noinspection PhpMissingBreakStatementInspection
*/
public function __construct(ZipEntry $entry)
{
@@ -364,9 +365,7 @@ class ZipInfo
$field = $entry->getExtraFieldsCollection()->get(WinZipAesEntryExtraField::getHeaderId());
if ($field !== null) {
- /**
- * @var WinZipAesEntryExtraField $field
- */
+ /** @var WinZipAesEntryExtraField $field */
$method = $field->getMethod();
}
}
@@ -389,7 +388,7 @@ class ZipInfo
if ($entry->isEncrypted()) {
if ($entry->getMethod() === ZipEntry::METHOD_WINZIP_AES) {
- $return .= ucfirst(self::$valuesCompressionMethod[$entry->getMethod()]);
+ $return .= ucfirst(self::$compressionMethodNames[$entry->getMethod()]);
/** @var WinZipAesEntryExtraField|null $field */
$field = $entry->getExtraFieldsCollection()->get(WinZipAesEntryExtraField::getHeaderId());
@@ -404,8 +403,8 @@ class ZipInfo
$return .= ' ';
}
- if (isset(self::$valuesCompressionMethod[$compressionMethod])) {
- $return .= ucfirst(self::$valuesCompressionMethod[$compressionMethod]);
+ if (isset(self::$compressionMethodNames[$compressionMethod])) {
+ $return .= ucfirst(self::$compressionMethodNames[$compressionMethod]);
} else {
$return .= 'unknown';
}
@@ -420,8 +419,8 @@ class ZipInfo
*/
public static function getPlatformName(ZipEntry $entry)
{
- if (isset(self::$valuesMadeBy[$entry->getCreatedOS()])) {
- return self::$valuesMadeBy[$entry->getCreatedOS()];
+ if (isset(self::$platformNames[$entry->getCreatedOS()])) {
+ return self::$platformNames[$entry->getCreatedOS()];
}
return 'unknown';
diff --git a/src/PhpZip/Util/Iterator/IgnoreFilesRecursiveFilterIterator.php b/src/PhpZip/Util/Iterator/IgnoreFilesRecursiveFilterIterator.php
index 8935127..580805b 100644
--- a/src/PhpZip/Util/Iterator/IgnoreFilesRecursiveFilterIterator.php
+++ b/src/PhpZip/Util/Iterator/IgnoreFilesRecursiveFilterIterator.php
@@ -66,6 +66,7 @@ class IgnoreFilesRecursiveFilterIterator extends \RecursiveFilterIterator
/**
* @return IgnoreFilesRecursiveFilterIterator
+ * @noinspection PhpMissingParentCallCommonInspection
*/
public function getChildren()
{
diff --git a/src/PhpZip/ZipFile.php b/src/PhpZip/ZipFile.php
index 52969f9..a91e013 100644
--- a/src/PhpZip/ZipFile.php
+++ b/src/PhpZip/ZipFile.php
@@ -740,16 +740,7 @@ class ZipFile implements ZipFileInterface
natcasesort($files);
$path = array_shift($files);
- foreach ($files as $file) {
- $relativePath = str_replace($path, $localPath, $file);
- $relativePath = ltrim($relativePath, '\\/');
-
- if (is_dir($file) && FilesUtil::isEmptyDir($file)) {
- $this->addEmptyDir($relativePath);
- } elseif (is_file($file)) {
- $this->addFile($file, $relativePath, $compressionMethod);
- }
- }
+ $this->doAddFiles($path, $files, $localPath, $compressionMethod);
return $this;
}
@@ -824,25 +815,7 @@ class ZipFile implements ZipFileInterface
return $this;
}
- if (!empty($localPath) && \is_string($localPath)) {
- $localPath = trim($localPath, '/\\') . '/';
- } else {
- $localPath = '/';
- }
-
- /**
- * @var string $file
- */
- foreach ($filesFound as $file) {
- $filename = str_replace($inputDir, $localPath, $file);
- $filename = ltrim($filename, '\\/');
-
- if (is_dir($file) && FilesUtil::isEmptyDir($file)) {
- $this->addEmptyDir($filename);
- } elseif (is_file($file)) {
- $this->addFile($file, $filename, $compressionMethod);
- }
- }
+ $this->doAddFiles($inputDir, $filesFound, $localPath, $compressionMethod);
return $this;
}
@@ -932,18 +905,34 @@ class ZipFile implements ZipFileInterface
return $this;
}
- if (!empty($localPath) && \is_string($localPath)) {
- $localPath = trim($localPath, '\\/') . '/';
+ $this->doAddFiles($inputDir, $files, $localPath, $compressionMethod);
+
+ return $this;
+ }
+
+ /**
+ * @param string $fileSystemDir
+ * @param array $files
+ * @param string $zipPath
+ * @param int|null $compressionMethod
+ *
+ * @throws ZipException
+ */
+ private function doAddFiles($fileSystemDir, array $files, $zipPath, $compressionMethod = null)
+ {
+ $fileSystemDir = rtrim($fileSystemDir, '/\\') . \DIRECTORY_SEPARATOR;
+
+ if (!empty($zipPath) && \is_string($zipPath)) {
+ $zipPath = trim($zipPath, '\\/') . '/';
} else {
- $localPath = '/';
+ $zipPath = '/';
}
- $inputDir = rtrim($inputDir, '/\\') . \DIRECTORY_SEPARATOR;
/**
* @var string $file
*/
foreach ($files as $file) {
- $filename = str_replace($inputDir, $localPath, $file);
+ $filename = str_replace($fileSystemDir, $zipPath, $file);
$filename = ltrim($filename, '\\/');
if (is_dir($file) && FilesUtil::isEmptyDir($file)) {
@@ -952,8 +941,6 @@ class ZipFile implements ZipFileInterface
$this->addFile($file, $filename, $compressionMethod);
}
}
-
- return $this;
}
/**
@@ -1443,26 +1430,25 @@ class ZipFile implements ZipFileInterface
* @param bool $attachment Http Header 'Content-Disposition' if true then attachment otherwise inline
*
* @throws ZipException
+ *
+ * @return string
*/
public function outputAsAttachment($outputFilename, $mimeType = null, $attachment = true)
{
$outputFilename = (string) $outputFilename;
- if (empty($mimeType) || (!\is_string($mimeType) && !empty($outputFilename))) {
- $ext = strtolower(pathinfo($outputFilename, \PATHINFO_EXTENSION));
-
- if (!empty($ext) && isset(self::$defaultMimeTypes[$ext])) {
- $mimeType = self::$defaultMimeTypes[$ext];
- }
+ if ($mimeType === null) {
+ $mimeType = $this->getMimeTypeByFilename($outputFilename);
}
- if (empty($mimeType)) {
- $mimeType = self::$defaultMimeTypes['zip'];
+ if (!($handle = fopen('php://temp', 'w+b'))) {
+ throw new InvalidArgumentException('php://temp cannot open for write.');
}
-
- $content = $this->outputAsString();
+ $this->writeZipToStream($handle);
$this->close();
+ $size = fstat($handle)['size'];
+
$headerContentDisposition = 'Content-Disposition: ' . ($attachment ? 'attachment' : 'inline');
if (!empty($outputFilename)) {
@@ -1471,9 +1457,32 @@ class ZipFile implements ZipFileInterface
header($headerContentDisposition);
header('Content-Type: ' . $mimeType);
- header('Content-Length: ' . \strlen($content));
+ header('Content-Length: ' . $size);
- exit($content);
+ rewind($handle);
+
+ try {
+ return stream_get_contents($handle, -1, 0);
+ } finally {
+ fclose($handle);
+ }
+ }
+
+ /**
+ * @param string $outputFilename
+ *
+ * @return string
+ */
+ protected function getMimeTypeByFilename($outputFilename)
+ {
+ $outputFilename = (string) $outputFilename;
+ $ext = strtolower(pathinfo($outputFilename, \PATHINFO_EXTENSION));
+
+ if (!empty($ext) && isset(self::$defaultMimeTypes[$ext])) {
+ return self::$defaultMimeTypes[$ext];
+ }
+
+ return self::$defaultMimeTypes['zip'];
}
/**
@@ -1492,22 +1501,15 @@ class ZipFile implements ZipFileInterface
{
$outputFilename = (string) $outputFilename;
- if (empty($mimeType) || (!\is_string($mimeType) && !empty($outputFilename))) {
- $ext = strtolower(pathinfo($outputFilename, \PATHINFO_EXTENSION));
-
- if (!empty($ext) && isset(self::$defaultMimeTypes[$ext])) {
- $mimeType = self::$defaultMimeTypes[$ext];
- }
+ if ($mimeType === null) {
+ $mimeType = $this->getMimeTypeByFilename($outputFilename);
}
- if (empty($mimeType)) {
- $mimeType = self::$defaultMimeTypes['zip'];
- }
-
- if (!($handle = fopen('php://memory', 'w+b'))) {
- throw new InvalidArgumentException('Memory can not open from write.');
+ if (!($handle = fopen('php://temp', 'w+b'))) {
+ throw new InvalidArgumentException('php://temp cannot open for write.');
}
$this->writeZipToStream($handle);
+ $this->close();
rewind($handle);
$contentDispositionValue = ($attachment ? 'attachment' : 'inline');
@@ -1548,15 +1550,17 @@ class ZipFile implements ZipFileInterface
*/
public function outputAsString()
{
- if (!($handle = fopen('php://memory', 'w+b'))) {
- throw new InvalidArgumentException('Memory can not open from write.');
+ if (!($handle = fopen('php://temp', 'w+b'))) {
+ throw new InvalidArgumentException('php://temp cannot open for write.');
}
$this->writeZipToStream($handle);
rewind($handle);
- $content = stream_get_contents($handle);
- fclose($handle);
- return $content;
+ try {
+ return stream_get_contents($handle);
+ } finally {
+ fclose($handle);
+ }
}
/**
diff --git a/tests/PhpZip/Issue24Test.php b/tests/PhpZip/Issue24Test.php
index 6e33163..4250470 100644
--- a/tests/PhpZip/Issue24Test.php
+++ b/tests/PhpZip/Issue24Test.php
@@ -13,6 +13,8 @@ class Issue24Test extends ZipTestCase
{
/**
* This method is called before the first test of this test class is run.
+ *
+ * @noinspection PhpMissingParentCallCommonInspection
*/
public static function setUpBeforeClass()
{
diff --git a/tests/PhpZip/ZipAlignTest.php b/tests/PhpZip/ZipAlignTest.php
index f6b8f4f..427a5d4 100644
--- a/tests/PhpZip/ZipAlignTest.php
+++ b/tests/PhpZip/ZipAlignTest.php
@@ -45,6 +45,7 @@ class ZipAlignTest extends ZipTestCase
* Test zip alignment.
*
* @throws ZipException
+ * @throws \Exception
*/
public function testZipAlignSourceZip()
{
diff --git a/tests/PhpZip/ZipTestCase.php b/tests/PhpZip/ZipTestCase.php
index 3710459..ab61665 100644
--- a/tests/PhpZip/ZipTestCase.php
+++ b/tests/PhpZip/ZipTestCase.php
@@ -19,6 +19,8 @@ abstract class ZipTestCase extends TestCase
/**
* Before test.
+ *
+ * @noinspection PhpMissingParentCallCommonInspection
*/
protected function setUp()
{
From 725959d98f90b850008fcf8b76af77e208c85c39 Mon Sep 17 00:00:00 2001
From: wapplay
Date: Sat, 7 Dec 2019 19:40:36 +0300
Subject: [PATCH 8/8] fix encryption
---
src/PhpZip/Crypto/TraditionalPkwareEncryptionEngine.php | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/PhpZip/Crypto/TraditionalPkwareEncryptionEngine.php b/src/PhpZip/Crypto/TraditionalPkwareEncryptionEngine.php
index 4045545..1d12603 100644
--- a/src/PhpZip/Crypto/TraditionalPkwareEncryptionEngine.php
+++ b/src/PhpZip/Crypto/TraditionalPkwareEncryptionEngine.php
@@ -367,8 +367,8 @@ class TraditionalPkwareEncryptionEngine implements ZipEncryptionEngine
$byte = 0;
for ($i = 0; $i < self::STD_DEC_HDR_SIZE; $i++) {
- $headerBytes[$i] = ($headerBytes[$i] ^ $this->decryptByte()) & 0xff;
- $this->updateKeys($headerBytes[$i]);
+ $byte = ($headerBytes[$i] ^ $this->decryptByte()) & 0xff;
+ $this->updateKeys($byte);
}
if ($this->entry->getGeneralPurposeBitFlag(ZipEntry::GPBF_DATA_DESCRIPTOR)) {