Version Description
- bumped minimum php version to 7.1
- flush buffer after every write in order to avoid exceeding memory
Download this release
Release Info
Developer | andrej.pavlovic |
Plugin | Export Media Library |
Version | 3.0.0 |
Comparing to | |
See all releases |
Code changes from version 2.2.0 to 3.0.0
- .gitignore +0 -1
- composer.json +0 -18
- composer.lock +0 -180
- index.php +1 -1
- lib/DependencyCheck.php +1 -1
- lib/MassEdge/WordPress/Plugin/ExportMediaLibrary/API.php +1 -0
- readme.txt +7 -3
- run.php +6 -2
- vendor/autoload.php +7 -0
- vendor/composer/ClassLoader.php +445 -0
- vendor/composer/LICENSE +21 -0
- vendor/composer/autoload_classmap.php +9 -0
- vendor/composer/autoload_namespaces.php +9 -0
- vendor/composer/autoload_psr4.php +13 -0
- vendor/composer/autoload_real.php +52 -0
- vendor/composer/autoload_static.php +52 -0
- vendor/composer/installed.json +164 -0
- vendor/maennchen/zipstream-php/.gitignore +6 -0
- vendor/maennchen/zipstream-php/.travis.yml +12 -0
- vendor/maennchen/zipstream-php/CHANGELOG.md +35 -0
- vendor/maennchen/zipstream-php/CONTRIBUTING.md +25 -0
- vendor/maennchen/zipstream-php/LICENSE +24 -0
- vendor/maennchen/zipstream-php/README.md +81 -0
- vendor/maennchen/zipstream-php/composer.json +41 -0
- vendor/maennchen/zipstream-php/phpunit.xml.dist +17 -0
- vendor/maennchen/zipstream-php/src/Bigint.php +172 -0
- vendor/maennchen/zipstream-php/src/DeflateStream.php +70 -0
- vendor/maennchen/zipstream-php/src/Exception.php +11 -0
- vendor/maennchen/zipstream-php/src/Exception/EncodingException.php +13 -0
- vendor/maennchen/zipstream-php/src/Exception/FileNotFoundException.php +22 -0
- vendor/maennchen/zipstream-php/src/Exception/FileNotReadableException.php +22 -0
- vendor/maennchen/zipstream-php/src/Exception/IncompatibleOptionsException.php +13 -0
- vendor/maennchen/zipstream-php/src/Exception/OverflowException.php +17 -0
- vendor/maennchen/zipstream-php/src/Exception/StreamNotReadableException.php +22 -0
- vendor/maennchen/zipstream-php/src/File.php +480 -0
- vendor/maennchen/zipstream-php/src/Option/Archive.php +261 -0
- vendor/maennchen/zipstream-php/src/Option/File.php +116 -0
- vendor/maennchen/zipstream-php/src/Option/Method.php +18 -0
- vendor/maennchen/zipstream-php/src/Option/Version.php +21 -0
- vendor/maennchen/zipstream-php/src/Stream.php +258 -0
- vendor/maennchen/zipstream-php/src/ZipStream.php +593 -0
- vendor/maennchen/zipstream-php/test/BigintTest.php +65 -0
- vendor/maennchen/zipstream-php/test/ZipStreamTest.php +560 -0
- vendor/maennchen/zipstream-php/test/bootstrap.php +6 -0
- vendor/maennchen/zipstream-php/test/bug/BugHonorFileTimeTest.php +39 -0
- vendor/myclabs/php-enum/LICENSE +18 -0
- vendor/myclabs/php-enum/README.md +131 -0
- vendor/myclabs/php-enum/SECURITY.md +11 -0
- vendor/myclabs/php-enum/composer.json +32 -0
- vendor/myclabs/php-enum/src/Enum.php +205 -0
- vendor/myclabs/php-enum/src/PHPUnit/Comparator.php +54 -0
- vendor/psr/http-message/CHANGELOG.md +36 -0
- vendor/psr/http-message/LICENSE +19 -0
- vendor/psr/http-message/README.md +13 -0
- vendor/psr/http-message/composer.json +26 -0
- vendor/psr/http-message/src/MessageInterface.php +187 -0
- vendor/psr/http-message/src/RequestInterface.php +129 -0
- vendor/psr/http-message/src/ResponseInterface.php +68 -0
- vendor/psr/http-message/src/ServerRequestInterface.php +261 -0
- vendor/psr/http-message/src/StreamInterface.php +158 -0
- vendor/psr/http-message/src/UploadedFileInterface.php +123 -0
- vendor/psr/http-message/src/UriInterface.php +323 -0
.gitignore
DELETED
@@ -1 +0,0 @@
|
|
1 |
-
/vendor
|
|
composer.json
DELETED
@@ -1,18 +0,0 @@
|
|
1 |
-
{
|
2 |
-
"name": "massedge/wordpress-plugin-export-media-library",
|
3 |
-
"description": "Wordpress plugin that allows admins to export media library files as a compressed zip archive.",
|
4 |
-
"version": "2.2.0",
|
5 |
-
"type": "wordpress-plugin",
|
6 |
-
"license": "GPL-3.0",
|
7 |
-
"repositories": [{
|
8 |
-
"type": "vcs",
|
9 |
-
"url": "https://github.com/massedge/ZipStream-PHP"
|
10 |
-
}],
|
11 |
-
"require": {
|
12 |
-
"php": ">=7.0",
|
13 |
-
"maennchen/zipstream-php": "dev-php-7.0-compatibility"
|
14 |
-
},
|
15 |
-
"autoload": {
|
16 |
-
"psr-4": {"": "lib/"}
|
17 |
-
}
|
18 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
composer.lock
DELETED
@@ -1,180 +0,0 @@
|
|
1 |
-
{
|
2 |
-
"_readme": [
|
3 |
-
"This file locks the dependencies of your project to a known state",
|
4 |
-
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
5 |
-
"This file is @generated automatically"
|
6 |
-
],
|
7 |
-
"content-hash": "fe9624c85f0ff41a34d7c72e43c77f72",
|
8 |
-
"packages": [
|
9 |
-
{
|
10 |
-
"name": "maennchen/zipstream-php",
|
11 |
-
"version": "dev-php-7.0-compatibility",
|
12 |
-
"source": {
|
13 |
-
"type": "git",
|
14 |
-
"url": "https://github.com/massedge/ZipStream-PHP.git",
|
15 |
-
"reference": "9b0f04a9f158454dd579d11bff191427e4de0525"
|
16 |
-
},
|
17 |
-
"dist": {
|
18 |
-
"type": "zip",
|
19 |
-
"url": "https://api.github.com/repos/massedge/ZipStream-PHP/zipball/9b0f04a9f158454dd579d11bff191427e4de0525",
|
20 |
-
"reference": "9b0f04a9f158454dd579d11bff191427e4de0525",
|
21 |
-
"shasum": ""
|
22 |
-
},
|
23 |
-
"require": {
|
24 |
-
"ext-mbstring": "*",
|
25 |
-
"myclabs/php-enum": "^1.5",
|
26 |
-
"php": ">= 7.0",
|
27 |
-
"psr/http-message": "^1.0"
|
28 |
-
},
|
29 |
-
"require-dev": {
|
30 |
-
"ext-zip": "*",
|
31 |
-
"guzzlehttp/guzzle": ">= 6.3",
|
32 |
-
"mikey179/vfsstream": "^1.6",
|
33 |
-
"phpunit/phpunit": "^4.0"
|
34 |
-
},
|
35 |
-
"type": "library",
|
36 |
-
"autoload": {
|
37 |
-
"psr-4": {
|
38 |
-
"ZipStream\\": "src/"
|
39 |
-
}
|
40 |
-
},
|
41 |
-
"license": [
|
42 |
-
"MIT"
|
43 |
-
],
|
44 |
-
"authors": [
|
45 |
-
{
|
46 |
-
"name": "Paul Duncan",
|
47 |
-
"email": "pabs@pablotron.org"
|
48 |
-
},
|
49 |
-
{
|
50 |
-
"name": "Jonatan Männchen",
|
51 |
-
"email": "jonatan@maennchen.ch"
|
52 |
-
},
|
53 |
-
{
|
54 |
-
"name": "Jesse Donat",
|
55 |
-
"email": "donatj@gmail.com"
|
56 |
-
},
|
57 |
-
{
|
58 |
-
"name": "András Kolesár",
|
59 |
-
"email": "kolesar@kolesar.hu"
|
60 |
-
}
|
61 |
-
],
|
62 |
-
"description": "ZipStream is a library for dynamically streaming dynamic zip files from PHP without writing to the disk at all on the server.",
|
63 |
-
"keywords": [
|
64 |
-
"stream",
|
65 |
-
"zip"
|
66 |
-
],
|
67 |
-
"support": {
|
68 |
-
"source": "https://github.com/massedge/ZipStream-PHP/tree/dev-php-7.0-compatibility"
|
69 |
-
},
|
70 |
-
"time": "2019-04-30T19:51:44+00:00"
|
71 |
-
},
|
72 |
-
{
|
73 |
-
"name": "myclabs/php-enum",
|
74 |
-
"version": "1.6.6",
|
75 |
-
"source": {
|
76 |
-
"type": "git",
|
77 |
-
"url": "https://github.com/myclabs/php-enum.git",
|
78 |
-
"reference": "32c4202886c51fbe5cc3a7c34ec5c9a4a790345e"
|
79 |
-
},
|
80 |
-
"dist": {
|
81 |
-
"type": "zip",
|
82 |
-
"url": "https://api.github.com/repos/myclabs/php-enum/zipball/32c4202886c51fbe5cc3a7c34ec5c9a4a790345e",
|
83 |
-
"reference": "32c4202886c51fbe5cc3a7c34ec5c9a4a790345e",
|
84 |
-
"shasum": ""
|
85 |
-
},
|
86 |
-
"require": {
|
87 |
-
"ext-json": "*",
|
88 |
-
"php": ">=5.4"
|
89 |
-
},
|
90 |
-
"require-dev": {
|
91 |
-
"phpunit/phpunit": "^4.8.35|^5.7|^6.0",
|
92 |
-
"squizlabs/php_codesniffer": "1.*"
|
93 |
-
},
|
94 |
-
"type": "library",
|
95 |
-
"autoload": {
|
96 |
-
"psr-4": {
|
97 |
-
"MyCLabs\\Enum\\": "src/"
|
98 |
-
}
|
99 |
-
},
|
100 |
-
"notification-url": "https://packagist.org/downloads/",
|
101 |
-
"license": [
|
102 |
-
"MIT"
|
103 |
-
],
|
104 |
-
"authors": [
|
105 |
-
{
|
106 |
-
"name": "PHP Enum contributors",
|
107 |
-
"homepage": "https://github.com/myclabs/php-enum/graphs/contributors"
|
108 |
-
}
|
109 |
-
],
|
110 |
-
"description": "PHP Enum implementation",
|
111 |
-
"homepage": "http://github.com/myclabs/php-enum",
|
112 |
-
"keywords": [
|
113 |
-
"enum"
|
114 |
-
],
|
115 |
-
"time": "2019-02-04T21:18:49+00:00"
|
116 |
-
},
|
117 |
-
{
|
118 |
-
"name": "psr/http-message",
|
119 |
-
"version": "1.0.1",
|
120 |
-
"source": {
|
121 |
-
"type": "git",
|
122 |
-
"url": "https://github.com/php-fig/http-message.git",
|
123 |
-
"reference": "f6561bf28d520154e4b0ec72be95418abe6d9363"
|
124 |
-
},
|
125 |
-
"dist": {
|
126 |
-
"type": "zip",
|
127 |
-
"url": "https://api.github.com/repos/php-fig/http-message/zipball/f6561bf28d520154e4b0ec72be95418abe6d9363",
|
128 |
-
"reference": "f6561bf28d520154e4b0ec72be95418abe6d9363",
|
129 |
-
"shasum": ""
|
130 |
-
},
|
131 |
-
"require": {
|
132 |
-
"php": ">=5.3.0"
|
133 |
-
},
|
134 |
-
"type": "library",
|
135 |
-
"extra": {
|
136 |
-
"branch-alias": {
|
137 |
-
"dev-master": "1.0.x-dev"
|
138 |
-
}
|
139 |
-
},
|
140 |
-
"autoload": {
|
141 |
-
"psr-4": {
|
142 |
-
"Psr\\Http\\Message\\": "src/"
|
143 |
-
}
|
144 |
-
},
|
145 |
-
"notification-url": "https://packagist.org/downloads/",
|
146 |
-
"license": [
|
147 |
-
"MIT"
|
148 |
-
],
|
149 |
-
"authors": [
|
150 |
-
{
|
151 |
-
"name": "PHP-FIG",
|
152 |
-
"homepage": "http://www.php-fig.org/"
|
153 |
-
}
|
154 |
-
],
|
155 |
-
"description": "Common interface for HTTP messages",
|
156 |
-
"homepage": "https://github.com/php-fig/http-message",
|
157 |
-
"keywords": [
|
158 |
-
"http",
|
159 |
-
"http-message",
|
160 |
-
"psr",
|
161 |
-
"psr-7",
|
162 |
-
"request",
|
163 |
-
"response"
|
164 |
-
],
|
165 |
-
"time": "2016-08-06T14:39:51+00:00"
|
166 |
-
}
|
167 |
-
],
|
168 |
-
"packages-dev": [],
|
169 |
-
"aliases": [],
|
170 |
-
"minimum-stability": "stable",
|
171 |
-
"stability-flags": {
|
172 |
-
"maennchen/zipstream-php": 20
|
173 |
-
},
|
174 |
-
"prefer-stable": false,
|
175 |
-
"prefer-lowest": false,
|
176 |
-
"platform": {
|
177 |
-
"php": ">=7.0"
|
178 |
-
},
|
179 |
-
"platform-dev": []
|
180 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
index.php
CHANGED
@@ -3,7 +3,7 @@
|
|
3 |
Plugin Name: Export Media Library
|
4 |
Plugin URI: https://github.com/massedge/wordpress-plugin-export-media-library
|
5 |
Description: Allows admins to export media library files as a compressed zip archive.
|
6 |
-
Version:
|
7 |
Author: Mass Edge Inc.
|
8 |
Author URI: https://www.massedge.com/
|
9 |
License: GPL3
|
3 |
Plugin Name: Export Media Library
|
4 |
Plugin URI: https://github.com/massedge/wordpress-plugin-export-media-library
|
5 |
Description: Allows admins to export media library files as a compressed zip archive.
|
6 |
+
Version: 3.0.0
|
7 |
Author: Mass Edge Inc.
|
8 |
Author URI: https://www.massedge.com/
|
9 |
License: GPL3
|
lib/DependencyCheck.php
CHANGED
@@ -3,7 +3,7 @@
|
|
3 |
class MassEdgeWordPressPluginExportMediaLibraryDependencyCheck {
|
4 |
const PLUGIN_NAME = 'Export Media Library';
|
5 |
|
6 |
-
const MINIMUM_PHP_VERSION_REQUIRED = '7.
|
7 |
|
8 |
const MBSTRING_EXTENSION_NAME = 'mbstring';
|
9 |
|
3 |
class MassEdgeWordPressPluginExportMediaLibraryDependencyCheck {
|
4 |
const PLUGIN_NAME = 'Export Media Library';
|
5 |
|
6 |
+
const MINIMUM_PHP_VERSION_REQUIRED = '7.1';
|
7 |
|
8 |
const MBSTRING_EXTENSION_NAME = 'mbstring';
|
9 |
|
lib/MassEdge/WordPress/Plugin/ExportMediaLibrary/API.php
CHANGED
@@ -54,6 +54,7 @@ class API {
|
|
54 |
// create a new zipstream object
|
55 |
$archiveOptions = new ArchiveOptions();
|
56 |
$archiveOptions->setSendHttpHeaders(true);
|
|
|
57 |
$zip = new ZipStream($options['filename'], $archiveOptions);
|
58 |
|
59 |
$query = new \WP_Query();
|
54 |
// create a new zipstream object
|
55 |
$archiveOptions = new ArchiveOptions();
|
56 |
$archiveOptions->setSendHttpHeaders(true);
|
57 |
+
$archiveOptions->setFlushOutput(true);
|
58 |
$zip = new ZipStream($options['filename'], $archiveOptions);
|
59 |
|
60 |
$query = new \WP_Query();
|
readme.txt
CHANGED
@@ -2,9 +2,9 @@
|
|
2 |
Contributors: andrej.pavlovic
|
3 |
Tags: export media library, download media library, media library, export, download
|
4 |
Requires at least: 4.7.10
|
5 |
-
Tested up to: 5.
|
6 |
-
Requires PHP: 7.
|
7 |
-
Stable tag:
|
8 |
License: GPLv3
|
9 |
License URI: http://www.gnu.org/licenses/gpl-3.0.html
|
10 |
|
@@ -26,6 +26,10 @@ Allows users to export media library files as a compressed zip archive.
|
|
26 |
|
27 |
== Changelog ==
|
28 |
|
|
|
|
|
|
|
|
|
29 |
= 2.2.0 =
|
30 |
* added support for PHP 7.0
|
31 |
|
2 |
Contributors: andrej.pavlovic
|
3 |
Tags: export media library, download media library, media library, export, download
|
4 |
Requires at least: 4.7.10
|
5 |
+
Tested up to: 5.3
|
6 |
+
Requires PHP: 7.1
|
7 |
+
Stable tag: 3.0.0
|
8 |
License: GPLv3
|
9 |
License URI: http://www.gnu.org/licenses/gpl-3.0.html
|
10 |
|
26 |
|
27 |
== Changelog ==
|
28 |
|
29 |
+
= 3.0.0 =
|
30 |
+
* bumped minimum php version to 7.1
|
31 |
+
* flush buffer after every write in order to avoid exceeding memory
|
32 |
+
|
33 |
= 2.2.0 =
|
34 |
* added support for PHP 7.0
|
35 |
|
run.php
CHANGED
@@ -3,8 +3,12 @@
|
|
3 |
// must be loaded by the plugin index.php file
|
4 |
if (!defined('MASSEDGE_WORDPRESS_PLUGIN_EXPORT_MEDIA_LIBRARY_PLUGIN_PATH')) exit;
|
5 |
|
6 |
-
//
|
7 |
-
|
|
|
|
|
|
|
|
|
8 |
|
9 |
(new MassEdge\WordPress\Plugin\ExportMediaLibrary\Plugin([
|
10 |
'pluginPath' => MASSEDGE_WORDPRESS_PLUGIN_EXPORT_MEDIA_LIBRARY_PLUGIN_PATH,
|
3 |
// must be loaded by the plugin index.php file
|
4 |
if (!defined('MASSEDGE_WORDPRESS_PLUGIN_EXPORT_MEDIA_LIBRARY_PLUGIN_PATH')) exit;
|
5 |
|
6 |
+
// If main plugin class can't be found, use the local autoloader. Generally,
|
7 |
+
// local autoloader would not be required if the plugin is installed using
|
8 |
+
// composer, while a regular wordpress install will need the local autoloader.
|
9 |
+
if (!class_exists('MassEdge\\WordPress\\Plugin\\ExportMediaLibrary\\Plugin')) {
|
10 |
+
require 'vendor/autoload.php';
|
11 |
+
}
|
12 |
|
13 |
(new MassEdge\WordPress\Plugin\ExportMediaLibrary\Plugin([
|
14 |
'pluginPath' => MASSEDGE_WORDPRESS_PLUGIN_EXPORT_MEDIA_LIBRARY_PLUGIN_PATH,
|
vendor/autoload.php
ADDED
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
// autoload.php @generated by Composer
|
4 |
+
|
5 |
+
require_once __DIR__ . '/composer/autoload_real.php';
|
6 |
+
|
7 |
+
return ComposerAutoloaderInit70c1bea2cbce529378170e8f3fa2903d::getLoader();
|
vendor/composer/ClassLoader.php
ADDED
@@ -0,0 +1,445 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/*
|
4 |
+
* This file is part of Composer.
|
5 |
+
*
|
6 |
+
* (c) Nils Adermann <naderman@naderman.de>
|
7 |
+
* Jordi Boggiano <j.boggiano@seld.be>
|
8 |
+
*
|
9 |
+
* For the full copyright and license information, please view the LICENSE
|
10 |
+
* file that was distributed with this source code.
|
11 |
+
*/
|
12 |
+
|
13 |
+
namespace Composer\Autoload;
|
14 |
+
|
15 |
+
/**
|
16 |
+
* ClassLoader implements a PSR-0, PSR-4 and classmap class loader.
|
17 |
+
*
|
18 |
+
* $loader = new \Composer\Autoload\ClassLoader();
|
19 |
+
*
|
20 |
+
* // register classes with namespaces
|
21 |
+
* $loader->add('Symfony\Component', __DIR__.'/component');
|
22 |
+
* $loader->add('Symfony', __DIR__.'/framework');
|
23 |
+
*
|
24 |
+
* // activate the autoloader
|
25 |
+
* $loader->register();
|
26 |
+
*
|
27 |
+
* // to enable searching the include path (eg. for PEAR packages)
|
28 |
+
* $loader->setUseIncludePath(true);
|
29 |
+
*
|
30 |
+
* In this example, if you try to use a class in the Symfony\Component
|
31 |
+
* namespace or one of its children (Symfony\Component\Console for instance),
|
32 |
+
* the autoloader will first look for the class under the component/
|
33 |
+
* directory, and it will then fallback to the framework/ directory if not
|
34 |
+
* found before giving up.
|
35 |
+
*
|
36 |
+
* This class is loosely based on the Symfony UniversalClassLoader.
|
37 |
+
*
|
38 |
+
* @author Fabien Potencier <fabien@symfony.com>
|
39 |
+
* @author Jordi Boggiano <j.boggiano@seld.be>
|
40 |
+
* @see http://www.php-fig.org/psr/psr-0/
|
41 |
+
* @see http://www.php-fig.org/psr/psr-4/
|
42 |
+
*/
|
43 |
+
class ClassLoader
|
44 |
+
{
|
45 |
+
// PSR-4
|
46 |
+
private $prefixLengthsPsr4 = array();
|
47 |
+
private $prefixDirsPsr4 = array();
|
48 |
+
private $fallbackDirsPsr4 = array();
|
49 |
+
|
50 |
+
// PSR-0
|
51 |
+
private $prefixesPsr0 = array();
|
52 |
+
private $fallbackDirsPsr0 = array();
|
53 |
+
|
54 |
+
private $useIncludePath = false;
|
55 |
+
private $classMap = array();
|
56 |
+
private $classMapAuthoritative = false;
|
57 |
+
private $missingClasses = array();
|
58 |
+
private $apcuPrefix;
|
59 |
+
|
60 |
+
public function getPrefixes()
|
61 |
+
{
|
62 |
+
if (!empty($this->prefixesPsr0)) {
|
63 |
+
return call_user_func_array('array_merge', $this->prefixesPsr0);
|
64 |
+
}
|
65 |
+
|
66 |
+
return array();
|
67 |
+
}
|
68 |
+
|
69 |
+
public function getPrefixesPsr4()
|
70 |
+
{
|
71 |
+
return $this->prefixDirsPsr4;
|
72 |
+
}
|
73 |
+
|
74 |
+
public function getFallbackDirs()
|
75 |
+
{
|
76 |
+
return $this->fallbackDirsPsr0;
|
77 |
+
}
|
78 |
+
|
79 |
+
public function getFallbackDirsPsr4()
|
80 |
+
{
|
81 |
+
return $this->fallbackDirsPsr4;
|
82 |
+
}
|
83 |
+
|
84 |
+
public function getClassMap()
|
85 |
+
{
|
86 |
+
return $this->classMap;
|
87 |
+
}
|
88 |
+
|
89 |
+
/**
|
90 |
+
* @param array $classMap Class to filename map
|
91 |
+
*/
|
92 |
+
public function addClassMap(array $classMap)
|
93 |
+
{
|
94 |
+
if ($this->classMap) {
|
95 |
+
$this->classMap = array_merge($this->classMap, $classMap);
|
96 |
+
} else {
|
97 |
+
$this->classMap = $classMap;
|
98 |
+
}
|
99 |
+
}
|
100 |
+
|
101 |
+
/**
|
102 |
+
* Registers a set of PSR-0 directories for a given prefix, either
|
103 |
+
* appending or prepending to the ones previously set for this prefix.
|
104 |
+
*
|
105 |
+
* @param string $prefix The prefix
|
106 |
+
* @param array|string $paths The PSR-0 root directories
|
107 |
+
* @param bool $prepend Whether to prepend the directories
|
108 |
+
*/
|
109 |
+
public function add($prefix, $paths, $prepend = false)
|
110 |
+
{
|
111 |
+
if (!$prefix) {
|
112 |
+
if ($prepend) {
|
113 |
+
$this->fallbackDirsPsr0 = array_merge(
|
114 |
+
(array) $paths,
|
115 |
+
$this->fallbackDirsPsr0
|
116 |
+
);
|
117 |
+
} else {
|
118 |
+
$this->fallbackDirsPsr0 = array_merge(
|
119 |
+
$this->fallbackDirsPsr0,
|
120 |
+
(array) $paths
|
121 |
+
);
|
122 |
+
}
|
123 |
+
|
124 |
+
return;
|
125 |
+
}
|
126 |
+
|
127 |
+
$first = $prefix[0];
|
128 |
+
if (!isset($this->prefixesPsr0[$first][$prefix])) {
|
129 |
+
$this->prefixesPsr0[$first][$prefix] = (array) $paths;
|
130 |
+
|
131 |
+
return;
|
132 |
+
}
|
133 |
+
if ($prepend) {
|
134 |
+
$this->prefixesPsr0[$first][$prefix] = array_merge(
|
135 |
+
(array) $paths,
|
136 |
+
$this->prefixesPsr0[$first][$prefix]
|
137 |
+
);
|
138 |
+
} else {
|
139 |
+
$this->prefixesPsr0[$first][$prefix] = array_merge(
|
140 |
+
$this->prefixesPsr0[$first][$prefix],
|
141 |
+
(array) $paths
|
142 |
+
);
|
143 |
+
}
|
144 |
+
}
|
145 |
+
|
146 |
+
/**
|
147 |
+
* Registers a set of PSR-4 directories for a given namespace, either
|
148 |
+
* appending or prepending to the ones previously set for this namespace.
|
149 |
+
*
|
150 |
+
* @param string $prefix The prefix/namespace, with trailing '\\'
|
151 |
+
* @param array|string $paths The PSR-4 base directories
|
152 |
+
* @param bool $prepend Whether to prepend the directories
|
153 |
+
*
|
154 |
+
* @throws \InvalidArgumentException
|
155 |
+
*/
|
156 |
+
public function addPsr4($prefix, $paths, $prepend = false)
|
157 |
+
{
|
158 |
+
if (!$prefix) {
|
159 |
+
// Register directories for the root namespace.
|
160 |
+
if ($prepend) {
|
161 |
+
$this->fallbackDirsPsr4 = array_merge(
|
162 |
+
(array) $paths,
|
163 |
+
$this->fallbackDirsPsr4
|
164 |
+
);
|
165 |
+
} else {
|
166 |
+
$this->fallbackDirsPsr4 = array_merge(
|
167 |
+
$this->fallbackDirsPsr4,
|
168 |
+
(array) $paths
|
169 |
+
);
|
170 |
+
}
|
171 |
+
} elseif (!isset($this->prefixDirsPsr4[$prefix])) {
|
172 |
+
// Register directories for a new namespace.
|
173 |
+
$length = strlen($prefix);
|
174 |
+
if ('\\' !== $prefix[$length - 1]) {
|
175 |
+
throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
|
176 |
+
}
|
177 |
+
$this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
|
178 |
+
$this->prefixDirsPsr4[$prefix] = (array) $paths;
|
179 |
+
} elseif ($prepend) {
|
180 |
+
// Prepend directories for an already registered namespace.
|
181 |
+
$this->prefixDirsPsr4[$prefix] = array_merge(
|
182 |
+
(array) $paths,
|
183 |
+
$this->prefixDirsPsr4[$prefix]
|
184 |
+
);
|
185 |
+
} else {
|
186 |
+
// Append directories for an already registered namespace.
|
187 |
+
$this->prefixDirsPsr4[$prefix] = array_merge(
|
188 |
+
$this->prefixDirsPsr4[$prefix],
|
189 |
+
(array) $paths
|
190 |
+
);
|
191 |
+
}
|
192 |
+
}
|
193 |
+
|
194 |
+
/**
|
195 |
+
* Registers a set of PSR-0 directories for a given prefix,
|
196 |
+
* replacing any others previously set for this prefix.
|
197 |
+
*
|
198 |
+
* @param string $prefix The prefix
|
199 |
+
* @param array|string $paths The PSR-0 base directories
|
200 |
+
*/
|
201 |
+
public function set($prefix, $paths)
|
202 |
+
{
|
203 |
+
if (!$prefix) {
|
204 |
+
$this->fallbackDirsPsr0 = (array) $paths;
|
205 |
+
} else {
|
206 |
+
$this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths;
|
207 |
+
}
|
208 |
+
}
|
209 |
+
|
210 |
+
/**
|
211 |
+
* Registers a set of PSR-4 directories for a given namespace,
|
212 |
+
* replacing any others previously set for this namespace.
|
213 |
+
*
|
214 |
+
* @param string $prefix The prefix/namespace, with trailing '\\'
|
215 |
+
* @param array|string $paths The PSR-4 base directories
|
216 |
+
*
|
217 |
+
* @throws \InvalidArgumentException
|
218 |
+
*/
|
219 |
+
public function setPsr4($prefix, $paths)
|
220 |
+
{
|
221 |
+
if (!$prefix) {
|
222 |
+
$this->fallbackDirsPsr4 = (array) $paths;
|
223 |
+
} else {
|
224 |
+
$length = strlen($prefix);
|
225 |
+
if ('\\' !== $prefix[$length - 1]) {
|
226 |
+
throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
|
227 |
+
}
|
228 |
+
$this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
|
229 |
+
$this->prefixDirsPsr4[$prefix] = (array) $paths;
|
230 |
+
}
|
231 |
+
}
|
232 |
+
|
233 |
+
/**
|
234 |
+
* Turns on searching the include path for class files.
|
235 |
+
*
|
236 |
+
* @param bool $useIncludePath
|
237 |
+
*/
|
238 |
+
public function setUseIncludePath($useIncludePath)
|
239 |
+
{
|
240 |
+
$this->useIncludePath = $useIncludePath;
|
241 |
+
}
|
242 |
+
|
243 |
+
/**
|
244 |
+
* Can be used to check if the autoloader uses the include path to check
|
245 |
+
* for classes.
|
246 |
+
*
|
247 |
+
* @return bool
|
248 |
+
*/
|
249 |
+
public function getUseIncludePath()
|
250 |
+
{
|
251 |
+
return $this->useIncludePath;
|
252 |
+
}
|
253 |
+
|
254 |
+
/**
|
255 |
+
* Turns off searching the prefix and fallback directories for classes
|
256 |
+
* that have not been registered with the class map.
|
257 |
+
*
|
258 |
+
* @param bool $classMapAuthoritative
|
259 |
+
*/
|
260 |
+
public function setClassMapAuthoritative($classMapAuthoritative)
|
261 |
+
{
|
262 |
+
$this->classMapAuthoritative = $classMapAuthoritative;
|
263 |
+
}
|
264 |
+
|
265 |
+
/**
|
266 |
+
* Should class lookup fail if not found in the current class map?
|
267 |
+
*
|
268 |
+
* @return bool
|
269 |
+
*/
|
270 |
+
public function isClassMapAuthoritative()
|
271 |
+
{
|
272 |
+
return $this->classMapAuthoritative;
|
273 |
+
}
|
274 |
+
|
275 |
+
/**
|
276 |
+
* APCu prefix to use to cache found/not-found classes, if the extension is enabled.
|
277 |
+
*
|
278 |
+
* @param string|null $apcuPrefix
|
279 |
+
*/
|
280 |
+
public function setApcuPrefix($apcuPrefix)
|
281 |
+
{
|
282 |
+
$this->apcuPrefix = function_exists('apcu_fetch') && filter_var(ini_get('apc.enabled'), FILTER_VALIDATE_BOOLEAN) ? $apcuPrefix : null;
|
283 |
+
}
|
284 |
+
|
285 |
+
/**
|
286 |
+
* The APCu prefix in use, or null if APCu caching is not enabled.
|
287 |
+
*
|
288 |
+
* @return string|null
|
289 |
+
*/
|
290 |
+
public function getApcuPrefix()
|
291 |
+
{
|
292 |
+
return $this->apcuPrefix;
|
293 |
+
}
|
294 |
+
|
295 |
+
/**
|
296 |
+
* Registers this instance as an autoloader.
|
297 |
+
*
|
298 |
+
* @param bool $prepend Whether to prepend the autoloader or not
|
299 |
+
*/
|
300 |
+
public function register($prepend = false)
|
301 |
+
{
|
302 |
+
spl_autoload_register(array($this, 'loadClass'), true, $prepend);
|
303 |
+
}
|
304 |
+
|
305 |
+
/**
|
306 |
+
* Unregisters this instance as an autoloader.
|
307 |
+
*/
|
308 |
+
public function unregister()
|
309 |
+
{
|
310 |
+
spl_autoload_unregister(array($this, 'loadClass'));
|
311 |
+
}
|
312 |
+
|
313 |
+
/**
|
314 |
+
* Loads the given class or interface.
|
315 |
+
*
|
316 |
+
* @param string $class The name of the class
|
317 |
+
* @return bool|null True if loaded, null otherwise
|
318 |
+
*/
|
319 |
+
public function loadClass($class)
|
320 |
+
{
|
321 |
+
if ($file = $this->findFile($class)) {
|
322 |
+
includeFile($file);
|
323 |
+
|
324 |
+
return true;
|
325 |
+
}
|
326 |
+
}
|
327 |
+
|
328 |
+
/**
|
329 |
+
* Finds the path to the file where the class is defined.
|
330 |
+
*
|
331 |
+
* @param string $class The name of the class
|
332 |
+
*
|
333 |
+
* @return string|false The path if found, false otherwise
|
334 |
+
*/
|
335 |
+
public function findFile($class)
|
336 |
+
{
|
337 |
+
// class map lookup
|
338 |
+
if (isset($this->classMap[$class])) {
|
339 |
+
return $this->classMap[$class];
|
340 |
+
}
|
341 |
+
if ($this->classMapAuthoritative || isset($this->missingClasses[$class])) {
|
342 |
+
return false;
|
343 |
+
}
|
344 |
+
if (null !== $this->apcuPrefix) {
|
345 |
+
$file = apcu_fetch($this->apcuPrefix.$class, $hit);
|
346 |
+
if ($hit) {
|
347 |
+
return $file;
|
348 |
+
}
|
349 |
+
}
|
350 |
+
|
351 |
+
$file = $this->findFileWithExtension($class, '.php');
|
352 |
+
|
353 |
+
// Search for Hack files if we are running on HHVM
|
354 |
+
if (false === $file && defined('HHVM_VERSION')) {
|
355 |
+
$file = $this->findFileWithExtension($class, '.hh');
|
356 |
+
}
|
357 |
+
|
358 |
+
if (null !== $this->apcuPrefix) {
|
359 |
+
apcu_add($this->apcuPrefix.$class, $file);
|
360 |
+
}
|
361 |
+
|
362 |
+
if (false === $file) {
|
363 |
+
// Remember that this class does not exist.
|
364 |
+
$this->missingClasses[$class] = true;
|
365 |
+
}
|
366 |
+
|
367 |
+
return $file;
|
368 |
+
}
|
369 |
+
|
370 |
+
private function findFileWithExtension($class, $ext)
|
371 |
+
{
|
372 |
+
// PSR-4 lookup
|
373 |
+
$logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext;
|
374 |
+
|
375 |
+
$first = $class[0];
|
376 |
+
if (isset($this->prefixLengthsPsr4[$first])) {
|
377 |
+
$subPath = $class;
|
378 |
+
while (false !== $lastPos = strrpos($subPath, '\\')) {
|
379 |
+
$subPath = substr($subPath, 0, $lastPos);
|
380 |
+
$search = $subPath . '\\';
|
381 |
+
if (isset($this->prefixDirsPsr4[$search])) {
|
382 |
+
$pathEnd = DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $lastPos + 1);
|
383 |
+
foreach ($this->prefixDirsPsr4[$search] as $dir) {
|
384 |
+
if (file_exists($file = $dir . $pathEnd)) {
|
385 |
+
return $file;
|
386 |
+
}
|
387 |
+
}
|
388 |
+
}
|
389 |
+
}
|
390 |
+
}
|
391 |
+
|
392 |
+
// PSR-4 fallback dirs
|
393 |
+
foreach ($this->fallbackDirsPsr4 as $dir) {
|
394 |
+
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) {
|
395 |
+
return $file;
|
396 |
+
}
|
397 |
+
}
|
398 |
+
|
399 |
+
// PSR-0 lookup
|
400 |
+
if (false !== $pos = strrpos($class, '\\')) {
|
401 |
+
// namespaced class name
|
402 |
+
$logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1)
|
403 |
+
. strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR);
|
404 |
+
} else {
|
405 |
+
// PEAR-like class name
|
406 |
+
$logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext;
|
407 |
+
}
|
408 |
+
|
409 |
+
if (isset($this->prefixesPsr0[$first])) {
|
410 |
+
foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) {
|
411 |
+
if (0 === strpos($class, $prefix)) {
|
412 |
+
foreach ($dirs as $dir) {
|
413 |
+
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
|
414 |
+
return $file;
|
415 |
+
}
|
416 |
+
}
|
417 |
+
}
|
418 |
+
}
|
419 |
+
}
|
420 |
+
|
421 |
+
// PSR-0 fallback dirs
|
422 |
+
foreach ($this->fallbackDirsPsr0 as $dir) {
|
423 |
+
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
|
424 |
+
return $file;
|
425 |
+
}
|
426 |
+
}
|
427 |
+
|
428 |
+
// PSR-0 include paths.
|
429 |
+
if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) {
|
430 |
+
return $file;
|
431 |
+
}
|
432 |
+
|
433 |
+
return false;
|
434 |
+
}
|
435 |
+
}
|
436 |
+
|
437 |
+
/**
|
438 |
+
* Scope isolated include.
|
439 |
+
*
|
440 |
+
* Prevents access to $this/self from included files.
|
441 |
+
*/
|
442 |
+
function includeFile($file)
|
443 |
+
{
|
444 |
+
include $file;
|
445 |
+
}
|
vendor/composer/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
|
2 |
+
Copyright (c) Nils Adermann, Jordi Boggiano
|
3 |
+
|
4 |
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
5 |
+
of this software and associated documentation files (the "Software"), to deal
|
6 |
+
in the Software without restriction, including without limitation the rights
|
7 |
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
8 |
+
copies of the Software, and to permit persons to whom the Software is furnished
|
9 |
+
to do so, subject to the following conditions:
|
10 |
+
|
11 |
+
The above copyright notice and this permission notice shall be included in all
|
12 |
+
copies or substantial portions of the Software.
|
13 |
+
|
14 |
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
15 |
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
16 |
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
17 |
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
18 |
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
19 |
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
20 |
+
THE SOFTWARE.
|
21 |
+
|
vendor/composer/autoload_classmap.php
ADDED
@@ -0,0 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
// autoload_classmap.php @generated by Composer
|
4 |
+
|
5 |
+
$vendorDir = dirname(dirname(__FILE__));
|
6 |
+
$baseDir = dirname($vendorDir);
|
7 |
+
|
8 |
+
return array(
|
9 |
+
);
|
vendor/composer/autoload_namespaces.php
ADDED
@@ -0,0 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
// autoload_namespaces.php @generated by Composer
|
4 |
+
|
5 |
+
$vendorDir = dirname(dirname(__FILE__));
|
6 |
+
$baseDir = dirname($vendorDir);
|
7 |
+
|
8 |
+
return array(
|
9 |
+
);
|
vendor/composer/autoload_psr4.php
ADDED
@@ -0,0 +1,13 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
// autoload_psr4.php @generated by Composer
|
4 |
+
|
5 |
+
$vendorDir = dirname(dirname(__FILE__));
|
6 |
+
$baseDir = dirname($vendorDir);
|
7 |
+
|
8 |
+
return array(
|
9 |
+
'ZipStream\\' => array($vendorDir . '/maennchen/zipstream-php/src'),
|
10 |
+
'Psr\\Http\\Message\\' => array($vendorDir . '/psr/http-message/src'),
|
11 |
+
'MyCLabs\\Enum\\' => array($vendorDir . '/myclabs/php-enum/src'),
|
12 |
+
'' => array($baseDir . '/lib'),
|
13 |
+
);
|
vendor/composer/autoload_real.php
ADDED
@@ -0,0 +1,52 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
// autoload_real.php @generated by Composer
|
4 |
+
|
5 |
+
class ComposerAutoloaderInit70c1bea2cbce529378170e8f3fa2903d
|
6 |
+
{
|
7 |
+
private static $loader;
|
8 |
+
|
9 |
+
public static function loadClassLoader($class)
|
10 |
+
{
|
11 |
+
if ('Composer\Autoload\ClassLoader' === $class) {
|
12 |
+
require __DIR__ . '/ClassLoader.php';
|
13 |
+
}
|
14 |
+
}
|
15 |
+
|
16 |
+
public static function getLoader()
|
17 |
+
{
|
18 |
+
if (null !== self::$loader) {
|
19 |
+
return self::$loader;
|
20 |
+
}
|
21 |
+
|
22 |
+
spl_autoload_register(array('ComposerAutoloaderInit70c1bea2cbce529378170e8f3fa2903d', 'loadClassLoader'), true, true);
|
23 |
+
self::$loader = $loader = new \Composer\Autoload\ClassLoader();
|
24 |
+
spl_autoload_unregister(array('ComposerAutoloaderInit70c1bea2cbce529378170e8f3fa2903d', 'loadClassLoader'));
|
25 |
+
|
26 |
+
$useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
|
27 |
+
if ($useStaticLoader) {
|
28 |
+
require_once __DIR__ . '/autoload_static.php';
|
29 |
+
|
30 |
+
call_user_func(\Composer\Autoload\ComposerStaticInit70c1bea2cbce529378170e8f3fa2903d::getInitializer($loader));
|
31 |
+
} else {
|
32 |
+
$map = require __DIR__ . '/autoload_namespaces.php';
|
33 |
+
foreach ($map as $namespace => $path) {
|
34 |
+
$loader->set($namespace, $path);
|
35 |
+
}
|
36 |
+
|
37 |
+
$map = require __DIR__ . '/autoload_psr4.php';
|
38 |
+
foreach ($map as $namespace => $path) {
|
39 |
+
$loader->setPsr4($namespace, $path);
|
40 |
+
}
|
41 |
+
|
42 |
+
$classMap = require __DIR__ . '/autoload_classmap.php';
|
43 |
+
if ($classMap) {
|
44 |
+
$loader->addClassMap($classMap);
|
45 |
+
}
|
46 |
+
}
|
47 |
+
|
48 |
+
$loader->register(true);
|
49 |
+
|
50 |
+
return $loader;
|
51 |
+
}
|
52 |
+
}
|
vendor/composer/autoload_static.php
ADDED
@@ -0,0 +1,52 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
// autoload_static.php @generated by Composer
|
4 |
+
|
5 |
+
namespace Composer\Autoload;
|
6 |
+
|
7 |
+
class ComposerStaticInit70c1bea2cbce529378170e8f3fa2903d
|
8 |
+
{
|
9 |
+
public static $prefixLengthsPsr4 = array (
|
10 |
+
'Z' =>
|
11 |
+
array (
|
12 |
+
'ZipStream\\' => 10,
|
13 |
+
),
|
14 |
+
'P' =>
|
15 |
+
array (
|
16 |
+
'Psr\\Http\\Message\\' => 17,
|
17 |
+
),
|
18 |
+
'M' =>
|
19 |
+
array (
|
20 |
+
'MyCLabs\\Enum\\' => 13,
|
21 |
+
),
|
22 |
+
);
|
23 |
+
|
24 |
+
public static $prefixDirsPsr4 = array (
|
25 |
+
'ZipStream\\' =>
|
26 |
+
array (
|
27 |
+
0 => __DIR__ . '/..' . '/maennchen/zipstream-php/src',
|
28 |
+
),
|
29 |
+
'Psr\\Http\\Message\\' =>
|
30 |
+
array (
|
31 |
+
0 => __DIR__ . '/..' . '/psr/http-message/src',
|
32 |
+
),
|
33 |
+
'MyCLabs\\Enum\\' =>
|
34 |
+
array (
|
35 |
+
0 => __DIR__ . '/..' . '/myclabs/php-enum/src',
|
36 |
+
),
|
37 |
+
);
|
38 |
+
|
39 |
+
public static $fallbackDirsPsr4 = array (
|
40 |
+
0 => __DIR__ . '/../..' . '/lib',
|
41 |
+
);
|
42 |
+
|
43 |
+
public static function getInitializer(ClassLoader $loader)
|
44 |
+
{
|
45 |
+
return \Closure::bind(function () use ($loader) {
|
46 |
+
$loader->prefixLengthsPsr4 = ComposerStaticInit70c1bea2cbce529378170e8f3fa2903d::$prefixLengthsPsr4;
|
47 |
+
$loader->prefixDirsPsr4 = ComposerStaticInit70c1bea2cbce529378170e8f3fa2903d::$prefixDirsPsr4;
|
48 |
+
$loader->fallbackDirsPsr4 = ComposerStaticInit70c1bea2cbce529378170e8f3fa2903d::$fallbackDirsPsr4;
|
49 |
+
|
50 |
+
}, null, ClassLoader::class);
|
51 |
+
}
|
52 |
+
}
|
vendor/composer/installed.json
ADDED
@@ -0,0 +1,164 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
[
|
2 |
+
{
|
3 |
+
"name": "maennchen/zipstream-php",
|
4 |
+
"version": "1.2.0",
|
5 |
+
"version_normalized": "1.2.0.0",
|
6 |
+
"source": {
|
7 |
+
"type": "git",
|
8 |
+
"url": "https://github.com/maennchen/ZipStream-PHP.git",
|
9 |
+
"reference": "6373eefe0b3274d7b702d81f2c99aa977ff97dc2"
|
10 |
+
},
|
11 |
+
"dist": {
|
12 |
+
"type": "zip",
|
13 |
+
"url": "https://api.github.com/repos/maennchen/ZipStream-PHP/zipball/6373eefe0b3274d7b702d81f2c99aa977ff97dc2",
|
14 |
+
"reference": "6373eefe0b3274d7b702d81f2c99aa977ff97dc2",
|
15 |
+
"shasum": ""
|
16 |
+
},
|
17 |
+
"require": {
|
18 |
+
"ext-mbstring": "*",
|
19 |
+
"myclabs/php-enum": "^1.5",
|
20 |
+
"php": ">= 7.1",
|
21 |
+
"psr/http-message": "^1.0"
|
22 |
+
},
|
23 |
+
"require-dev": {
|
24 |
+
"ext-zip": "*",
|
25 |
+
"guzzlehttp/guzzle": ">= 6.3",
|
26 |
+
"mikey179/vfsstream": "^1.6",
|
27 |
+
"phpunit/phpunit": ">= 7.5"
|
28 |
+
},
|
29 |
+
"time": "2019-07-17T11:01:58+00:00",
|
30 |
+
"type": "library",
|
31 |
+
"installation-source": "source",
|
32 |
+
"autoload": {
|
33 |
+
"psr-4": {
|
34 |
+
"ZipStream\\": "src/"
|
35 |
+
}
|
36 |
+
},
|
37 |
+
"notification-url": "https://packagist.org/downloads/",
|
38 |
+
"license": [
|
39 |
+
"MIT"
|
40 |
+
],
|
41 |
+
"authors": [
|
42 |
+
{
|
43 |
+
"name": "Paul Duncan",
|
44 |
+
"email": "pabs@pablotron.org"
|
45 |
+
},
|
46 |
+
{
|
47 |
+
"name": "Jesse Donat",
|
48 |
+
"email": "donatj@gmail.com"
|
49 |
+
},
|
50 |
+
{
|
51 |
+
"name": "Jonatan Männchen",
|
52 |
+
"email": "jonatan@maennchen.ch"
|
53 |
+
},
|
54 |
+
{
|
55 |
+
"name": "András Kolesár",
|
56 |
+
"email": "kolesar@kolesar.hu"
|
57 |
+
}
|
58 |
+
],
|
59 |
+
"description": "ZipStream is a library for dynamically streaming dynamic zip files from PHP without writing to the disk at all on the server.",
|
60 |
+
"keywords": [
|
61 |
+
"stream",
|
62 |
+
"zip"
|
63 |
+
]
|
64 |
+
},
|
65 |
+
{
|
66 |
+
"name": "myclabs/php-enum",
|
67 |
+
"version": "1.7.2",
|
68 |
+
"version_normalized": "1.7.2.0",
|
69 |
+
"source": {
|
70 |
+
"type": "git",
|
71 |
+
"url": "https://github.com/myclabs/php-enum.git",
|
72 |
+
"reference": "45f01adf6922df6082bcda36619deb466e826acf"
|
73 |
+
},
|
74 |
+
"dist": {
|
75 |
+
"type": "zip",
|
76 |
+
"url": "https://api.github.com/repos/myclabs/php-enum/zipball/45f01adf6922df6082bcda36619deb466e826acf",
|
77 |
+
"reference": "45f01adf6922df6082bcda36619deb466e826acf",
|
78 |
+
"shasum": ""
|
79 |
+
},
|
80 |
+
"require": {
|
81 |
+
"ext-json": "*",
|
82 |
+
"php": ">=7.1"
|
83 |
+
},
|
84 |
+
"require-dev": {
|
85 |
+
"phpunit/phpunit": "^4.8.35|^5.7|^6.0",
|
86 |
+
"squizlabs/php_codesniffer": "1.*"
|
87 |
+
},
|
88 |
+
"time": "2019-08-19T13:53:00+00:00",
|
89 |
+
"type": "library",
|
90 |
+
"installation-source": "dist",
|
91 |
+
"autoload": {
|
92 |
+
"psr-4": {
|
93 |
+
"MyCLabs\\Enum\\": "src/"
|
94 |
+
}
|
95 |
+
},
|
96 |
+
"notification-url": "https://packagist.org/downloads/",
|
97 |
+
"license": [
|
98 |
+
"MIT"
|
99 |
+
],
|
100 |
+
"authors": [
|
101 |
+
{
|
102 |
+
"name": "PHP Enum contributors",
|
103 |
+
"homepage": "https://github.com/myclabs/php-enum/graphs/contributors"
|
104 |
+
}
|
105 |
+
],
|
106 |
+
"description": "PHP Enum implementation",
|
107 |
+
"homepage": "http://github.com/myclabs/php-enum",
|
108 |
+
"keywords": [
|
109 |
+
"enum"
|
110 |
+
]
|
111 |
+
},
|
112 |
+
{
|
113 |
+
"name": "psr/http-message",
|
114 |
+
"version": "1.0.1",
|
115 |
+
"version_normalized": "1.0.1.0",
|
116 |
+
"source": {
|
117 |
+
"type": "git",
|
118 |
+
"url": "https://github.com/php-fig/http-message.git",
|
119 |
+
"reference": "f6561bf28d520154e4b0ec72be95418abe6d9363"
|
120 |
+
},
|
121 |
+
"dist": {
|
122 |
+
"type": "zip",
|
123 |
+
"url": "https://api.github.com/repos/php-fig/http-message/zipball/f6561bf28d520154e4b0ec72be95418abe6d9363",
|
124 |
+
"reference": "f6561bf28d520154e4b0ec72be95418abe6d9363",
|
125 |
+
"shasum": ""
|
126 |
+
},
|
127 |
+
"require": {
|
128 |
+
"php": ">=5.3.0"
|
129 |
+
},
|
130 |
+
"time": "2016-08-06T14:39:51+00:00",
|
131 |
+
"type": "library",
|
132 |
+
"extra": {
|
133 |
+
"branch-alias": {
|
134 |
+
"dev-master": "1.0.x-dev"
|
135 |
+
}
|
136 |
+
},
|
137 |
+
"installation-source": "dist",
|
138 |
+
"autoload": {
|
139 |
+
"psr-4": {
|
140 |
+
"Psr\\Http\\Message\\": "src/"
|
141 |
+
}
|
142 |
+
},
|
143 |
+
"notification-url": "https://packagist.org/downloads/",
|
144 |
+
"license": [
|
145 |
+
"MIT"
|
146 |
+
],
|
147 |
+
"authors": [
|
148 |
+
{
|
149 |
+
"name": "PHP-FIG",
|
150 |
+
"homepage": "http://www.php-fig.org/"
|
151 |
+
}
|
152 |
+
],
|
153 |
+
"description": "Common interface for HTTP messages",
|
154 |
+
"homepage": "https://github.com/php-fig/http-message",
|
155 |
+
"keywords": [
|
156 |
+
"http",
|
157 |
+
"http-message",
|
158 |
+
"psr",
|
159 |
+
"psr-7",
|
160 |
+
"request",
|
161 |
+
"response"
|
162 |
+
]
|
163 |
+
}
|
164 |
+
]
|
vendor/maennchen/zipstream-php/.gitignore
ADDED
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
clover.xml
|
2 |
+
composer.lock
|
3 |
+
coverage.clover
|
4 |
+
.idea
|
5 |
+
phpunit.xml
|
6 |
+
vendor
|
vendor/maennchen/zipstream-php/.travis.yml
ADDED
@@ -0,0 +1,12 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
language: php
|
2 |
+
dist: trusty
|
3 |
+
sudo: false
|
4 |
+
php:
|
5 |
+
- 7.1
|
6 |
+
- 7.2
|
7 |
+
- 7.3
|
8 |
+
install: composer install
|
9 |
+
script: ./vendor/bin/phpunit --coverage-clover=coverage.clover
|
10 |
+
after_script:
|
11 |
+
- wget https://scrutinizer-ci.com/ocular.phar
|
12 |
+
- php ocular.phar code-coverage:upload --format=php-clover coverage.clover
|
vendor/maennchen/zipstream-php/CHANGELOG.md
ADDED
@@ -0,0 +1,35 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# CHANGELOG for ZipStream-PHP
|
2 |
+
|
3 |
+
All notable changes to this project will be documented in this file.
|
4 |
+
|
5 |
+
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
|
6 |
+
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
|
7 |
+
|
8 |
+
## [1.2.0] - 2019-07-11
|
9 |
+
|
10 |
+
### Added
|
11 |
+
- Option to flush output buffer after every write (#122)
|
12 |
+
|
13 |
+
## [1.1.0] - 2019-04-30
|
14 |
+
|
15 |
+
### Fixed
|
16 |
+
- Honor last-modified timestamps set via `ZipStream\Option\File::setTime()` (#106)
|
17 |
+
- Documentation regarding output of HTTP headers
|
18 |
+
- Test warnings with PHPUnit (#109)
|
19 |
+
|
20 |
+
### Added
|
21 |
+
- Test for FileNotReadableException (#114)
|
22 |
+
- Size attribute to File options (#113)
|
23 |
+
- Tests on PHP 7.3 (#108)
|
24 |
+
|
25 |
+
## [1.0.0] - 2019-04-17
|
26 |
+
|
27 |
+
### Breaking changes
|
28 |
+
- Mininum PHP version is now 7.1
|
29 |
+
- Options are now passed to the ZipStream object via the Option\Archive object. See the wiki for available options and code examples
|
30 |
+
|
31 |
+
### Added
|
32 |
+
- Add large file support with Zip64 headers
|
33 |
+
|
34 |
+
### Changed
|
35 |
+
- Major refactoring and code cleanup
|
vendor/maennchen/zipstream-php/CONTRIBUTING.md
ADDED
@@ -0,0 +1,25 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# ZipStream Readme for Contributors
|
2 |
+
## Code styling
|
3 |
+
### Indention
|
4 |
+
For spaces are used to indent code. The convention is [K&R](http://en.wikipedia.org/wiki/Indent_style#K&R)
|
5 |
+
|
6 |
+
### Comments
|
7 |
+
Double Slashes are used for an one line comment.
|
8 |
+
|
9 |
+
Classes, Variables, Methods etc:
|
10 |
+
|
11 |
+
```php
|
12 |
+
/**
|
13 |
+
* My comment
|
14 |
+
*
|
15 |
+
* @myanotation like @param etc.
|
16 |
+
*/
|
17 |
+
```
|
18 |
+
|
19 |
+
## Pull requests
|
20 |
+
Feel free to submit pull requests.
|
21 |
+
|
22 |
+
## Testing
|
23 |
+
For every new feature please write a new PHPUnit test.
|
24 |
+
|
25 |
+
Before every commit execute `./vendor/bin/phpunit` to check if your changes wrecked something:
|
vendor/maennchen/zipstream-php/LICENSE
ADDED
@@ -0,0 +1,24 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
MIT License
|
2 |
+
|
3 |
+
Copyright (C) 2007-2009 Paul Duncan <pabs@pablotron.org>
|
4 |
+
Copyright (C) 2014 Jonatan Männchen <jonatan@maennchen.ch>
|
5 |
+
Copyright (C) 2014 Jesse G. Donat <donatj@gmail.com>
|
6 |
+
Copyright (C) 2018 Nicolas CARPi <nicolas.carpi@curie.fr>
|
7 |
+
|
8 |
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
9 |
+
of this software and associated documentation files (the "Software"), to deal
|
10 |
+
in the Software without restriction, including without limitation the rights
|
11 |
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
12 |
+
copies of the Software, and to permit persons to whom the Software is
|
13 |
+
furnished to do so, subject to the following conditions:
|
14 |
+
|
15 |
+
The above copyright notice and this permission notice shall be included in all
|
16 |
+
copies or substantial portions of the Software.
|
17 |
+
|
18 |
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
19 |
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
20 |
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
21 |
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
22 |
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
23 |
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
24 |
+
SOFTWARE.
|
vendor/maennchen/zipstream-php/README.md
ADDED
@@ -0,0 +1,81 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# ZipStream-PHP
|
2 |
+
|
3 |
+
[![Build Status](https://travis-ci.org/maennchen/ZipStream-PHP.svg?branch=master)](https://travis-ci.org/maennchen/ZipStream-PHP)
|
4 |
+
[![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/maennchen/ZipStream-PHP/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/maennchen/ZipStream-PHP/)
|
5 |
+
[![Code Coverage](https://scrutinizer-ci.com/g/maennchen/ZipStream-PHP/badges/coverage.png?b=master)](https://scrutinizer-ci.com/g/maennchen/ZipStream-PHP/)
|
6 |
+
[![Latest Stable Version](https://poser.pugx.org/maennchen/zipstream-php/v/stable)](https://packagist.org/packages/maennchen/zipstream-php)
|
7 |
+
[![Total Downloads](https://poser.pugx.org/maennchen/zipstream-php/downloads)](https://packagist.org/packages/maennchen/zipstream-php)
|
8 |
+
[![License](https://img.shields.io/github/license/maennchen/zipstream-php.svg)](LICENSE)
|
9 |
+
|
10 |
+
## Overview
|
11 |
+
|
12 |
+
A fast and simple streaming zip file downloader for PHP. Using this library will save you from having to write the Zip to disk. You can directly send it to the user, which is much faster. It can work with S3 buckets or any PSR7 Stream.
|
13 |
+
|
14 |
+
Please see the [LICENSE](LICENSE) file for licensing and warranty information.
|
15 |
+
|
16 |
+
## Installation
|
17 |
+
|
18 |
+
Simply add a dependency on maennchen/zipstream-php to your project's composer.json file if you use Composer to manage the dependencies of your project. Use following command to add the package to your project's dependencies:
|
19 |
+
|
20 |
+
```bash
|
21 |
+
composer require maennchen/zipstream-php
|
22 |
+
```
|
23 |
+
|
24 |
+
## Usage and options
|
25 |
+
|
26 |
+
Here's a simple example:
|
27 |
+
|
28 |
+
```php
|
29 |
+
# Autoload the dependencies
|
30 |
+
require 'vendor/autoload.php';
|
31 |
+
|
32 |
+
# enable output of HTTP headers
|
33 |
+
$options = new ZipStream\Option\Archive();
|
34 |
+
$options->setSendHttpHeaders(true);
|
35 |
+
|
36 |
+
# create a new zipstream object
|
37 |
+
$zip = new ZipStream\ZipStream('example.zip', $options);
|
38 |
+
|
39 |
+
# create a file named 'hello.txt'
|
40 |
+
$zip->addFile('hello.txt', 'This is the contents of hello.txt');
|
41 |
+
|
42 |
+
# add a file named 'some_image.jpg' from a local file 'path/to/image.jpg'
|
43 |
+
$zip->addFileFromPath('some_image.jpg', 'path/to/image.jpg');
|
44 |
+
|
45 |
+
# add a file named 'goodbye.txt' from an open stream resource
|
46 |
+
$fp = tmpfile();
|
47 |
+
fwrite($fp, 'The quick brown fox jumped over the lazy dog.');
|
48 |
+
rewind($fp);
|
49 |
+
$zip->addFileFromStream('goodbye.txt', $fp);
|
50 |
+
fclose($fp);
|
51 |
+
|
52 |
+
# finish the zip stream
|
53 |
+
$zip->finish();
|
54 |
+
```
|
55 |
+
|
56 |
+
You can also add comments, modify file timestamps, and customize (or
|
57 |
+
disable) the HTTP headers. It is also possible to specify the storage method when adding files,
|
58 |
+
the current default storage method is 'deflate' i.e files are stored with Compression mode 0x08.
|
59 |
+
|
60 |
+
See the [Wiki](https://github.com/maennchen/ZipStream-PHP/wiki) for details.
|
61 |
+
|
62 |
+
## Upgrade to version 1.0.0
|
63 |
+
|
64 |
+
* All options parameters to all function have been moved from an `array` to structured option objects. See [the wiki](https://github.com/maennchen/ZipStream-PHP/wiki/Available-options) for examples.
|
65 |
+
* The whole library has been refactored. The minimal PHP requirement has been raised to PHP 7.1.
|
66 |
+
|
67 |
+
## Usage with Symfony and S3
|
68 |
+
|
69 |
+
You can find example code on [the wiki](https://github.com/maennchen/ZipStream-PHP/wiki/Symfony-example).
|
70 |
+
|
71 |
+
## Contributing
|
72 |
+
|
73 |
+
ZipStream-PHP is a collaborative project. Please take a look at the [CONTRIBUTING.md](CONTRIBUTING.md) file.
|
74 |
+
|
75 |
+
## About the Authors
|
76 |
+
|
77 |
+
* Paul Duncan <pabs@pablotron.org> - http://pablotron.org/
|
78 |
+
* Jonatan Männchen <jonatan@maennchen.ch> - http://commanders.ch
|
79 |
+
* Jesse G. Donat <donatj@gmail.com> - https://donatstudios.com
|
80 |
+
* Nicolas CARPi <nicolas.carpi@curie.fr> - https://www.elabftw.net
|
81 |
+
* Nik Barham <nik@brokencube.co.uk> - https://www.brokencube.co.uk
|
vendor/maennchen/zipstream-php/composer.json
ADDED
@@ -0,0 +1,41 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{
|
2 |
+
"name": "maennchen/zipstream-php",
|
3 |
+
"description": "ZipStream is a library for dynamically streaming dynamic zip files from PHP without writing to the disk at all on the server.",
|
4 |
+
"keywords": ["zip", "stream"],
|
5 |
+
"type": "library",
|
6 |
+
"license": "MIT",
|
7 |
+
"authors": [{
|
8 |
+
"name": "Paul Duncan",
|
9 |
+
"email": "pabs@pablotron.org"
|
10 |
+
},
|
11 |
+
{
|
12 |
+
"name": "Jonatan Männchen",
|
13 |
+
"email": "jonatan@maennchen.ch"
|
14 |
+
},
|
15 |
+
{
|
16 |
+
"name": "Jesse Donat",
|
17 |
+
"email": "donatj@gmail.com"
|
18 |
+
},
|
19 |
+
{
|
20 |
+
"name": "András Kolesár",
|
21 |
+
"email": "kolesar@kolesar.hu"
|
22 |
+
}
|
23 |
+
],
|
24 |
+
"require": {
|
25 |
+
"php": ">= 7.1",
|
26 |
+
"ext-mbstring": "*",
|
27 |
+
"psr/http-message": "^1.0",
|
28 |
+
"myclabs/php-enum": "^1.5"
|
29 |
+
},
|
30 |
+
"require-dev": {
|
31 |
+
"phpunit/phpunit": ">= 7.5",
|
32 |
+
"guzzlehttp/guzzle": ">= 6.3",
|
33 |
+
"ext-zip": "*",
|
34 |
+
"mikey179/vfsStream": "^1.6"
|
35 |
+
},
|
36 |
+
"autoload": {
|
37 |
+
"psr-4": {
|
38 |
+
"ZipStream\\": "src/"
|
39 |
+
}
|
40 |
+
}
|
41 |
+
}
|
vendor/maennchen/zipstream-php/phpunit.xml.dist
ADDED
@@ -0,0 +1,17 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<phpunit bootstrap="test/bootstrap.php">
|
2 |
+
<testsuites>
|
3 |
+
<testsuite name="Application">
|
4 |
+
<directory>test</directory>
|
5 |
+
</testsuite>
|
6 |
+
</testsuites>
|
7 |
+
|
8 |
+
<logging>
|
9 |
+
<log type="coverage-clover" target="clover.xml"/>
|
10 |
+
</logging>
|
11 |
+
|
12 |
+
<filter>
|
13 |
+
<whitelist processUncoveredFilesFromWhitelist="true">
|
14 |
+
<directory suffix=".php">src</directory>
|
15 |
+
</whitelist>
|
16 |
+
</filter>
|
17 |
+
</phpunit>
|
vendor/maennchen/zipstream-php/src/Bigint.php
ADDED
@@ -0,0 +1,172 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
declare(strict_types=1);
|
3 |
+
|
4 |
+
namespace ZipStream;
|
5 |
+
|
6 |
+
use OverflowException;
|
7 |
+
|
8 |
+
class Bigint
|
9 |
+
{
|
10 |
+
/**
|
11 |
+
* @var int[]
|
12 |
+
*/
|
13 |
+
private $bytes = [0, 0, 0, 0, 0, 0, 0, 0];
|
14 |
+
|
15 |
+
/**
|
16 |
+
* Initialize the bytes array
|
17 |
+
*
|
18 |
+
* @param int $value
|
19 |
+
*/
|
20 |
+
public function __construct(int $value = 0)
|
21 |
+
{
|
22 |
+
$this->fillBytes($value, 0, 8);
|
23 |
+
}
|
24 |
+
|
25 |
+
/**
|
26 |
+
* Fill the bytes field with int
|
27 |
+
*
|
28 |
+
* @param int $value
|
29 |
+
* @param int $start
|
30 |
+
* @param int $count
|
31 |
+
* @return void
|
32 |
+
*/
|
33 |
+
protected function fillBytes(int $value, int $start, int $count): void
|
34 |
+
{
|
35 |
+
for ($i = 0; $i < $count; $i++) {
|
36 |
+
$this->bytes[$start + $i] = $i >= PHP_INT_SIZE ? 0 : $value & 0xFF;
|
37 |
+
$value >>= 8;
|
38 |
+
}
|
39 |
+
}
|
40 |
+
|
41 |
+
/**
|
42 |
+
* Get an instance
|
43 |
+
*
|
44 |
+
* @param int $value
|
45 |
+
* @return Bigint
|
46 |
+
*/
|
47 |
+
public static function init(int $value = 0): self
|
48 |
+
{
|
49 |
+
return new self($value);
|
50 |
+
}
|
51 |
+
|
52 |
+
/**
|
53 |
+
* Fill bytes from low to high
|
54 |
+
*
|
55 |
+
* @param int $low
|
56 |
+
* @param int $high
|
57 |
+
* @return Bigint
|
58 |
+
*/
|
59 |
+
public static function fromLowHigh(int $low, int $high): self
|
60 |
+
{
|
61 |
+
$bigint = new Bigint();
|
62 |
+
$bigint->fillBytes($low, 0, 4);
|
63 |
+
$bigint->fillBytes($high, 4, 4);
|
64 |
+
return $bigint;
|
65 |
+
}
|
66 |
+
|
67 |
+
/**
|
68 |
+
* Get high 32
|
69 |
+
*
|
70 |
+
* @return int
|
71 |
+
*/
|
72 |
+
public function getHigh32(): int
|
73 |
+
{
|
74 |
+
return $this->getValue(4, 4);
|
75 |
+
}
|
76 |
+
|
77 |
+
/**
|
78 |
+
* Get value from bytes array
|
79 |
+
*
|
80 |
+
* @param int $end
|
81 |
+
* @param int $length
|
82 |
+
* @return int
|
83 |
+
*/
|
84 |
+
public function getValue(int $end = 0, int $length = 8): int
|
85 |
+
{
|
86 |
+
$result = 0;
|
87 |
+
for ($i = $end + $length - 1; $i >= $end; $i--) {
|
88 |
+
$result <<= 8;
|
89 |
+
$result |= $this->bytes[$i];
|
90 |
+
}
|
91 |
+
return $result;
|
92 |
+
}
|
93 |
+
|
94 |
+
/**
|
95 |
+
* Get low FF
|
96 |
+
*
|
97 |
+
* @param bool $force
|
98 |
+
* @return int
|
99 |
+
*/
|
100 |
+
public function getLowFF(bool $force = false): int
|
101 |
+
{
|
102 |
+
if ($force || $this->isOver32()) {
|
103 |
+
return 0xFFFFFFFF;
|
104 |
+
}
|
105 |
+
return $this->getLow32();
|
106 |
+
}
|
107 |
+
|
108 |
+
/**
|
109 |
+
* Check if is over 32
|
110 |
+
*
|
111 |
+
* @param bool $force
|
112 |
+
* @return bool
|
113 |
+
*/
|
114 |
+
public function isOver32(bool $force = false): bool
|
115 |
+
{
|
116 |
+
// value 0xFFFFFFFF already needs a Zip64 header
|
117 |
+
return $force ||
|
118 |
+
max(array_slice($this->bytes, 4, 4)) > 0 ||
|
119 |
+
min(array_slice($this->bytes, 0, 4)) === 0xFF;
|
120 |
+
}
|
121 |
+
|
122 |
+
/**
|
123 |
+
* Get low 32
|
124 |
+
*
|
125 |
+
* @return int
|
126 |
+
*/
|
127 |
+
public function getLow32(): int
|
128 |
+
{
|
129 |
+
return $this->getValue(0, 4);
|
130 |
+
}
|
131 |
+
|
132 |
+
/**
|
133 |
+
* Get hexadecimal
|
134 |
+
*
|
135 |
+
* @return string
|
136 |
+
*/
|
137 |
+
public function getHex64(): string
|
138 |
+
{
|
139 |
+
$result = '0x';
|
140 |
+
for ($i = 7; $i >= 0; $i--) {
|
141 |
+
$result .= sprintf('%02X', $this->bytes[$i]);
|
142 |
+
}
|
143 |
+
return $result;
|
144 |
+
}
|
145 |
+
|
146 |
+
/**
|
147 |
+
* Add
|
148 |
+
*
|
149 |
+
* @param Bigint $other
|
150 |
+
* @return Bigint
|
151 |
+
*/
|
152 |
+
public function add(Bigint $other): Bigint
|
153 |
+
{
|
154 |
+
$result = clone $this;
|
155 |
+
$overflow = false;
|
156 |
+
for ($i = 0; $i < 8; $i++) {
|
157 |
+
$result->bytes[$i] += $other->bytes[$i];
|
158 |
+
if ($overflow) {
|
159 |
+
$result->bytes[$i]++;
|
160 |
+
$overflow = false;
|
161 |
+
}
|
162 |
+
if ($result->bytes[$i] & 0x100) {
|
163 |
+
$overflow = true;
|
164 |
+
$result->bytes[$i] &= 0xFF;
|
165 |
+
}
|
166 |
+
}
|
167 |
+
if ($overflow) {
|
168 |
+
throw new OverflowException;
|
169 |
+
}
|
170 |
+
return $result;
|
171 |
+
}
|
172 |
+
}
|
vendor/maennchen/zipstream-php/src/DeflateStream.php
ADDED
@@ -0,0 +1,70 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
declare(strict_types=1);
|
3 |
+
|
4 |
+
namespace ZipStream;
|
5 |
+
|
6 |
+
class DeflateStream extends Stream
|
7 |
+
{
|
8 |
+
protected $filter;
|
9 |
+
|
10 |
+
/**
|
11 |
+
* @var Option\File
|
12 |
+
*/
|
13 |
+
protected $options;
|
14 |
+
|
15 |
+
/**
|
16 |
+
* Rewind stream
|
17 |
+
*
|
18 |
+
* @return void
|
19 |
+
*/
|
20 |
+
public function rewind(): void
|
21 |
+
{
|
22 |
+
// deflate filter needs to be removed before rewind
|
23 |
+
if ($this->filter) {
|
24 |
+
$this->removeDeflateFilter();
|
25 |
+
$this->seek(0);
|
26 |
+
$this->addDeflateFilter($this->options);
|
27 |
+
} else {
|
28 |
+
rewind($this->stream);
|
29 |
+
}
|
30 |
+
}
|
31 |
+
|
32 |
+
/**
|
33 |
+
* Remove the deflate filter
|
34 |
+
*
|
35 |
+
* @return void
|
36 |
+
*/
|
37 |
+
public function removeDeflateFilter(): void
|
38 |
+
{
|
39 |
+
if (!$this->filter) {
|
40 |
+
return;
|
41 |
+
}
|
42 |
+
stream_filter_remove($this->filter);
|
43 |
+
$this->filter = null;
|
44 |
+
}
|
45 |
+
|
46 |
+
/**
|
47 |
+
* Add a deflate filter
|
48 |
+
*
|
49 |
+
* @param Option\File $options
|
50 |
+
* @return void
|
51 |
+
*/
|
52 |
+
public function addDeflateFilter(Option\File $options): void
|
53 |
+
{
|
54 |
+
$this->options = $options;
|
55 |
+
// parameter 4 for stream_filter_append expects array
|
56 |
+
// so we convert the option object in an array
|
57 |
+
$optionsArr = [
|
58 |
+
'comment' => $options->getComment(),
|
59 |
+
'method' => $options->getMethod(),
|
60 |
+
'deflateLevel' => $options->getDeflateLevel(),
|
61 |
+
'time' => $options->getTime()
|
62 |
+
];
|
63 |
+
$this->filter = stream_filter_append(
|
64 |
+
$this->stream,
|
65 |
+
'zlib.deflate',
|
66 |
+
STREAM_FILTER_READ,
|
67 |
+
$optionsArr
|
68 |
+
);
|
69 |
+
}
|
70 |
+
}
|
vendor/maennchen/zipstream-php/src/Exception.php
ADDED
@@ -0,0 +1,11 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
declare(strict_types=1);
|
3 |
+
|
4 |
+
namespace ZipStream;
|
5 |
+
|
6 |
+
/**
|
7 |
+
* This class is only for inheriting
|
8 |
+
*/
|
9 |
+
abstract class Exception extends \Exception
|
10 |
+
{
|
11 |
+
}
|
vendor/maennchen/zipstream-php/src/Exception/EncodingException.php
ADDED
@@ -0,0 +1,13 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
declare(strict_types=1);
|
3 |
+
|
4 |
+
namespace ZipStream\Exception;
|
5 |
+
|
6 |
+
use ZipStream\Exception;
|
7 |
+
|
8 |
+
/**
|
9 |
+
* This Exception gets invoked if file or comment encoding is incorrect
|
10 |
+
*/
|
11 |
+
class EncodingException extends Exception
|
12 |
+
{
|
13 |
+
}
|
vendor/maennchen/zipstream-php/src/Exception/FileNotFoundException.php
ADDED
@@ -0,0 +1,22 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
declare(strict_types=1);
|
3 |
+
|
4 |
+
namespace ZipStream\Exception;
|
5 |
+
|
6 |
+
use ZipStream\Exception;
|
7 |
+
|
8 |
+
/**
|
9 |
+
* This Exception gets invoked if a file wasn't found
|
10 |
+
*/
|
11 |
+
class FileNotFoundException extends Exception
|
12 |
+
{
|
13 |
+
/**
|
14 |
+
* Constructor of the Exception
|
15 |
+
*
|
16 |
+
* @param String $path - The path which wasn't found
|
17 |
+
*/
|
18 |
+
public function __construct(string $path)
|
19 |
+
{
|
20 |
+
parent::__construct("The file with the path $path wasn't found.");
|
21 |
+
}
|
22 |
+
}
|
vendor/maennchen/zipstream-php/src/Exception/FileNotReadableException.php
ADDED
@@ -0,0 +1,22 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
declare(strict_types=1);
|
3 |
+
|
4 |
+
namespace ZipStream\Exception;
|
5 |
+
|
6 |
+
use ZipStream\Exception;
|
7 |
+
|
8 |
+
/**
|
9 |
+
* This Exception gets invoked if a file wasn't found
|
10 |
+
*/
|
11 |
+
class FileNotReadableException extends Exception
|
12 |
+
{
|
13 |
+
/**
|
14 |
+
* Constructor of the Exception
|
15 |
+
*
|
16 |
+
* @param String $path - The path which wasn't found
|
17 |
+
*/
|
18 |
+
public function __construct(string $path)
|
19 |
+
{
|
20 |
+
parent::__construct("The file with the path $path isn't readable.");
|
21 |
+
}
|
22 |
+
}
|
vendor/maennchen/zipstream-php/src/Exception/IncompatibleOptionsException.php
ADDED
@@ -0,0 +1,13 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
declare(strict_types=1);
|
3 |
+
|
4 |
+
namespace ZipStream\Exception;
|
5 |
+
|
6 |
+
use ZipStream\Exception;
|
7 |
+
|
8 |
+
/**
|
9 |
+
* This Exception gets invoked if options are incompatible
|
10 |
+
*/
|
11 |
+
class IncompatibleOptionsException extends Exception
|
12 |
+
{
|
13 |
+
}
|
vendor/maennchen/zipstream-php/src/Exception/OverflowException.php
ADDED
@@ -0,0 +1,17 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
declare(strict_types=1);
|
3 |
+
|
4 |
+
namespace ZipStream\Exception;
|
5 |
+
|
6 |
+
use ZipStream\Exception;
|
7 |
+
|
8 |
+
/**
|
9 |
+
* This Exception gets invoked if a counter value exceeds storage size
|
10 |
+
*/
|
11 |
+
class OverflowException extends Exception
|
12 |
+
{
|
13 |
+
public function __construct()
|
14 |
+
{
|
15 |
+
parent::__construct('File size exceeds limit of 32 bit integer. Please enable "zip64" option.');
|
16 |
+
}
|
17 |
+
}
|
vendor/maennchen/zipstream-php/src/Exception/StreamNotReadableException.php
ADDED
@@ -0,0 +1,22 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
declare(strict_types=1);
|
3 |
+
|
4 |
+
namespace ZipStream\Exception;
|
5 |
+
|
6 |
+
use ZipStream\Exception;
|
7 |
+
|
8 |
+
/**
|
9 |
+
* This Exception gets invoked if `fread` fails on a stream.
|
10 |
+
*/
|
11 |
+
class StreamNotReadableException extends Exception
|
12 |
+
{
|
13 |
+
/**
|
14 |
+
* Constructor of the Exception
|
15 |
+
*
|
16 |
+
* @param string $fileName - The name of the file which the stream belongs to.
|
17 |
+
*/
|
18 |
+
public function __construct(string $fileName)
|
19 |
+
{
|
20 |
+
parent::__construct("The stream for $fileName could not be read.");
|
21 |
+
}
|
22 |
+
}
|
vendor/maennchen/zipstream-php/src/File.php
ADDED
@@ -0,0 +1,480 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
declare(strict_types=1);
|
3 |
+
|
4 |
+
namespace ZipStream;
|
5 |
+
|
6 |
+
use Psr\Http\Message\StreamInterface;
|
7 |
+
use ZipStream\Exception\EncodingException;
|
8 |
+
use ZipStream\Exception\FileNotFoundException;
|
9 |
+
use ZipStream\Exception\FileNotReadableException;
|
10 |
+
use ZipStream\Exception\OverflowException;
|
11 |
+
use ZipStream\Option\File as FileOptions;
|
12 |
+
use ZipStream\Option\Method;
|
13 |
+
use ZipStream\Option\Version;
|
14 |
+
|
15 |
+
class File
|
16 |
+
{
|
17 |
+
const HASH_ALGORITHM = 'crc32b';
|
18 |
+
|
19 |
+
const BIT_ZERO_HEADER = 0x0008;
|
20 |
+
const BIT_EFS_UTF8 = 0x0800;
|
21 |
+
|
22 |
+
const COMPUTE = 1;
|
23 |
+
const SEND = 2;
|
24 |
+
|
25 |
+
private const CHUNKED_READ_BLOCK_SIZE = 1048576;
|
26 |
+
|
27 |
+
/**
|
28 |
+
* @var string
|
29 |
+
*/
|
30 |
+
public $name;
|
31 |
+
|
32 |
+
/**
|
33 |
+
* @var FileOptions
|
34 |
+
*/
|
35 |
+
public $opt;
|
36 |
+
|
37 |
+
/**
|
38 |
+
* @var Bigint
|
39 |
+
*/
|
40 |
+
public $len;
|
41 |
+
/**
|
42 |
+
* @var Bigint
|
43 |
+
*/
|
44 |
+
public $zlen;
|
45 |
+
|
46 |
+
/** @var int */
|
47 |
+
public $crc;
|
48 |
+
|
49 |
+
/**
|
50 |
+
* @var Bigint
|
51 |
+
*/
|
52 |
+
public $hlen;
|
53 |
+
|
54 |
+
/**
|
55 |
+
* @var Bigint
|
56 |
+
*/
|
57 |
+
public $ofs;
|
58 |
+
|
59 |
+
/**
|
60 |
+
* @var int
|
61 |
+
*/
|
62 |
+
public $bits;
|
63 |
+
|
64 |
+
/**
|
65 |
+
* @var Version
|
66 |
+
*/
|
67 |
+
public $version;
|
68 |
+
|
69 |
+
/**
|
70 |
+
* @var ZipStream
|
71 |
+
*/
|
72 |
+
public $zip;
|
73 |
+
|
74 |
+
/**
|
75 |
+
* @var resource
|
76 |
+
*/
|
77 |
+
private $deflate;
|
78 |
+
/**
|
79 |
+
* @var resource
|
80 |
+
*/
|
81 |
+
private $hash;
|
82 |
+
|
83 |
+
/**
|
84 |
+
* @var Method
|
85 |
+
*/
|
86 |
+
private $method;
|
87 |
+
|
88 |
+
/**
|
89 |
+
* @var Bigint
|
90 |
+
*/
|
91 |
+
private $totalLength;
|
92 |
+
|
93 |
+
public function __construct(ZipStream $zip, string $name, ?FileOptions $opt = null)
|
94 |
+
{
|
95 |
+
$this->zip = $zip;
|
96 |
+
|
97 |
+
$this->name = $name;
|
98 |
+
$this->opt = $opt ?: new FileOptions();
|
99 |
+
$this->method = $this->opt->getMethod();
|
100 |
+
$this->version = Version::STORE();
|
101 |
+
$this->ofs = new Bigint();
|
102 |
+
}
|
103 |
+
|
104 |
+
public function processPath(string $path): void
|
105 |
+
{
|
106 |
+
if (!is_readable($path)) {
|
107 |
+
if (!file_exists($path)) {
|
108 |
+
throw new FileNotFoundException($path);
|
109 |
+
}
|
110 |
+
throw new FileNotReadableException($path);
|
111 |
+
}
|
112 |
+
if ($this->zip->isLargeFile($path) === false) {
|
113 |
+
$data = file_get_contents($path);
|
114 |
+
$this->processData($data);
|
115 |
+
} else {
|
116 |
+
$this->method = $this->zip->opt->getLargeFileMethod();
|
117 |
+
|
118 |
+
$stream = new DeflateStream(fopen($path, 'rb'));
|
119 |
+
$this->processStream($stream);
|
120 |
+
}
|
121 |
+
}
|
122 |
+
|
123 |
+
public function processData(string $data): void
|
124 |
+
{
|
125 |
+
$this->len = new Bigint(strlen($data));
|
126 |
+
$this->crc = crc32($data);
|
127 |
+
|
128 |
+
// compress data if needed
|
129 |
+
if ($this->method->equals(Method::DEFLATE())) {
|
130 |
+
$data = gzdeflate($data);
|
131 |
+
}
|
132 |
+
|
133 |
+
$this->zlen = new Bigint(strlen($data));
|
134 |
+
$this->addFileHeader();
|
135 |
+
$this->zip->send($data);
|
136 |
+
$this->addFileFooter();
|
137 |
+
}
|
138 |
+
|
139 |
+
/**
|
140 |
+
* Create and send zip header for this file.
|
141 |
+
*
|
142 |
+
* @return void
|
143 |
+
* @throws \ZipStream\Exception\EncodingException
|
144 |
+
*/
|
145 |
+
public function addFileHeader(): void
|
146 |
+
{
|
147 |
+
$name = static::filterFilename($this->name);
|
148 |
+
|
149 |
+
// calculate name length
|
150 |
+
$nameLength = strlen($name);
|
151 |
+
|
152 |
+
// create dos timestamp
|
153 |
+
$time = static::dosTime($this->opt->getTime()->getTimestamp());
|
154 |
+
|
155 |
+
$comment = $this->opt->getComment();
|
156 |
+
|
157 |
+
if (!mb_check_encoding($name, 'ASCII') ||
|
158 |
+
!mb_check_encoding($comment, 'ASCII')) {
|
159 |
+
// Sets Bit 11: Language encoding flag (EFS). If this bit is set,
|
160 |
+
// the filename and comment fields for this file
|
161 |
+
// MUST be encoded using UTF-8. (see APPENDIX D)
|
162 |
+
if (!mb_check_encoding($name, 'UTF-8') ||
|
163 |
+
!mb_check_encoding($comment, 'UTF-8')) {
|
164 |
+
throw new EncodingException(
|
165 |
+
'File name and comment should use UTF-8 ' .
|
166 |
+
'if one of them does not fit into ASCII range.'
|
167 |
+
);
|
168 |
+
}
|
169 |
+
$this->bits |= self::BIT_EFS_UTF8;
|
170 |
+
}
|
171 |
+
|
172 |
+
if ($this->method->equals(Method::DEFLATE())) {
|
173 |
+
$this->version = Version::DEFLATE();
|
174 |
+
}
|
175 |
+
|
176 |
+
$force = (boolean)($this->bits & self::BIT_ZERO_HEADER) &&
|
177 |
+
$this->zip->opt->isEnableZip64();
|
178 |
+
|
179 |
+
$footer = $this->buildZip64ExtraBlock($force);
|
180 |
+
|
181 |
+
// If this file will start over 4GB limit in ZIP file,
|
182 |
+
// CDR record will have to use Zip64 extension to describe offset
|
183 |
+
// to keep consistency we use the same value here
|
184 |
+
if ($this->zip->ofs->isOver32()) {
|
185 |
+
$this->version = Version::ZIP64();
|
186 |
+
}
|
187 |
+
|
188 |
+
$fields = [
|
189 |
+
['V', ZipStream::FILE_HEADER_SIGNATURE],
|
190 |
+
['v', $this->version->getValue()], // Version needed to Extract
|
191 |
+
['v', $this->bits], // General purpose bit flags - data descriptor flag set
|
192 |
+
['v', $this->method->getValue()], // Compression method
|
193 |
+
['V', $time], // Timestamp (DOS Format)
|
194 |
+
['V', $this->crc], // CRC32 of data (0 -> moved to data descriptor footer)
|
195 |
+
['V', $this->zlen->getLowFF($force)], // Length of compressed data (forced to 0xFFFFFFFF for zero header)
|
196 |
+
['V', $this->len->getLowFF($force)], // Length of original data (forced to 0xFFFFFFFF for zero header)
|
197 |
+
['v', $nameLength], // Length of filename
|
198 |
+
['v', strlen($footer)], // Extra data (see above)
|
199 |
+
];
|
200 |
+
|
201 |
+
// pack fields and calculate "total" length
|
202 |
+
$header = ZipStream::packFields($fields);
|
203 |
+
|
204 |
+
// print header and filename
|
205 |
+
$data = $header . $name . $footer;
|
206 |
+
$this->zip->send($data);
|
207 |
+
|
208 |
+
// save header length
|
209 |
+
$this->hlen = Bigint::init(strlen($data));
|
210 |
+
}
|
211 |
+
|
212 |
+
/**
|
213 |
+
* Strip characters that are not legal in Windows filenames
|
214 |
+
* to prevent compatibility issues
|
215 |
+
*
|
216 |
+
* @param string $filename Unprocessed filename
|
217 |
+
* @return string
|
218 |
+
*/
|
219 |
+
public static function filterFilename(string $filename): string
|
220 |
+
{
|
221 |
+
// strip leading slashes from file name
|
222 |
+
// (fixes bug in windows archive viewer)
|
223 |
+
$filename = preg_replace('/^\\/+/', '', $filename);
|
224 |
+
|
225 |
+
return str_replace(['\\', ':', '*', '?', '"', '<', '>', '|'], '_', $filename);
|
226 |
+
}
|
227 |
+
|
228 |
+
/**
|
229 |
+
* Convert a UNIX timestamp to a DOS timestamp.
|
230 |
+
*
|
231 |
+
* @param int $when
|
232 |
+
* @return int DOS Timestamp
|
233 |
+
*/
|
234 |
+
final protected static function dosTime(int $when): int
|
235 |
+
{
|
236 |
+
// get date array for timestamp
|
237 |
+
$d = getdate($when);
|
238 |
+
|
239 |
+
// set lower-bound on dates
|
240 |
+
if ($d['year'] < 1980) {
|
241 |
+
$d = array(
|
242 |
+
'year' => 1980,
|
243 |
+
'mon' => 1,
|
244 |
+
'mday' => 1,
|
245 |
+
'hours' => 0,
|
246 |
+
'minutes' => 0,
|
247 |
+
'seconds' => 0
|
248 |
+
);
|
249 |
+
}
|
250 |
+
|
251 |
+
// remove extra years from 1980
|
252 |
+
$d['year'] -= 1980;
|
253 |
+
|
254 |
+
// return date string
|
255 |
+
return
|
256 |
+
($d['year'] << 25) |
|
257 |
+
($d['mon'] << 21) |
|
258 |
+
($d['mday'] << 16) |
|
259 |
+
($d['hours'] << 11) |
|
260 |
+
($d['minutes'] << 5) |
|
261 |
+
($d['seconds'] >> 1);
|
262 |
+
}
|
263 |
+
|
264 |
+
protected function buildZip64ExtraBlock(bool $force = false): string
|
265 |
+
{
|
266 |
+
|
267 |
+
$fields = [];
|
268 |
+
if ($this->len->isOver32($force)) {
|
269 |
+
$fields[] = ['P', $this->len]; // Length of original data
|
270 |
+
}
|
271 |
+
|
272 |
+
if ($this->len->isOver32($force)) {
|
273 |
+
$fields[] = ['P', $this->zlen]; // Length of compressed data
|
274 |
+
}
|
275 |
+
|
276 |
+
if ($this->ofs->isOver32()) {
|
277 |
+
$fields[] = ['P', $this->ofs]; // Offset of local header record
|
278 |
+
}
|
279 |
+
|
280 |
+
if (!empty($fields)) {
|
281 |
+
if (!$this->zip->opt->isEnableZip64()) {
|
282 |
+
throw new OverflowException();
|
283 |
+
}
|
284 |
+
|
285 |
+
array_unshift(
|
286 |
+
$fields,
|
287 |
+
['v', 0x0001], // 64 bit extension
|
288 |
+
['v', count($fields) * 8] // Length of data block
|
289 |
+
);
|
290 |
+
$this->version = Version::ZIP64();
|
291 |
+
}
|
292 |
+
|
293 |
+
return ZipStream::packFields($fields);
|
294 |
+
}
|
295 |
+
|
296 |
+
/**
|
297 |
+
* Create and send data descriptor footer for this file.
|
298 |
+
*
|
299 |
+
* @return void
|
300 |
+
*/
|
301 |
+
|
302 |
+
public function addFileFooter(): void
|
303 |
+
{
|
304 |
+
|
305 |
+
if ($this->bits & self::BIT_ZERO_HEADER) {
|
306 |
+
$fields = [
|
307 |
+
['V', ZipStream::DATA_DESCRIPTOR_SIGNATURE],
|
308 |
+
['V', $this->crc], // CRC32
|
309 |
+
['V', $this->zlen], // Length of compressed data
|
310 |
+
['V', $this->len], // Length of original data
|
311 |
+
];
|
312 |
+
|
313 |
+
if ($this->zip->opt->isEnableZip64()) {
|
314 |
+
$fields = [
|
315 |
+
['V', ZipStream::DATA_DESCRIPTOR_SIGNATURE],
|
316 |
+
['V', $this->crc], // CRC32
|
317 |
+
['P', $this->zlen], // Length of compressed data
|
318 |
+
['P', $this->len], // Length of original data
|
319 |
+
];
|
320 |
+
}
|
321 |
+
|
322 |
+
$footer = ZipStream::packFields($fields);
|
323 |
+
$this->zip->send($footer);
|
324 |
+
} else {
|
325 |
+
$footer = '';
|
326 |
+
}
|
327 |
+
$this->totalLength = $this->hlen->add($this->zlen)->add(Bigint::init(strlen($footer)));
|
328 |
+
$this->zip->addToCdr($this);
|
329 |
+
}
|
330 |
+
|
331 |
+
public function processStream(StreamInterface $stream): void
|
332 |
+
{
|
333 |
+
$this->zlen = new Bigint();
|
334 |
+
$this->len = new Bigint();
|
335 |
+
|
336 |
+
if ($this->zip->opt->isZeroHeader()) {
|
337 |
+
$this->processStreamWithZeroHeader($stream);
|
338 |
+
} else {
|
339 |
+
$this->processStreamWithComputedHeader($stream);
|
340 |
+
}
|
341 |
+
}
|
342 |
+
|
343 |
+
protected function processStreamWithZeroHeader(StreamInterface $stream): void
|
344 |
+
{
|
345 |
+
$this->bits |= self::BIT_ZERO_HEADER;
|
346 |
+
$this->addFileHeader();
|
347 |
+
$this->readStream($stream, self::COMPUTE | self::SEND);
|
348 |
+
$this->addFileFooter();
|
349 |
+
}
|
350 |
+
|
351 |
+
protected function readStream(StreamInterface $stream, ?int $options = null): void
|
352 |
+
{
|
353 |
+
$this->deflateInit();
|
354 |
+
$total = 0;
|
355 |
+
$size = $this->opt->getSize();
|
356 |
+
while (!$stream->eof() && ($size === 0 || $total < $size)) {
|
357 |
+
$data = $stream->read(self::CHUNKED_READ_BLOCK_SIZE);
|
358 |
+
$total += strlen($data);
|
359 |
+
if ($size > 0 && $total > $size) {
|
360 |
+
$data = substr($data, 0 , strlen($data)-($total - $size));
|
361 |
+
}
|
362 |
+
$this->deflateData($stream, $data, $options);
|
363 |
+
if ($options & self::SEND) {
|
364 |
+
$this->zip->send($data);
|
365 |
+
}
|
366 |
+
}
|
367 |
+
$this->deflateFinish($options);
|
368 |
+
}
|
369 |
+
|
370 |
+
protected function deflateInit(): void
|
371 |
+
{
|
372 |
+
$this->hash = hash_init(self::HASH_ALGORITHM);
|
373 |
+
if ($this->method->equals(Method::DEFLATE())) {
|
374 |
+
$this->deflate = deflate_init(
|
375 |
+
ZLIB_ENCODING_RAW,
|
376 |
+
['level' => $this->opt->getDeflateLevel()]
|
377 |
+
);
|
378 |
+
}
|
379 |
+
}
|
380 |
+
|
381 |
+
protected function deflateData(StreamInterface $stream, string &$data, ?int $options = null): void
|
382 |
+
{
|
383 |
+
if ($options & self::COMPUTE) {
|
384 |
+
$this->len = $this->len->add(Bigint::init(strlen($data)));
|
385 |
+
hash_update($this->hash, $data);
|
386 |
+
}
|
387 |
+
if ($this->deflate) {
|
388 |
+
$data = deflate_add(
|
389 |
+
$this->deflate,
|
390 |
+
$data,
|
391 |
+
$stream->eof()
|
392 |
+
? ZLIB_FINISH
|
393 |
+
: ZLIB_NO_FLUSH
|
394 |
+
);
|
395 |
+
}
|
396 |
+
if ($options & self::COMPUTE) {
|
397 |
+
$this->zlen = $this->zlen->add(Bigint::init(strlen($data)));
|
398 |
+
}
|
399 |
+
}
|
400 |
+
|
401 |
+
protected function deflateFinish(?int $options = null): void
|
402 |
+
{
|
403 |
+
if ($options & self::COMPUTE) {
|
404 |
+
$this->crc = hexdec(hash_final($this->hash));
|
405 |
+
}
|
406 |
+
}
|
407 |
+
|
408 |
+
protected function processStreamWithComputedHeader(StreamInterface $stream): void
|
409 |
+
{
|
410 |
+
$this->readStream($stream, self::COMPUTE);
|
411 |
+
$stream->rewind();
|
412 |
+
|
413 |
+
// incremental compression with deflate_add
|
414 |
+
// makes this second read unnecessary
|
415 |
+
// but it is only available from PHP 7.0
|
416 |
+
if (!$this->deflate && $stream instanceof DeflateStream && $this->method->equals(Method::DEFLATE())) {
|
417 |
+
$stream->addDeflateFilter($this->opt);
|
418 |
+
$this->zlen = new Bigint();
|
419 |
+
while (!$stream->eof()) {
|
420 |
+
$data = $stream->read(self::CHUNKED_READ_BLOCK_SIZE);
|
421 |
+
$this->zlen = $this->zlen->add(Bigint::init(strlen($data)));
|
422 |
+
}
|
423 |
+
$stream->rewind();
|
424 |
+
}
|
425 |
+
|
426 |
+
$this->addFileHeader();
|
427 |
+
$this->readStream($stream, self::SEND);
|
428 |
+
$this->addFileFooter();
|
429 |
+
}
|
430 |
+
|
431 |
+
/**
|
432 |
+
* Send CDR record for specified file.
|
433 |
+
*
|
434 |
+
* @return string
|
435 |
+
*/
|
436 |
+
public function getCdrFile(): string
|
437 |
+
{
|
438 |
+
$name = static::filterFilename($this->name);
|
439 |
+
|
440 |
+
// get attributes
|
441 |
+
$comment = $this->opt->getComment();
|
442 |
+
|
443 |
+
// get dos timestamp
|
444 |
+
$time = static::dosTime($this->opt->getTime()->getTimestamp());
|
445 |
+
|
446 |
+
$footer = $this->buildZip64ExtraBlock();
|
447 |
+
|
448 |
+
$fields = [
|
449 |
+
['V', ZipStream::CDR_FILE_SIGNATURE], // Central file header signature
|
450 |
+
['v', ZipStream::ZIP_VERSION_MADE_BY], // Made by version
|
451 |
+
['v', $this->version->getValue()], // Extract by version
|
452 |
+
['v', $this->bits], // General purpose bit flags - data descriptor flag set
|
453 |
+
['v', $this->method->getValue()], // Compression method
|
454 |
+
['V', $time], // Timestamp (DOS Format)
|
455 |
+
['V', $this->crc], // CRC32
|
456 |
+
['V', $this->zlen->getLowFF()], // Compressed Data Length
|
457 |
+
['V', $this->len->getLowFF()], // Original Data Length
|
458 |
+
['v', strlen($name)], // Length of filename
|
459 |
+
['v', strlen($footer)], // Extra data len (see above)
|
460 |
+
['v', strlen($comment)], // Length of comment
|
461 |
+
['v', 0], // Disk number
|
462 |
+
['v', 0], // Internal File Attributes
|
463 |
+
['V', 32], // External File Attributes
|
464 |
+
['V', $this->ofs->getLowFF()] // Relative offset of local header
|
465 |
+
];
|
466 |
+
|
467 |
+
// pack fields, then append name and comment
|
468 |
+
$header = ZipStream::packFields($fields);
|
469 |
+
|
470 |
+
return $header . $name . $footer . $comment;
|
471 |
+
}
|
472 |
+
|
473 |
+
/**
|
474 |
+
* @return Bigint
|
475 |
+
*/
|
476 |
+
public function getTotalLength(): Bigint
|
477 |
+
{
|
478 |
+
return $this->totalLength;
|
479 |
+
}
|
480 |
+
}
|
vendor/maennchen/zipstream-php/src/Option/Archive.php
ADDED
@@ -0,0 +1,261 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
declare(strict_types=1);
|
3 |
+
|
4 |
+
namespace ZipStream\Option;
|
5 |
+
|
6 |
+
final class Archive
|
7 |
+
{
|
8 |
+
const DEFAULT_DEFLATE_LEVEL = 6;
|
9 |
+
/**
|
10 |
+
* @var string
|
11 |
+
*/
|
12 |
+
private $comment = '';
|
13 |
+
/**
|
14 |
+
* Size, in bytes, of the largest file to try
|
15 |
+
* and load into memory (used by
|
16 |
+
* addFileFromPath()). Large files may also
|
17 |
+
* be compressed differently; see the
|
18 |
+
* 'largeFileMethod' option. Default is ~20 Mb.
|
19 |
+
*
|
20 |
+
* @var int
|
21 |
+
*/
|
22 |
+
private $largeFileSize = 20 * 1024 * 1024;
|
23 |
+
/**
|
24 |
+
* How to handle large files. Legal values are
|
25 |
+
* Method::STORE() (the default), or
|
26 |
+
* Method::DEFLATE(). STORE sends the file
|
27 |
+
* raw and is significantly
|
28 |
+
* faster, while DEFLATE compresses the file
|
29 |
+
* and is much, much slower. Note that DEFLATE
|
30 |
+
* must compress the file twice and is extremely slow.
|
31 |
+
*
|
32 |
+
* @var Method
|
33 |
+
*/
|
34 |
+
private $largeFileMethod;
|
35 |
+
/**
|
36 |
+
* Boolean indicating whether or not to send
|
37 |
+
* the HTTP headers for this file.
|
38 |
+
*
|
39 |
+
* @var bool
|
40 |
+
*/
|
41 |
+
private $sendHttpHeaders = false;
|
42 |
+
/**
|
43 |
+
* The method called to send headers
|
44 |
+
*
|
45 |
+
* @var Callable
|
46 |
+
*/
|
47 |
+
private $httpHeaderCallback = 'header';
|
48 |
+
/**
|
49 |
+
* Enable Zip64 extension, supporting very large
|
50 |
+
* archives (any size > 4 GB or file count > 64k)
|
51 |
+
*
|
52 |
+
* @var bool
|
53 |
+
*/
|
54 |
+
private $enableZip64 = true;
|
55 |
+
/**
|
56 |
+
* Enable streaming files with single read where
|
57 |
+
* general purpose bit 3 indicates local file header
|
58 |
+
* contain zero values in crc and size fields,
|
59 |
+
* these appear only after file contents
|
60 |
+
* in data descriptor block.
|
61 |
+
*
|
62 |
+
* @var bool
|
63 |
+
*/
|
64 |
+
private $zeroHeader = false;
|
65 |
+
/**
|
66 |
+
* Enable reading file stat for determining file size.
|
67 |
+
* When a 32-bit system reads file size that is
|
68 |
+
* over 2 GB, invalid value appears in file size
|
69 |
+
* due to integer overflow. Should be disabled on
|
70 |
+
* 32-bit systems with method addFileFromPath
|
71 |
+
* if any file may exceed 2 GB. In this case file
|
72 |
+
* will be read in blocks and correct size will be
|
73 |
+
* determined from content.
|
74 |
+
*
|
75 |
+
* @var bool
|
76 |
+
*/
|
77 |
+
private $statFiles = true;
|
78 |
+
/**
|
79 |
+
* Enable flush after every write to output stream.
|
80 |
+
* @var bool
|
81 |
+
*/
|
82 |
+
private $flushOutput = false;
|
83 |
+
/**
|
84 |
+
* HTTP Content-Disposition. Defaults to
|
85 |
+
* 'attachment', where
|
86 |
+
* FILENAME is the specified filename.
|
87 |
+
*
|
88 |
+
* Note that this does nothing if you are
|
89 |
+
* not sending HTTP headers.
|
90 |
+
*
|
91 |
+
* @var string
|
92 |
+
*/
|
93 |
+
private $contentDisposition = 'attachment';
|
94 |
+
/**
|
95 |
+
* Note that this does nothing if you are
|
96 |
+
* not sending HTTP headers.
|
97 |
+
*
|
98 |
+
* @var string
|
99 |
+
*/
|
100 |
+
private $contentType = 'application/x-zip';
|
101 |
+
/**
|
102 |
+
* @var int
|
103 |
+
*/
|
104 |
+
private $deflateLevel = 6;
|
105 |
+
|
106 |
+
/**
|
107 |
+
* @var resource
|
108 |
+
*/
|
109 |
+
private $outputStream;
|
110 |
+
|
111 |
+
/**
|
112 |
+
* Options constructor.
|
113 |
+
*/
|
114 |
+
public function __construct()
|
115 |
+
{
|
116 |
+
$this->largeFileMethod = Method::STORE();
|
117 |
+
$this->outputStream = fopen('php://output', 'wb');
|
118 |
+
}
|
119 |
+
|
120 |
+
public function getComment(): string
|
121 |
+
{
|
122 |
+
return $this->comment;
|
123 |
+
}
|
124 |
+
|
125 |
+
public function setComment(string $comment): void
|
126 |
+
{
|
127 |
+
$this->comment = $comment;
|
128 |
+
}
|
129 |
+
|
130 |
+
public function getLargeFileSize(): int
|
131 |
+
{
|
132 |
+
return $this->largeFileSize;
|
133 |
+
}
|
134 |
+
|
135 |
+
public function setLargeFileSize(int $largeFileSize): void
|
136 |
+
{
|
137 |
+
$this->largeFileSize = $largeFileSize;
|
138 |
+
}
|
139 |
+
|
140 |
+
public function getLargeFileMethod(): Method
|
141 |
+
{
|
142 |
+
return $this->largeFileMethod;
|
143 |
+
}
|
144 |
+
|
145 |
+
public function setLargeFileMethod(Method $largeFileMethod): void
|
146 |
+
{
|
147 |
+
$this->largeFileMethod = $largeFileMethod;
|
148 |
+
}
|
149 |
+
|
150 |
+
public function isSendHttpHeaders(): bool
|
151 |
+
{
|
152 |
+
return $this->sendHttpHeaders;
|
153 |
+
}
|
154 |
+
|
155 |
+
public function setSendHttpHeaders(bool $sendHttpHeaders): void
|
156 |
+
{
|
157 |
+
$this->sendHttpHeaders = $sendHttpHeaders;
|
158 |
+
}
|
159 |
+
|
160 |
+
public function getHttpHeaderCallback(): Callable
|
161 |
+
{
|
162 |
+
return $this->httpHeaderCallback;
|
163 |
+
}
|
164 |
+
|
165 |
+
public function setHttpHeaderCallback(Callable $httpHeaderCallback): void
|
166 |
+
{
|
167 |
+
$this->httpHeaderCallback = $httpHeaderCallback;
|
168 |
+
}
|
169 |
+
|
170 |
+
public function isEnableZip64(): bool
|
171 |
+
{
|
172 |
+
return $this->enableZip64;
|
173 |
+
}
|
174 |
+
|
175 |
+
public function setEnableZip64(bool $enableZip64): void
|
176 |
+
{
|
177 |
+
$this->enableZip64 = $enableZip64;
|
178 |
+
}
|
179 |
+
|
180 |
+
public function isZeroHeader(): bool
|
181 |
+
{
|
182 |
+
return $this->zeroHeader;
|
183 |
+
}
|
184 |
+
|
185 |
+
public function setZeroHeader(bool $zeroHeader): void
|
186 |
+
{
|
187 |
+
$this->zeroHeader = $zeroHeader;
|
188 |
+
}
|
189 |
+
|
190 |
+
public function isFlushOutput(): bool
|
191 |
+
{
|
192 |
+
return $this->flushOutput;
|
193 |
+
}
|
194 |
+
|
195 |
+
public function setFlushOutput(bool $flushOutput): void
|
196 |
+
{
|
197 |
+
$this->flushOutput = $flushOutput;
|
198 |
+
}
|
199 |
+
|
200 |
+
public function isStatFiles(): bool
|
201 |
+
{
|
202 |
+
return $this->statFiles;
|
203 |
+
}
|
204 |
+
|
205 |
+
public function setStatFiles(bool $statFiles): void
|
206 |
+
{
|
207 |
+
$this->statFiles = $statFiles;
|
208 |
+
}
|
209 |
+
|
210 |
+
public function getContentDisposition(): string
|
211 |
+
{
|
212 |
+
return $this->contentDisposition;
|
213 |
+
}
|
214 |
+
|
215 |
+
public function setContentDisposition(string $contentDisposition): void
|
216 |
+
{
|
217 |
+
$this->contentDisposition = $contentDisposition;
|
218 |
+
}
|
219 |
+
|
220 |
+
public function getContentType(): string
|
221 |
+
{
|
222 |
+
return $this->contentType;
|
223 |
+
}
|
224 |
+
|
225 |
+
public function setContentType(string $contentType): void
|
226 |
+
{
|
227 |
+
$this->contentType = $contentType;
|
228 |
+
}
|
229 |
+
|
230 |
+
/**
|
231 |
+
* @return resource
|
232 |
+
*/
|
233 |
+
public function getOutputStream()
|
234 |
+
{
|
235 |
+
return $this->outputStream;
|
236 |
+
}
|
237 |
+
|
238 |
+
/**
|
239 |
+
* @param resource $outputStream
|
240 |
+
*/
|
241 |
+
public function setOutputStream($outputStream): void
|
242 |
+
{
|
243 |
+
$this->outputStream = $outputStream;
|
244 |
+
}
|
245 |
+
|
246 |
+
/**
|
247 |
+
* @return int
|
248 |
+
*/
|
249 |
+
public function getDeflateLevel(): int
|
250 |
+
{
|
251 |
+
return $this->deflateLevel;
|
252 |
+
}
|
253 |
+
|
254 |
+
/**
|
255 |
+
* @param int $deflateLevel
|
256 |
+
*/
|
257 |
+
public function setDeflateLevel(int $deflateLevel): void
|
258 |
+
{
|
259 |
+
$this->deflateLevel = $deflateLevel;
|
260 |
+
}
|
261 |
+
}
|
vendor/maennchen/zipstream-php/src/Option/File.php
ADDED
@@ -0,0 +1,116 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
declare(strict_types=1);
|
3 |
+
|
4 |
+
namespace ZipStream\Option;
|
5 |
+
|
6 |
+
use DateTime;
|
7 |
+
|
8 |
+
final class File
|
9 |
+
{
|
10 |
+
/**
|
11 |
+
* @var string
|
12 |
+
*/
|
13 |
+
private $comment = '';
|
14 |
+
/**
|
15 |
+
* @var Method
|
16 |
+
*/
|
17 |
+
private $method;
|
18 |
+
/**
|
19 |
+
* @var int
|
20 |
+
*/
|
21 |
+
private $deflateLevel;
|
22 |
+
/**
|
23 |
+
* @var DateTime
|
24 |
+
*/
|
25 |
+
private $time;
|
26 |
+
/**
|
27 |
+
* @var int
|
28 |
+
*/
|
29 |
+
private $size = 0;
|
30 |
+
|
31 |
+
public function defaultTo(Archive $archiveOptions): void
|
32 |
+
{
|
33 |
+
$this->deflateLevel = $this->deflateLevel ?: $archiveOptions->getDeflateLevel();
|
34 |
+
$this->time = $this->time ?: new DateTime();
|
35 |
+
}
|
36 |
+
|
37 |
+
/**
|
38 |
+
* @return string
|
39 |
+
*/
|
40 |
+
public function getComment(): string
|
41 |
+
{
|
42 |
+
return $this->comment;
|
43 |
+
}
|
44 |
+
|
45 |
+
/**
|
46 |
+
* @param string $comment
|
47 |
+
*/
|
48 |
+
public function setComment(string $comment): void
|
49 |
+
{
|
50 |
+
$this->comment = $comment;
|
51 |
+
}
|
52 |
+
|
53 |
+
/**
|
54 |
+
* @return Method
|
55 |
+
*/
|
56 |
+
public function getMethod(): Method
|
57 |
+
{
|
58 |
+
return $this->method ?: Method::DEFLATE();
|
59 |
+
}
|
60 |
+
|
61 |
+
/**
|
62 |
+
* @param Method $method
|
63 |
+
*/
|
64 |
+
public function setMethod(Method $method): void
|
65 |
+
{
|
66 |
+
$this->method = $method;
|
67 |
+
}
|
68 |
+
|
69 |
+
/**
|
70 |
+
* @return int
|
71 |
+
*/
|
72 |
+
public function getDeflateLevel(): int
|
73 |
+
{
|
74 |
+
return $this->deflateLevel ?: Archive::DEFAULT_DEFLATE_LEVEL;
|
75 |
+
}
|
76 |
+
|
77 |
+
/**
|
78 |
+
* @param int $deflateLevel
|
79 |
+
*/
|
80 |
+
public function setDeflateLevel(int $deflateLevel): void
|
81 |
+
{
|
82 |
+
$this->deflateLevel = $deflateLevel;
|
83 |
+
}
|
84 |
+
|
85 |
+
/**
|
86 |
+
* @return DateTime
|
87 |
+
*/
|
88 |
+
public function getTime(): DateTime
|
89 |
+
{
|
90 |
+
return $this->time;
|
91 |
+
}
|
92 |
+
|
93 |
+
/**
|
94 |
+
* @param DateTime $time
|
95 |
+
*/
|
96 |
+
public function setTime(DateTime $time): void
|
97 |
+
{
|
98 |
+
$this->time = $time;
|
99 |
+
}
|
100 |
+
|
101 |
+
/**
|
102 |
+
* @return int
|
103 |
+
*/
|
104 |
+
public function getSize(): int
|
105 |
+
{
|
106 |
+
return $this->size;
|
107 |
+
}
|
108 |
+
|
109 |
+
/**
|
110 |
+
* @param int $size
|
111 |
+
*/
|
112 |
+
public function setSize(int $size): void
|
113 |
+
{
|
114 |
+
$this->size = $size;
|
115 |
+
}
|
116 |
+
}
|
vendor/maennchen/zipstream-php/src/Option/Method.php
ADDED
@@ -0,0 +1,18 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
declare(strict_types=1);
|
3 |
+
|
4 |
+
namespace ZipStream\Option;
|
5 |
+
|
6 |
+
use MyCLabs\Enum\Enum;
|
7 |
+
|
8 |
+
/**
|
9 |
+
* Methods enum
|
10 |
+
*
|
11 |
+
* @method static STORE(): Method
|
12 |
+
* @method static DEFLATE(): Method
|
13 |
+
*/
|
14 |
+
class Method extends Enum
|
15 |
+
{
|
16 |
+
const STORE = 0x00;
|
17 |
+
const DEFLATE = 0x08;
|
18 |
+
}
|
vendor/maennchen/zipstream-php/src/Option/Version.php
ADDED
@@ -0,0 +1,21 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
declare(strict_types=1);
|
3 |
+
|
4 |
+
namespace ZipStream\Option;
|
5 |
+
|
6 |
+
use MyCLabs\Enum\Enum;
|
7 |
+
|
8 |
+
/**
|
9 |
+
* Class Version
|
10 |
+
* @package ZipStream\Option
|
11 |
+
*
|
12 |
+
* @method static STORE(): Version
|
13 |
+
* @method static DEFLATE(): Version
|
14 |
+
* @method static ZIP64(): Version
|
15 |
+
*/
|
16 |
+
class Version extends Enum
|
17 |
+
{
|
18 |
+
const STORE = 0x000A; // 1.00
|
19 |
+
const DEFLATE = 0x0014; // 2.00
|
20 |
+
const ZIP64 = 0x002D; // 4.50
|
21 |
+
}
|
vendor/maennchen/zipstream-php/src/Stream.php
ADDED
@@ -0,0 +1,258 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
declare(strict_types=1);
|
3 |
+
|
4 |
+
namespace ZipStream;
|
5 |
+
|
6 |
+
use Psr\Http\Message\StreamInterface;
|
7 |
+
use RuntimeException;
|
8 |
+
|
9 |
+
/**
|
10 |
+
* Describes a data stream.
|
11 |
+
*
|
12 |
+
* Typically, an instance will wrap a PHP stream; this interface provides
|
13 |
+
* a wrapper around the most common operations, including serialization of
|
14 |
+
* the entire stream to a string.
|
15 |
+
*/
|
16 |
+
class Stream implements StreamInterface
|
17 |
+
{
|
18 |
+
protected $stream;
|
19 |
+
|
20 |
+
public function __construct($stream)
|
21 |
+
{
|
22 |
+
$this->stream = $stream;
|
23 |
+
}
|
24 |
+
|
25 |
+
public function __destruct()
|
26 |
+
{
|
27 |
+
$this->close();
|
28 |
+
}
|
29 |
+
|
30 |
+
/**
|
31 |
+
* Closes the stream and any underlying resources.
|
32 |
+
*
|
33 |
+
* @return void
|
34 |
+
*/
|
35 |
+
public function close(): void
|
36 |
+
{
|
37 |
+
if (is_resource($this->stream)) {
|
38 |
+
fclose($this->stream);
|
39 |
+
}
|
40 |
+
$this->detach();
|
41 |
+
}
|
42 |
+
|
43 |
+
/**
|
44 |
+
* Separates any underlying resources from the stream.
|
45 |
+
*
|
46 |
+
* After the stream has been detached, the stream is in an unusable state.
|
47 |
+
*
|
48 |
+
* @return resource|null Underlying PHP stream, if any
|
49 |
+
*/
|
50 |
+
public function detach()
|
51 |
+
{
|
52 |
+
$result = $this->stream;
|
53 |
+
$this->stream = null;
|
54 |
+
return $result;
|
55 |
+
}
|
56 |
+
|
57 |
+
/**
|
58 |
+
* Reads all data from the stream into a string, from the beginning to end.
|
59 |
+
*
|
60 |
+
* This method MUST attempt to seek to the beginning of the stream before
|
61 |
+
* reading data and read the stream until the end is reached.
|
62 |
+
*
|
63 |
+
* Warning: This could attempt to load a large amount of data into memory.
|
64 |
+
*
|
65 |
+
* This method MUST NOT raise an exception in order to conform with PHP's
|
66 |
+
* string casting operations.
|
67 |
+
*
|
68 |
+
* @see http://php.net/manual/en/language.oop5.magic.php#object.tostring
|
69 |
+
* @return string
|
70 |
+
*/
|
71 |
+
public function __toString(): string
|
72 |
+
{
|
73 |
+
try {
|
74 |
+
$this->seek(0);
|
75 |
+
} catch (\RuntimeException $e) {}
|
76 |
+
return (string) stream_get_contents($this->stream);
|
77 |
+
}
|
78 |
+
|
79 |
+
/**
|
80 |
+
* Seek to a position in the stream.
|
81 |
+
*
|
82 |
+
* @link http://www.php.net/manual/en/function.fseek.php
|
83 |
+
* @param int $offset Stream offset
|
84 |
+
* @param int $whence Specifies how the cursor position will be calculated
|
85 |
+
* based on the seek offset. Valid values are identical to the built-in
|
86 |
+
* PHP $whence values for `fseek()`. SEEK_SET: Set position equal to
|
87 |
+
* offset bytes SEEK_CUR: Set position to current location plus offset
|
88 |
+
* SEEK_END: Set position to end-of-stream plus offset.
|
89 |
+
* @throws \RuntimeException on failure.
|
90 |
+
*/
|
91 |
+
public function seek($offset, $whence = SEEK_SET): void
|
92 |
+
{
|
93 |
+
if (!$this->isSeekable()) {
|
94 |
+
throw new RuntimeException;
|
95 |
+
}
|
96 |
+
if (fseek($this->stream, $offset, $whence) !== 0) {
|
97 |
+
throw new RuntimeException;
|
98 |
+
}
|
99 |
+
}
|
100 |
+
|
101 |
+
/**
|
102 |
+
* Returns whether or not the stream is seekable.
|
103 |
+
*
|
104 |
+
* @return bool
|
105 |
+
*/
|
106 |
+
public function isSeekable(): bool
|
107 |
+
{
|
108 |
+
return (bool)$this->getMetadata('seekable');
|
109 |
+
}
|
110 |
+
|
111 |
+
/**
|
112 |
+
* Get stream metadata as an associative array or retrieve a specific key.
|
113 |
+
*
|
114 |
+
* The keys returned are identical to the keys returned from PHP's
|
115 |
+
* stream_get_meta_data() function.
|
116 |
+
*
|
117 |
+
* @link http://php.net/manual/en/function.stream-get-meta-data.php
|
118 |
+
* @param string $key Specific metadata to retrieve.
|
119 |
+
* @return array|mixed|null Returns an associative array if no key is
|
120 |
+
* provided. Returns a specific key value if a key is provided and the
|
121 |
+
* value is found, or null if the key is not found.
|
122 |
+
*/
|
123 |
+
public function getMetadata($key = null)
|
124 |
+
{
|
125 |
+
$metadata = stream_get_meta_data($this->stream);
|
126 |
+
return $key !== null ? @$metadata[$key] : $metadata;
|
127 |
+
}
|
128 |
+
|
129 |
+
/**
|
130 |
+
* Get the size of the stream if known.
|
131 |
+
*
|
132 |
+
* @return int|null Returns the size in bytes if known, or null if unknown.
|
133 |
+
*/
|
134 |
+
public function getSize(): ?int
|
135 |
+
{
|
136 |
+
$stats = fstat($this->stream);
|
137 |
+
return $stats['size'];
|
138 |
+
}
|
139 |
+
|
140 |
+
/**
|
141 |
+
* Returns the current position of the file read/write pointer
|
142 |
+
*
|
143 |
+
* @return int Position of the file pointer
|
144 |
+
* @throws \RuntimeException on error.
|
145 |
+
*/
|
146 |
+
public function tell(): int
|
147 |
+
{
|
148 |
+
$position = ftell($this->stream);
|
149 |
+
if ($position === false) {
|
150 |
+
throw new RuntimeException;
|
151 |
+
}
|
152 |
+
return $position;
|
153 |
+
}
|
154 |
+
|
155 |
+
/**
|
156 |
+
* Returns true if the stream is at the end of the stream.
|
157 |
+
*
|
158 |
+
* @return bool
|
159 |
+
*/
|
160 |
+
public function eof(): bool
|
161 |
+
{
|
162 |
+
return feof($this->stream);
|
163 |
+
}
|
164 |
+
|
165 |
+
/**
|
166 |
+
* Seek to the beginning of the stream.
|
167 |
+
*
|
168 |
+
* If the stream is not seekable, this method will raise an exception;
|
169 |
+
* otherwise, it will perform a seek(0).
|
170 |
+
*
|
171 |
+
* @see seek()
|
172 |
+
* @link http://www.php.net/manual/en/function.fseek.php
|
173 |
+
* @throws \RuntimeException on failure.
|
174 |
+
*/
|
175 |
+
public function rewind(): void
|
176 |
+
{
|
177 |
+
$this->seek(0);
|
178 |
+
}
|
179 |
+
|
180 |
+
/**
|
181 |
+
* Write data to the stream.
|
182 |
+
*
|
183 |
+
* @param string $string The string that is to be written.
|
184 |
+
* @return int Returns the number of bytes written to the stream.
|
185 |
+
* @throws \RuntimeException on failure.
|
186 |
+
*/
|
187 |
+
public function write($string): int
|
188 |
+
{
|
189 |
+
if (!$this->isWritable()) {
|
190 |
+
throw new RuntimeException;
|
191 |
+
}
|
192 |
+
if (fwrite($this->stream, $string) === false) {
|
193 |
+
throw new RuntimeException;
|
194 |
+
}
|
195 |
+
return \mb_strlen($string);
|
196 |
+
}
|
197 |
+
|
198 |
+
/**
|
199 |
+
* Returns whether or not the stream is writable.
|
200 |
+
*
|
201 |
+
* @return bool
|
202 |
+
*/
|
203 |
+
public function isWritable(): bool
|
204 |
+
{
|
205 |
+
return preg_match('/[waxc+]/', $this->getMetadata('mode')) === 1;
|
206 |
+
}
|
207 |
+
|
208 |
+
/**
|
209 |
+
* Read data from the stream.
|
210 |
+
*
|
211 |
+
* @param int $length Read up to $length bytes from the object and return
|
212 |
+
* them. Fewer than $length bytes may be returned if underlying stream
|
213 |
+
* call returns fewer bytes.
|
214 |
+
* @return string Returns the data read from the stream, or an empty string
|
215 |
+
* if no bytes are available.
|
216 |
+
* @throws \RuntimeException if an error occurs.
|
217 |
+
*/
|
218 |
+
public function read($length): string
|
219 |
+
{
|
220 |
+
if (!$this->isReadable()) {
|
221 |
+
throw new RuntimeException;
|
222 |
+
}
|
223 |
+
$result = fread($this->stream, $length);
|
224 |
+
if ($result === false) {
|
225 |
+
throw new RuntimeException;
|
226 |
+
}
|
227 |
+
return $result;
|
228 |
+
}
|
229 |
+
|
230 |
+
/**
|
231 |
+
* Returns whether or not the stream is readable.
|
232 |
+
*
|
233 |
+
* @return bool
|
234 |
+
*/
|
235 |
+
public function isReadable(): bool
|
236 |
+
{
|
237 |
+
return preg_match('/[r+]/', $this->getMetadata('mode')) === 1;
|
238 |
+
}
|
239 |
+
|
240 |
+
/**
|
241 |
+
* Returns the remaining contents in a string
|
242 |
+
*
|
243 |
+
* @return string
|
244 |
+
* @throws \RuntimeException if unable to read or an error occurs while
|
245 |
+
* reading.
|
246 |
+
*/
|
247 |
+
public function getContents(): string
|
248 |
+
{
|
249 |
+
if (!$this->isReadable()) {
|
250 |
+
throw new RuntimeException;
|
251 |
+
}
|
252 |
+
$result = stream_get_contents($this->stream);
|
253 |
+
if ($result === false) {
|
254 |
+
throw new RuntimeException;
|
255 |
+
}
|
256 |
+
return $result;
|
257 |
+
}
|
258 |
+
}
|
vendor/maennchen/zipstream-php/src/ZipStream.php
ADDED
@@ -0,0 +1,593 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
declare(strict_types=1);
|
3 |
+
|
4 |
+
namespace ZipStream;
|
5 |
+
|
6 |
+
use Psr\Http\Message\StreamInterface;
|
7 |
+
use ZipStream\Exception\OverflowException;
|
8 |
+
use ZipStream\Option\Archive as ArchiveOptions;
|
9 |
+
use ZipStream\Option\File as FileOptions;
|
10 |
+
use ZipStream\Option\Version;
|
11 |
+
|
12 |
+
/**
|
13 |
+
* ZipStream
|
14 |
+
*
|
15 |
+
* Streamed, dynamically generated zip archives.
|
16 |
+
*
|
17 |
+
* Usage:
|
18 |
+
*
|
19 |
+
* Streaming zip archives is a simple, three-step process:
|
20 |
+
*
|
21 |
+
* 1. Create the zip stream:
|
22 |
+
*
|
23 |
+
* $zip = new ZipStream('example.zip');
|
24 |
+
*
|
25 |
+
* 2. Add one or more files to the archive:
|
26 |
+
*
|
27 |
+
* * add first file
|
28 |
+
* $data = file_get_contents('some_file.gif');
|
29 |
+
* $zip->addFile('some_file.gif', $data);
|
30 |
+
*
|
31 |
+
* * add second file
|
32 |
+
* $data = file_get_contents('some_file.gif');
|
33 |
+
* $zip->addFile('another_file.png', $data);
|
34 |
+
*
|
35 |
+
* 3. Finish the zip stream:
|
36 |
+
*
|
37 |
+
* $zip->finish();
|
38 |
+
*
|
39 |
+
* You can also add an archive comment, add comments to individual files,
|
40 |
+
* and adjust the timestamp of files. See the API documentation for each
|
41 |
+
* method below for additional information.
|
42 |
+
*
|
43 |
+
* Example:
|
44 |
+
*
|
45 |
+
* // create a new zip stream object
|
46 |
+
* $zip = new ZipStream('some_files.zip');
|
47 |
+
*
|
48 |
+
* // list of local files
|
49 |
+
* $files = array('foo.txt', 'bar.jpg');
|
50 |
+
*
|
51 |
+
* // read and add each file to the archive
|
52 |
+
* foreach ($files as $path)
|
53 |
+
* $zip->addFile($path, file_get_contents($path));
|
54 |
+
*
|
55 |
+
* // write archive footer to stream
|
56 |
+
* $zip->finish();
|
57 |
+
*/
|
58 |
+
class ZipStream
|
59 |
+
{
|
60 |
+
/**
|
61 |
+
* This number corresponds to the ZIP version/OS used (2 bytes)
|
62 |
+
* From: https://www.iana.org/assignments/media-types/application/zip
|
63 |
+
* The upper byte (leftmost one) indicates the host system (OS) for the
|
64 |
+
* file. Software can use this information to determine
|
65 |
+
* the line record format for text files etc. The current
|
66 |
+
* mappings are:
|
67 |
+
*
|
68 |
+
* 0 - MS-DOS and OS/2 (F.A.T. file systems)
|
69 |
+
* 1 - Amiga 2 - VAX/VMS
|
70 |
+
* 3 - *nix 4 - VM/CMS
|
71 |
+
* 5 - Atari ST 6 - OS/2 H.P.F.S.
|
72 |
+
* 7 - Macintosh 8 - Z-System
|
73 |
+
* 9 - CP/M 10 thru 255 - unused
|
74 |
+
*
|
75 |
+
* The lower byte (rightmost one) indicates the version number of the
|
76 |
+
* software used to encode the file. The value/10
|
77 |
+
* indicates the major version number, and the value
|
78 |
+
* mod 10 is the minor version number.
|
79 |
+
* Here we are using 6 for the OS, indicating OS/2 H.P.F.S.
|
80 |
+
* to prevent file permissions issues upon extract (see #84)
|
81 |
+
* 0x603 is 00000110 00000011 in binary, so 6 and 3
|
82 |
+
*/
|
83 |
+
const ZIP_VERSION_MADE_BY = 0x603;
|
84 |
+
|
85 |
+
/**
|
86 |
+
* The following signatures end with 0x4b50, which in ASCII is PK,
|
87 |
+
* the initials of the inventor Phil Katz.
|
88 |
+
* See https://en.wikipedia.org/wiki/Zip_(file_format)#File_headers
|
89 |
+
*/
|
90 |
+
const FILE_HEADER_SIGNATURE = 0x04034b50;
|
91 |
+
const CDR_FILE_SIGNATURE = 0x02014b50;
|
92 |
+
const CDR_EOF_SIGNATURE = 0x06054b50;
|
93 |
+
const DATA_DESCRIPTOR_SIGNATURE = 0x08074b50;
|
94 |
+
const ZIP64_CDR_EOF_SIGNATURE = 0x06064b50;
|
95 |
+
const ZIP64_CDR_LOCATOR_SIGNATURE = 0x07064b50;
|
96 |
+
|
97 |
+
/**
|
98 |
+
* Global Options
|
99 |
+
*
|
100 |
+
* @var ArchiveOptions
|
101 |
+
*/
|
102 |
+
public $opt;
|
103 |
+
|
104 |
+
/**
|
105 |
+
* @var array
|
106 |
+
*/
|
107 |
+
public $files = [];
|
108 |
+
|
109 |
+
/**
|
110 |
+
* @var Bigint
|
111 |
+
*/
|
112 |
+
public $cdr_ofs;
|
113 |
+
|
114 |
+
/**
|
115 |
+
* @var Bigint
|
116 |
+
*/
|
117 |
+
public $ofs;
|
118 |
+
|
119 |
+
/**
|
120 |
+
* @var bool
|
121 |
+
*/
|
122 |
+
protected $need_headers;
|
123 |
+
|
124 |
+
/**
|
125 |
+
* @var null|String
|
126 |
+
*/
|
127 |
+
protected $output_name;
|
128 |
+
|
129 |
+
/**
|
130 |
+
* Create a new ZipStream object.
|
131 |
+
*
|
132 |
+
* Parameters:
|
133 |
+
*
|
134 |
+
* @param String $name - Name of output file (optional).
|
135 |
+
* @param ArchiveOptions $opt - Archive Options
|
136 |
+
*
|
137 |
+
* Large File Support:
|
138 |
+
*
|
139 |
+
* By default, the method addFileFromPath() will send send files
|
140 |
+
* larger than 20 megabytes along raw rather than attempting to
|
141 |
+
* compress them. You can change both the maximum size and the
|
142 |
+
* compression behavior using the largeFile* options above, with the
|
143 |
+
* following caveats:
|
144 |
+
*
|
145 |
+
* * For "small" files (e.g. files smaller than largeFileSize), the
|
146 |
+
* memory use can be up to twice that of the actual file. In other
|
147 |
+
* words, adding a 10 megabyte file to the archive could potentially
|
148 |
+
* occupy 20 megabytes of memory.
|
149 |
+
*
|
150 |
+
* * Enabling compression on large files (e.g. files larger than
|
151 |
+
* large_file_size) is extremely slow, because ZipStream has to pass
|
152 |
+
* over the large file once to calculate header information, and then
|
153 |
+
* again to compress and send the actual data.
|
154 |
+
*
|
155 |
+
* Examples:
|
156 |
+
*
|
157 |
+
* // create a new zip file named 'foo.zip'
|
158 |
+
* $zip = new ZipStream('foo.zip');
|
159 |
+
*
|
160 |
+
* // create a new zip file named 'bar.zip' with a comment
|
161 |
+
* $opt->setComment = 'this is a comment for the zip file.';
|
162 |
+
* $zip = new ZipStream('bar.zip', $opt);
|
163 |
+
*
|
164 |
+
* Notes:
|
165 |
+
*
|
166 |
+
* In order to let this library send HTTP headers, a filename must be given
|
167 |
+
* _and_ the option `sendHttpHeaders` must be `true`. This behavior is to
|
168 |
+
* allow software to send its own headers (including the filename), and
|
169 |
+
* still use this library.
|
170 |
+
*/
|
171 |
+
public function __construct(?string $name = null, ?ArchiveOptions $opt = null)
|
172 |
+
{
|
173 |
+
$this->opt = $opt ?: new ArchiveOptions();
|
174 |
+
|
175 |
+
$this->output_name = $name;
|
176 |
+
$this->need_headers = $name && $this->opt->isSendHttpHeaders();
|
177 |
+
|
178 |
+
$this->cdr_ofs = new Bigint();
|
179 |
+
$this->ofs = new Bigint();
|
180 |
+
}
|
181 |
+
|
182 |
+
/**
|
183 |
+
* addFile
|
184 |
+
*
|
185 |
+
* Add a file to the archive.
|
186 |
+
*
|
187 |
+
* @param String $name - path of file in archive (including directory).
|
188 |
+
* @param String $data - contents of file
|
189 |
+
* @param FileOptions $options
|
190 |
+
*
|
191 |
+
* File Options:
|
192 |
+
* time - Last-modified timestamp (seconds since the epoch) of
|
193 |
+
* this file. Defaults to the current time.
|
194 |
+
* comment - Comment related to this file.
|
195 |
+
* method - Storage method for file ("store" or "deflate")
|
196 |
+
*
|
197 |
+
* Examples:
|
198 |
+
*
|
199 |
+
* // add a file named 'foo.txt'
|
200 |
+
* $data = file_get_contents('foo.txt');
|
201 |
+
* $zip->addFile('foo.txt', $data);
|
202 |
+
*
|
203 |
+
* // add a file named 'bar.jpg' with a comment and a last-modified
|
204 |
+
* // time of two hours ago
|
205 |
+
* $data = file_get_contents('bar.jpg');
|
206 |
+
* $opt->setTime = time() - 2 * 3600;
|
207 |
+
* $opt->setComment = 'this is a comment about bar.jpg';
|
208 |
+
* $zip->addFile('bar.jpg', $data, $opt);
|
209 |
+
*/
|
210 |
+
public function addFile(string $name, string $data, ?FileOptions $options = null): void
|
211 |
+
{
|
212 |
+
$options = $options ?: new FileOptions();
|
213 |
+
$options->defaultTo($this->opt);
|
214 |
+
|
215 |
+
$file = new File($this, $name, $options);
|
216 |
+
$file->processData($data);
|
217 |
+
}
|
218 |
+
|
219 |
+
/**
|
220 |
+
* addFileFromPath
|
221 |
+
*
|
222 |
+
* Add a file at path to the archive.
|
223 |
+
*
|
224 |
+
* Note that large files may be compressed differently than smaller
|
225 |
+
* files; see the "Large File Support" section above for more
|
226 |
+
* information.
|
227 |
+
*
|
228 |
+
* @param String $name - name of file in archive (including directory path).
|
229 |
+
* @param String $path - path to file on disk (note: paths should be encoded using
|
230 |
+
* UNIX-style forward slashes -- e.g '/path/to/some/file').
|
231 |
+
* @param FileOptions $options
|
232 |
+
*
|
233 |
+
* File Options:
|
234 |
+
* time - Last-modified timestamp (seconds since the epoch) of
|
235 |
+
* this file. Defaults to the current time.
|
236 |
+
* comment - Comment related to this file.
|
237 |
+
* method - Storage method for file ("store" or "deflate")
|
238 |
+
*
|
239 |
+
* Examples:
|
240 |
+
*
|
241 |
+
* // add a file named 'foo.txt' from the local file '/tmp/foo.txt'
|
242 |
+
* $zip->addFileFromPath('foo.txt', '/tmp/foo.txt');
|
243 |
+
*
|
244 |
+
* // add a file named 'bigfile.rar' from the local file
|
245 |
+
* // '/usr/share/bigfile.rar' with a comment and a last-modified
|
246 |
+
* // time of two hours ago
|
247 |
+
* $path = '/usr/share/bigfile.rar';
|
248 |
+
* $opt->setTime = time() - 2 * 3600;
|
249 |
+
* $opt->setComment = 'this is a comment about bar.jpg';
|
250 |
+
* $zip->addFileFromPath('bigfile.rar', $path, $opt);
|
251 |
+
*
|
252 |
+
* @return void
|
253 |
+
* @throws \ZipStream\Exception\FileNotFoundException
|
254 |
+
* @throws \ZipStream\Exception\FileNotReadableException
|
255 |
+
*/
|
256 |
+
public function addFileFromPath(string $name, string $path, ?FileOptions $options = null): void
|
257 |
+
{
|
258 |
+
$options = $options ?: new FileOptions();
|
259 |
+
$options->defaultTo($this->opt);
|
260 |
+
|
261 |
+
$file = new File($this, $name, $options);
|
262 |
+
$file->processPath($path);
|
263 |
+
}
|
264 |
+
|
265 |
+
/**
|
266 |
+
* addFileFromStream
|
267 |
+
*
|
268 |
+
* Add an open stream to the archive.
|
269 |
+
*
|
270 |
+
* @param String $name - path of file in archive (including directory).
|
271 |
+
* @param Resource $stream - contents of file as a stream resource
|
272 |
+
* @param FileOptions $options
|
273 |
+
*
|
274 |
+
* File Options:
|
275 |
+
* time - Last-modified timestamp (seconds since the epoch) of
|
276 |
+
* this file. Defaults to the current time.
|
277 |
+
* comment - Comment related to this file.
|
278 |
+
*
|
279 |
+
* Examples:
|
280 |
+
*
|
281 |
+
* // create a temporary file stream and write text to it
|
282 |
+
* $fp = tmpfile();
|
283 |
+
* fwrite($fp, 'The quick brown fox jumped over the lazy dog.');
|
284 |
+
*
|
285 |
+
* // add a file named 'streamfile.txt' from the content of the stream
|
286 |
+
* $x->addFileFromStream('streamfile.txt', $fp);
|
287 |
+
*
|
288 |
+
* @return void
|
289 |
+
*/
|
290 |
+
public function addFileFromStream(string $name, $stream, ?FileOptions $options = null): void
|
291 |
+
{
|
292 |
+
$options = $options ?: new FileOptions();
|
293 |
+
$options->defaultTo($this->opt);
|
294 |
+
|
295 |
+
$file = new File($this, $name, $options);
|
296 |
+
$file->processStream(new DeflateStream($stream));
|
297 |
+
}
|
298 |
+
|
299 |
+
/**
|
300 |
+
* addFileFromPsr7Stream
|
301 |
+
*
|
302 |
+
* Add an open stream to the archive.
|
303 |
+
*
|
304 |
+
* @param String $name - path of file in archive (including directory).
|
305 |
+
* @param StreamInterface $stream - contents of file as a stream resource
|
306 |
+
* @param FileOptions $options
|
307 |
+
*
|
308 |
+
* File Options:
|
309 |
+
* time - Last-modified timestamp (seconds since the epoch) of
|
310 |
+
* this file. Defaults to the current time.
|
311 |
+
* comment - Comment related to this file.
|
312 |
+
*
|
313 |
+
* Examples:
|
314 |
+
*
|
315 |
+
* // create a temporary file stream and write text to it
|
316 |
+
* $fp = tmpfile();
|
317 |
+
* fwrite($fp, 'The quick brown fox jumped over the lazy dog.');
|
318 |
+
*
|
319 |
+
* // add a file named 'streamfile.txt' from the content of the stream
|
320 |
+
* $x->addFileFromPsr7Stream('streamfile.txt', $fp);
|
321 |
+
*
|
322 |
+
* @return void
|
323 |
+
*/
|
324 |
+
public function addFileFromPsr7Stream(
|
325 |
+
string $name,
|
326 |
+
StreamInterface $stream,
|
327 |
+
?FileOptions $options = null
|
328 |
+
): void {
|
329 |
+
$options = $options ?: new FileOptions();
|
330 |
+
$options->defaultTo($this->opt);
|
331 |
+
|
332 |
+
$file = new File($this, $name, $options);
|
333 |
+
$file->processStream($stream);
|
334 |
+
}
|
335 |
+
|
336 |
+
/**
|
337 |
+
* finish
|
338 |
+
*
|
339 |
+
* Write zip footer to stream.
|
340 |
+
*
|
341 |
+
* Example:
|
342 |
+
*
|
343 |
+
* // add a list of files to the archive
|
344 |
+
* $files = array('foo.txt', 'bar.jpg');
|
345 |
+
* foreach ($files as $path)
|
346 |
+
* $zip->addFile($path, file_get_contents($path));
|
347 |
+
*
|
348 |
+
* // write footer to stream
|
349 |
+
* $zip->finish();
|
350 |
+
* @return void
|
351 |
+
*
|
352 |
+
* @throws OverflowException
|
353 |
+
*/
|
354 |
+
public function finish(): void
|
355 |
+
{
|
356 |
+
// add trailing cdr file records
|
357 |
+
foreach ($this->files as $cdrFile) {
|
358 |
+
$this->send($cdrFile);
|
359 |
+
$this->cdr_ofs = $this->cdr_ofs->add(Bigint::init(strlen($cdrFile)));
|
360 |
+
}
|
361 |
+
|
362 |
+
// Add 64bit headers (if applicable)
|
363 |
+
if (count($this->files) >= 0xFFFF ||
|
364 |
+
$this->cdr_ofs->isOver32() ||
|
365 |
+
$this->ofs->isOver32()) {
|
366 |
+
if (!$this->opt->isEnableZip64()) {
|
367 |
+
throw new OverflowException();
|
368 |
+
}
|
369 |
+
|
370 |
+
$this->addCdr64Eof();
|
371 |
+
$this->addCdr64Locator();
|
372 |
+
}
|
373 |
+
|
374 |
+
// add trailing cdr eof record
|
375 |
+
$this->addCdrEof();
|
376 |
+
|
377 |
+
// The End
|
378 |
+
$this->clear();
|
379 |
+
}
|
380 |
+
|
381 |
+
/**
|
382 |
+
* Send ZIP64 CDR EOF (Central Directory Record End-of-File) record.
|
383 |
+
*
|
384 |
+
* @return void
|
385 |
+
*/
|
386 |
+
protected function addCdr64Eof(): void
|
387 |
+
{
|
388 |
+
$num_files = count($this->files);
|
389 |
+
$cdr_length = $this->cdr_ofs;
|
390 |
+
$cdr_offset = $this->ofs;
|
391 |
+
|
392 |
+
$fields = [
|
393 |
+
['V', static::ZIP64_CDR_EOF_SIGNATURE], // ZIP64 end of central file header signature
|
394 |
+
['P', 44], // Length of data below this header (length of block - 12) = 44
|
395 |
+
['v', static::ZIP_VERSION_MADE_BY], // Made by version
|
396 |
+
['v', Version::ZIP64], // Extract by version
|
397 |
+
['V', 0x00], // disk number
|
398 |
+
['V', 0x00], // no of disks
|
399 |
+
['P', $num_files], // no of entries on disk
|
400 |
+
['P', $num_files], // no of entries in cdr
|
401 |
+
['P', $cdr_length], // CDR size
|
402 |
+
['P', $cdr_offset], // CDR offset
|
403 |
+
];
|
404 |
+
|
405 |
+
$ret = static::packFields($fields);
|
406 |
+
$this->send($ret);
|
407 |
+
}
|
408 |
+
|
409 |
+
/**
|
410 |
+
* Create a format string and argument list for pack(), then call
|
411 |
+
* pack() and return the result.
|
412 |
+
*
|
413 |
+
* @param array $fields
|
414 |
+
* @return string
|
415 |
+
*/
|
416 |
+
public static function packFields(array $fields): string
|
417 |
+
{
|
418 |
+
$fmt = '';
|
419 |
+
$args = [];
|
420 |
+
|
421 |
+
// populate format string and argument list
|
422 |
+
foreach ($fields as [$format, $value]) {
|
423 |
+
if ($format === 'P') {
|
424 |
+
$fmt .= 'VV';
|
425 |
+
if ($value instanceof Bigint) {
|
426 |
+
$args[] = $value->getLow32();
|
427 |
+
$args[] = $value->getHigh32();
|
428 |
+
} else {
|
429 |
+
$args[] = $value;
|
430 |
+
$args[] = 0;
|
431 |
+
}
|
432 |
+
} else {
|
433 |
+
if ($value instanceof Bigint) {
|
434 |
+
$value = $value->getLow32();
|
435 |
+
}
|
436 |
+
$fmt .= $format;
|
437 |
+
$args[] = $value;
|
438 |
+
}
|
439 |
+
}
|
440 |
+
|
441 |
+
// prepend format string to argument list
|
442 |
+
array_unshift($args, $fmt);
|
443 |
+
|
444 |
+
// build output string from header and compressed data
|
445 |
+
return pack(...$args);
|
446 |
+
}
|
447 |
+
|
448 |
+
/**
|
449 |
+
* Send string, sending HTTP headers if necessary.
|
450 |
+
* Flush output after write if configure option is set.
|
451 |
+
*
|
452 |
+
* @param String $str
|
453 |
+
* @return void
|
454 |
+
*/
|
455 |
+
public function send(string $str): void
|
456 |
+
{
|
457 |
+
if ($this->need_headers) {
|
458 |
+
$this->sendHttpHeaders();
|
459 |
+
}
|
460 |
+
$this->need_headers = false;
|
461 |
+
|
462 |
+
fwrite($this->opt->getOutputStream(), $str);
|
463 |
+
|
464 |
+
if ($this->opt->isFlushOutput()) {
|
465 |
+
flush();
|
466 |
+
ob_flush();
|
467 |
+
}
|
468 |
+
}
|
469 |
+
|
470 |
+
/**
|
471 |
+
* Send HTTP headers for this stream.
|
472 |
+
*
|
473 |
+
* @return void
|
474 |
+
*/
|
475 |
+
protected function sendHttpHeaders(): void
|
476 |
+
{
|
477 |
+
// grab content disposition
|
478 |
+
$disposition = $this->opt->getContentDisposition();
|
479 |
+
|
480 |
+
if ($this->output_name) {
|
481 |
+
// Various different browsers dislike various characters here. Strip them all for safety.
|
482 |
+
$safe_output = trim(str_replace(['"', "'", '\\', ';', "\n", "\r"], '', $this->output_name));
|
483 |
+
|
484 |
+
// Check if we need to UTF-8 encode the filename
|
485 |
+
$urlencoded = rawurlencode($safe_output);
|
486 |
+
$disposition .= "; filename*=UTF-8''{$urlencoded}";
|
487 |
+
}
|
488 |
+
|
489 |
+
$headers = array(
|
490 |
+
'Content-Type' => $this->opt->getContentType(),
|
491 |
+
'Content-Disposition' => $disposition,
|
492 |
+
'Pragma' => 'public',
|
493 |
+
'Cache-Control' => 'public, must-revalidate',
|
494 |
+
'Content-Transfer-Encoding' => 'binary'
|
495 |
+
);
|
496 |
+
|
497 |
+
$call = $this->opt->getHttpHeaderCallback();
|
498 |
+
foreach ($headers as $key => $val) {
|
499 |
+
$call("$key: $val");
|
500 |
+
}
|
501 |
+
}
|
502 |
+
|
503 |
+
/**
|
504 |
+
* Send ZIP64 CDR Locator (Central Directory Record Locator) record.
|
505 |
+
*
|
506 |
+
* @return void
|
507 |
+
*/
|
508 |
+
protected function addCdr64Locator(): void
|
509 |
+
{
|
510 |
+
$cdr_offset = $this->ofs->add($this->cdr_ofs);
|
511 |
+
|
512 |
+
$fields = [
|
513 |
+
['V', static::ZIP64_CDR_LOCATOR_SIGNATURE], // ZIP64 end of central file header signature
|
514 |
+
['V', 0x00], // Disc number containing CDR64EOF
|
515 |
+
['P', $cdr_offset], // CDR offset
|
516 |
+
['V', 1], // Total number of disks
|
517 |
+
];
|
518 |
+
|
519 |
+
$ret = static::packFields($fields);
|
520 |
+
$this->send($ret);
|
521 |
+
}
|
522 |
+
|
523 |
+
/**
|
524 |
+
* Send CDR EOF (Central Directory Record End-of-File) record.
|
525 |
+
*
|
526 |
+
* @return void
|
527 |
+
*/
|
528 |
+
protected function addCdrEof(): void
|
529 |
+
{
|
530 |
+
$num_files = count($this->files);
|
531 |
+
$cdr_length = $this->cdr_ofs;
|
532 |
+
$cdr_offset = $this->ofs;
|
533 |
+
|
534 |
+
// grab comment (if specified)
|
535 |
+
$comment = $this->opt->getComment();
|
536 |
+
|
537 |
+
$fields = [
|
538 |
+
['V', static::CDR_EOF_SIGNATURE], // end of central file header signature
|
539 |
+
['v', 0x00], // disk number
|
540 |
+
['v', 0x00], // no of disks
|
541 |
+
['v', min($num_files, 0xFFFF)], // no of entries on disk
|
542 |
+
['v', min($num_files, 0xFFFF)], // no of entries in cdr
|
543 |
+
['V', $cdr_length->getLowFF()], // CDR size
|
544 |
+
['V', $cdr_offset->getLowFF()], // CDR offset
|
545 |
+
['v', strlen($comment)], // Zip Comment size
|
546 |
+
];
|
547 |
+
|
548 |
+
$ret = static::packFields($fields) . $comment;
|
549 |
+
$this->send($ret);
|
550 |
+
}
|
551 |
+
|
552 |
+
/**
|
553 |
+
* Clear all internal variables. Note that the stream object is not
|
554 |
+
* usable after this.
|
555 |
+
*
|
556 |
+
* @return void
|
557 |
+
*/
|
558 |
+
protected function clear(): void
|
559 |
+
{
|
560 |
+
$this->files = [];
|
561 |
+
$this->ofs = new Bigint();
|
562 |
+
$this->cdr_ofs = new Bigint();
|
563 |
+
$this->opt = new ArchiveOptions();
|
564 |
+
}
|
565 |
+
|
566 |
+
/**
|
567 |
+
* Is this file larger than large_file_size?
|
568 |
+
*
|
569 |
+
* @param string $path
|
570 |
+
* @return bool
|
571 |
+
*/
|
572 |
+
public function isLargeFile(string $path): bool
|
573 |
+
{
|
574 |
+
if (!$this->opt->isStatFiles()) {
|
575 |
+
return false;
|
576 |
+
}
|
577 |
+
$stat = stat($path);
|
578 |
+
return $stat['size'] > $this->opt->getLargeFileSize();
|
579 |
+
}
|
580 |
+
|
581 |
+
/**
|
582 |
+
* Save file attributes for trailing CDR record.
|
583 |
+
*
|
584 |
+
* @param File $file
|
585 |
+
* @return void
|
586 |
+
*/
|
587 |
+
public function addToCdr(File $file): void
|
588 |
+
{
|
589 |
+
$file->ofs = $this->ofs;
|
590 |
+
$this->ofs = $this->ofs->add($file->getTotalLength());
|
591 |
+
$this->files[] = $file->getCdrFile();
|
592 |
+
}
|
593 |
+
}
|
vendor/maennchen/zipstream-php/test/BigintTest.php
ADDED
@@ -0,0 +1,65 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
declare(strict_types=1);
|
3 |
+
|
4 |
+
namespace BigintTest;
|
5 |
+
|
6 |
+
use OverflowException;
|
7 |
+
use PHPUnit\Framework\TestCase;
|
8 |
+
use ZipStream\Bigint;
|
9 |
+
|
10 |
+
class BigintTest extends TestCase
|
11 |
+
{
|
12 |
+
public function testConstruct(): void
|
13 |
+
{
|
14 |
+
$bigint = new Bigint(0x12345678);
|
15 |
+
$this->assertSame('0x0000000012345678', $bigint->getHex64());
|
16 |
+
$this->assertSame(0x12345678, $bigint->getLow32());
|
17 |
+
$this->assertSame(0, $bigint->getHigh32());
|
18 |
+
}
|
19 |
+
|
20 |
+
public function testConstructLarge(): void
|
21 |
+
{
|
22 |
+
$bigint = new Bigint(0x87654321);
|
23 |
+
$this->assertSame('0x0000000087654321', $bigint->getHex64());
|
24 |
+
$this->assertSame('87654321', bin2hex(pack('N', $bigint->getLow32())));
|
25 |
+
$this->assertSame(0, $bigint->getHigh32());
|
26 |
+
}
|
27 |
+
|
28 |
+
public function testAddSmallValue(): void
|
29 |
+
{
|
30 |
+
$bigint = new Bigint(1);
|
31 |
+
$bigint = $bigint->add(Bigint::init(2));
|
32 |
+
$this->assertSame(3, $bigint->getLow32());
|
33 |
+
$this->assertFalse($bigint->isOver32());
|
34 |
+
$this->assertTrue($bigint->isOver32(true));
|
35 |
+
$this->assertSame($bigint->getLowFF(), $bigint->getLow32());
|
36 |
+
$this->assertSame($bigint->getLowFF(true), 0xFFFFFFFF);
|
37 |
+
}
|
38 |
+
|
39 |
+
public function testAddWithOverflowAtLowestByte(): void
|
40 |
+
{
|
41 |
+
$bigint = new Bigint(0xFF);
|
42 |
+
$bigint = $bigint->add(Bigint::init(0x01));
|
43 |
+
$this->assertSame(0x100, $bigint->getLow32());
|
44 |
+
}
|
45 |
+
|
46 |
+
public function testAddWithOverflowAtInteger32(): void
|
47 |
+
{
|
48 |
+
$bigint = new Bigint(0xFFFFFFFE);
|
49 |
+
$this->assertFalse($bigint->isOver32());
|
50 |
+
$bigint = $bigint->add(Bigint::init(0x01));
|
51 |
+
$this->assertTrue($bigint->isOver32());
|
52 |
+
$bigint = $bigint->add(Bigint::init(0x01));
|
53 |
+
$this->assertSame('0x0000000100000000', $bigint->getHex64());
|
54 |
+
$this->assertTrue($bigint->isOver32());
|
55 |
+
$this->assertSame(0xFFFFFFFF, $bigint->getLowFF());
|
56 |
+
}
|
57 |
+
|
58 |
+
public function testAddWithOverflowAtInteger64(): void
|
59 |
+
{
|
60 |
+
$bigint = Bigint::fromLowHigh(0xFFFFFFFF, 0xFFFFFFFF);
|
61 |
+
$this->assertSame('0xFFFFFFFFFFFFFFFF', $bigint->getHex64());
|
62 |
+
$this->expectException(OverflowException::class);
|
63 |
+
$bigint->add(Bigint::init(1));
|
64 |
+
}
|
65 |
+
}
|
vendor/maennchen/zipstream-php/test/ZipStreamTest.php
ADDED
@@ -0,0 +1,560 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
declare(strict_types=1);
|
3 |
+
|
4 |
+
namespace ZipStreamTest;
|
5 |
+
|
6 |
+
use org\bovigo\vfs\vfsStream;
|
7 |
+
use GuzzleHttp\Psr7\Response;
|
8 |
+
use PHPUnit\Framework\TestCase;
|
9 |
+
use ZipStream\File;
|
10 |
+
use ZipStream\Option\Archive as ArchiveOptions;
|
11 |
+
use ZipStream\Option\File as FileOptions;
|
12 |
+
use ZipStream\Option\Method;
|
13 |
+
use ZipStream\ZipStream;
|
14 |
+
|
15 |
+
/**
|
16 |
+
* Test Class for the Main ZipStream CLass
|
17 |
+
*/
|
18 |
+
class ZipStreamTest extends TestCase
|
19 |
+
{
|
20 |
+
const OSX_ARCHIVE_UTILITY =
|
21 |
+
'/System/Library/CoreServices/Applications/Archive Utility.app/Contents/MacOS/Archive Utility';
|
22 |
+
|
23 |
+
public function testFileNotFoundException(): void
|
24 |
+
{
|
25 |
+
$this->expectException(\ZipStream\Exception\FileNotFoundException::class);
|
26 |
+
// Get ZipStream Object
|
27 |
+
$zip = new ZipStream();
|
28 |
+
|
29 |
+
// Trigger error by adding a file which doesn't exist
|
30 |
+
$zip->addFileFromPath('foobar.php', '/foo/bar/foobar.php');
|
31 |
+
}
|
32 |
+
|
33 |
+
public function testFileNotReadableException(): void
|
34 |
+
{
|
35 |
+
// create new virtual filesystem
|
36 |
+
$root = vfsStream::setup('vfs');
|
37 |
+
// create a virtual file with no permissions
|
38 |
+
$file = vfsStream::newFile('foo.txt', 0000)->at($root)->setContent('bar');
|
39 |
+
$zip = new ZipStream();
|
40 |
+
$this->expectException(\ZipStream\Exception\FileNotReadableException::class);
|
41 |
+
$zip->addFileFromPath('foo.txt', $file->url());
|
42 |
+
}
|
43 |
+
|
44 |
+
public function testDostime(): void
|
45 |
+
{
|
46 |
+
// Allows testing of protected method
|
47 |
+
$class = new \ReflectionClass(File::class);
|
48 |
+
$method = $class->getMethod('dostime');
|
49 |
+
$method->setAccessible(true);
|
50 |
+
|
51 |
+
$this->assertSame($method->invoke(null, 1416246368), 1165069764);
|
52 |
+
|
53 |
+
// January 1 1980 - DOS Epoch.
|
54 |
+
$this->assertSame($method->invoke(null, 315532800), 2162688);
|
55 |
+
|
56 |
+
// January 1 1970 -> January 1 1980 due to minimum DOS Epoch. @todo Throw Exception?
|
57 |
+
$this->assertSame($method->invoke(null, 0), 2162688);
|
58 |
+
}
|
59 |
+
|
60 |
+
public function testAddFile(): void
|
61 |
+
{
|
62 |
+
[$tmp, $stream] = $this->getTmpFileStream();
|
63 |
+
|
64 |
+
$options = new ArchiveOptions();
|
65 |
+
$options->setOutputStream($stream);
|
66 |
+
|
67 |
+
$zip = new ZipStream(null, $options);
|
68 |
+
|
69 |
+
$zip->addFile('sample.txt', 'Sample String Data');
|
70 |
+
$zip->addFile('test/sample.txt', 'More Simple Sample Data');
|
71 |
+
|
72 |
+
$zip->finish();
|
73 |
+
fclose($stream);
|
74 |
+
|
75 |
+
$tmpDir = $this->validateAndExtractZip($tmp);
|
76 |
+
|
77 |
+
$files = $this->getRecursiveFileList($tmpDir);
|
78 |
+
$this->assertEquals(['sample.txt', 'test/sample.txt'], $files);
|
79 |
+
|
80 |
+
$this->assertStringEqualsFile($tmpDir . '/sample.txt', 'Sample String Data');
|
81 |
+
$this->assertStringEqualsFile($tmpDir . '/test/sample.txt', 'More Simple Sample Data');
|
82 |
+
}
|
83 |
+
|
84 |
+
/**
|
85 |
+
* @return array
|
86 |
+
*/
|
87 |
+
protected function getTmpFileStream(): array
|
88 |
+
{
|
89 |
+
$tmp = tempnam(sys_get_temp_dir(), 'zipstreamtest');
|
90 |
+
$stream = fopen($tmp, 'wb+');
|
91 |
+
|
92 |
+
return array($tmp, $stream);
|
93 |
+
}
|
94 |
+
|
95 |
+
/**
|
96 |
+
* @param string $tmp
|
97 |
+
* @return string
|
98 |
+
*/
|
99 |
+
protected function validateAndExtractZip($tmp): string
|
100 |
+
{
|
101 |
+
$tmpDir = $this->getTmpDir();
|
102 |
+
|
103 |
+
$zipArch = new \ZipArchive;
|
104 |
+
$res = $zipArch->open($tmp);
|
105 |
+
|
106 |
+
if ($res !== true) {
|
107 |
+
$this->fail("Failed to open {$tmp}. Code: $res");
|
108 |
+
|
109 |
+
return $tmpDir;
|
110 |
+
}
|
111 |
+
|
112 |
+
$this->assertEquals(0, $zipArch->status);
|
113 |
+
$this->assertEquals(0, $zipArch->statusSys);
|
114 |
+
|
115 |
+
$zipArch->extractTo($tmpDir);
|
116 |
+
$zipArch->close();
|
117 |
+
|
118 |
+
return $tmpDir;
|
119 |
+
}
|
120 |
+
|
121 |
+
protected function getTmpDir(): string
|
122 |
+
{
|
123 |
+
$tmp = tempnam(sys_get_temp_dir(), 'zipstreamtest');
|
124 |
+
unlink($tmp);
|
125 |
+
mkdir($tmp) or $this->fail('Failed to make directory');
|
126 |
+
|
127 |
+
return $tmp;
|
128 |
+
}
|
129 |
+
|
130 |
+
/**
|
131 |
+
* @param string $path
|
132 |
+
* @return string[]
|
133 |
+
*/
|
134 |
+
protected function getRecursiveFileList(string $path): array
|
135 |
+
{
|
136 |
+
$data = array();
|
137 |
+
$path = (string)realpath($path);
|
138 |
+
$files = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($path));
|
139 |
+
|
140 |
+
$pathLen = strlen($path);
|
141 |
+
foreach ($files as $file) {
|
142 |
+
$filePath = $file->getRealPath();
|
143 |
+
if (!is_dir($filePath)) {
|
144 |
+
$data[] = substr($filePath, $pathLen + 1);
|
145 |
+
}
|
146 |
+
}
|
147 |
+
|
148 |
+
sort($data);
|
149 |
+
|
150 |
+
return $data;
|
151 |
+
}
|
152 |
+
|
153 |
+
public function testAddFileUtf8NameComment(): void
|
154 |
+
{
|
155 |
+
[$tmp, $stream] = $this->getTmpFileStream();
|
156 |
+
|
157 |
+
$options = new ArchiveOptions();
|
158 |
+
$options->setOutputStream($stream);
|
159 |
+
|
160 |
+
$zip = new ZipStream(null, $options);
|
161 |
+
|
162 |
+
$name = 'árvíztűrő tükörfúrógép.txt';
|
163 |
+
$content = 'Sample String Data';
|
164 |
+
$comment =
|
165 |
+
'Filename has every special characters ' .
|
166 |
+
'from Hungarian language in lowercase. ' .
|
167 |
+
'In uppercase: ÁÍŰŐÜÖÚÓÉ';
|
168 |
+
|
169 |
+
$fileOptions = new FileOptions();
|
170 |
+
$fileOptions->setComment($comment);
|
171 |
+
|
172 |
+
$zip->addFile($name, $content, $fileOptions);
|
173 |
+
$zip->finish();
|
174 |
+
fclose($stream);
|
175 |
+
|
176 |
+
$tmpDir = $this->validateAndExtractZip($tmp);
|
177 |
+
|
178 |
+
$files = $this->getRecursiveFileList($tmpDir);
|
179 |
+
$this->assertEquals(array($name), $files);
|
180 |
+
$this->assertStringEqualsFile($tmpDir . '/' . $name, $content);
|
181 |
+
|
182 |
+
$zipArch = new \ZipArchive();
|
183 |
+
$zipArch->open($tmp);
|
184 |
+
$this->assertEquals($comment, $zipArch->getCommentName($name));
|
185 |
+
}
|
186 |
+
|
187 |
+
public function testAddFileUtf8NameNonUtfComment(): void
|
188 |
+
{
|
189 |
+
$this->expectException(\ZipStream\Exception\EncodingException::class);
|
190 |
+
|
191 |
+
$stream = $this->getTmpFileStream()[1];
|
192 |
+
|
193 |
+
$options = new ArchiveOptions();
|
194 |
+
$options->setOutputStream($stream);
|
195 |
+
|
196 |
+
$zip = new ZipStream(null, $options);
|
197 |
+
|
198 |
+
$name = 'á.txt';
|
199 |
+
$content = 'any';
|
200 |
+
$comment = 'á';
|
201 |
+
|
202 |
+
$fileOptions = new FileOptions();
|
203 |
+
$fileOptions->setComment(mb_convert_encoding($comment, 'ISO-8859-2', 'UTF-8'));
|
204 |
+
|
205 |
+
$zip->addFile($name, $content, $fileOptions);
|
206 |
+
}
|
207 |
+
|
208 |
+
public function testAddFileNonUtf8NameUtfComment(): void
|
209 |
+
{
|
210 |
+
$this->expectException(\ZipStream\Exception\EncodingException::class);
|
211 |
+
|
212 |
+
$stream = $this->getTmpFileStream()[1];
|
213 |
+
|
214 |
+
$options = new ArchiveOptions();
|
215 |
+
$options->setOutputStream($stream);
|
216 |
+
|
217 |
+
$zip = new ZipStream(null, $options);
|
218 |
+
|
219 |
+
$name = 'á.txt';
|
220 |
+
$content = 'any';
|
221 |
+
$comment = 'á';
|
222 |
+
|
223 |
+
$fileOptions = new FileOptions();
|
224 |
+
$fileOptions->setComment($comment);
|
225 |
+
|
226 |
+
$zip->addFile(mb_convert_encoding($name, 'ISO-8859-2', 'UTF-8'), $content, $fileOptions);
|
227 |
+
}
|
228 |
+
|
229 |
+
public function testAddFileWithStorageMethod(): void
|
230 |
+
{
|
231 |
+
[$tmp, $stream] = $this->getTmpFileStream();
|
232 |
+
|
233 |
+
$options = new ArchiveOptions();
|
234 |
+
$options->setOutputStream($stream);
|
235 |
+
|
236 |
+
$zip = new ZipStream(null, $options);
|
237 |
+
|
238 |
+
$fileOptions = new FileOptions();
|
239 |
+
$fileOptions->setMethod(Method::STORE());
|
240 |
+
|
241 |
+
$zip->addFile('sample.txt', 'Sample String Data', $fileOptions);
|
242 |
+
$zip->addFile('test/sample.txt', 'More Simple Sample Data');
|
243 |
+
$zip->finish();
|
244 |
+
fclose($stream);
|
245 |
+
|
246 |
+
$zipArch = new \ZipArchive();
|
247 |
+
$zipArch->open($tmp);
|
248 |
+
|
249 |
+
$sample1 = $zipArch->statName('sample.txt');
|
250 |
+
$sample12 = $zipArch->statName('test/sample.txt');
|
251 |
+
$this->assertEquals($sample1['comp_method'], Method::STORE);
|
252 |
+
$this->assertEquals($sample12['comp_method'], Method::DEFLATE);
|
253 |
+
|
254 |
+
$zipArch->close();
|
255 |
+
}
|
256 |
+
|
257 |
+
public function testDecompressFileWithMacUnarchiver(): void
|
258 |
+
{
|
259 |
+
if (!file_exists(self::OSX_ARCHIVE_UTILITY)) {
|
260 |
+
$this->markTestSkipped('The Mac OSX Archive Utility is not available.');
|
261 |
+
}
|
262 |
+
|
263 |
+
[$tmp, $stream] = $this->getTmpFileStream();
|
264 |
+
|
265 |
+
$options = new ArchiveOptions();
|
266 |
+
$options->setOutputStream($stream);
|
267 |
+
|
268 |
+
$zip = new ZipStream(null, $options);
|
269 |
+
|
270 |
+
$folder = uniqid('', true);
|
271 |
+
|
272 |
+
$zip->addFile($folder . '/sample.txt', 'Sample Data');
|
273 |
+
$zip->finish();
|
274 |
+
fclose($stream);
|
275 |
+
|
276 |
+
exec(escapeshellarg(self::OSX_ARCHIVE_UTILITY) . ' ' . escapeshellarg($tmp), $output, $returnStatus);
|
277 |
+
|
278 |
+
$this->assertEquals(0, $returnStatus);
|
279 |
+
$this->assertCount(0, $output);
|
280 |
+
|
281 |
+
$this->assertFileExists(dirname($tmp) . '/' . $folder . '/sample.txt');
|
282 |
+
$this->assertStringEqualsFile(dirname($tmp) . '/' . $folder . '/sample.txt', 'Sample Data');
|
283 |
+
}
|
284 |
+
|
285 |
+
public function testAddFileFromPath(): void
|
286 |
+
{
|
287 |
+
[$tmp, $stream] = $this->getTmpFileStream();
|
288 |
+
|
289 |
+
$options = new ArchiveOptions();
|
290 |
+
$options->setOutputStream($stream);
|
291 |
+
|
292 |
+
$zip = new ZipStream(null, $options);
|
293 |
+
|
294 |
+
[$tmpExample, $streamExample] = $this->getTmpFileStream();
|
295 |
+
fwrite($streamExample, 'Sample String Data');
|
296 |
+
fclose($streamExample);
|
297 |
+
$zip->addFileFromPath('sample.txt', $tmpExample);
|
298 |
+
|
299 |
+
[$tmpExample, $streamExample] = $this->getTmpFileStream();
|
300 |
+
fwrite($streamExample, 'More Simple Sample Data');
|
301 |
+
fclose($streamExample);
|
302 |
+
$zip->addFileFromPath('test/sample.txt', $tmpExample);
|
303 |
+
|
304 |
+
$zip->finish();
|
305 |
+
fclose($stream);
|
306 |
+
|
307 |
+
$tmpDir = $this->validateAndExtractZip($tmp);
|
308 |
+
|
309 |
+
$files = $this->getRecursiveFileList($tmpDir);
|
310 |
+
$this->assertEquals(array('sample.txt', 'test/sample.txt'), $files);
|
311 |
+
|
312 |
+
$this->assertStringEqualsFile($tmpDir . '/sample.txt', 'Sample String Data');
|
313 |
+
$this->assertStringEqualsFile($tmpDir . '/test/sample.txt', 'More Simple Sample Data');
|
314 |
+
}
|
315 |
+
|
316 |
+
public function testAddFileFromPathWithStorageMethod(): void
|
317 |
+
{
|
318 |
+
[$tmp, $stream] = $this->getTmpFileStream();
|
319 |
+
|
320 |
+
$options = new ArchiveOptions();
|
321 |
+
$options->setOutputStream($stream);
|
322 |
+
|
323 |
+
$zip = new ZipStream(null, $options);
|
324 |
+
|
325 |
+
$fileOptions = new FileOptions();
|
326 |
+
$fileOptions->setMethod(Method::STORE());
|
327 |
+
|
328 |
+
[$tmpExample, $streamExample] = $this->getTmpFileStream();
|
329 |
+
fwrite($streamExample, 'Sample String Data');
|
330 |
+
fclose($streamExample);
|
331 |
+
$zip->addFileFromPath('sample.txt', $tmpExample, $fileOptions);
|
332 |
+
|
333 |
+
[$tmpExample, $streamExample] = $this->getTmpFileStream();
|
334 |
+
fwrite($streamExample, 'More Simple Sample Data');
|
335 |
+
fclose($streamExample);
|
336 |
+
$zip->addFileFromPath('test/sample.txt', $tmpExample);
|
337 |
+
|
338 |
+
$zip->finish();
|
339 |
+
fclose($stream);
|
340 |
+
|
341 |
+
$zipArch = new \ZipArchive();
|
342 |
+
$zipArch->open($tmp);
|
343 |
+
|
344 |
+
$sample1 = $zipArch->statName('sample.txt');
|
345 |
+
$this->assertEquals(Method::STORE, $sample1['comp_method']);
|
346 |
+
|
347 |
+
$sample2 = $zipArch->statName('test/sample.txt');
|
348 |
+
$this->assertEquals(Method::DEFLATE, $sample2['comp_method']);
|
349 |
+
|
350 |
+
$zipArch->close();
|
351 |
+
}
|
352 |
+
|
353 |
+
public function testAddLargeFileFromPath(): void
|
354 |
+
{
|
355 |
+
$methods = [Method::DEFLATE(), Method::STORE()];
|
356 |
+
$falseTrue = [false, true];
|
357 |
+
foreach ($methods as $method) {
|
358 |
+
foreach ($falseTrue as $zeroHeader) {
|
359 |
+
foreach ($falseTrue as $zip64) {
|
360 |
+
if ($zeroHeader && $method->equals(Method::DEFLATE())) {
|
361 |
+
continue;
|
362 |
+
}
|
363 |
+
$this->addLargeFileFileFromPath($method, $zeroHeader, $zip64);
|
364 |
+
}
|
365 |
+
}
|
366 |
+
}
|
367 |
+
}
|
368 |
+
|
369 |
+
protected function addLargeFileFileFromPath($method, $zeroHeader, $zip64): void
|
370 |
+
{
|
371 |
+
[$tmp, $stream] = $this->getTmpFileStream();
|
372 |
+
|
373 |
+
$options = new ArchiveOptions();
|
374 |
+
$options->setOutputStream($stream);
|
375 |
+
$options->setLargeFileMethod($method);
|
376 |
+
$options->setLargeFileSize(5);
|
377 |
+
$options->setZeroHeader($zeroHeader);
|
378 |
+
$options->setEnableZip64($zip64);
|
379 |
+
|
380 |
+
$zip = new ZipStream(null, $options);
|
381 |
+
|
382 |
+
[$tmpExample, $streamExample] = $this->getTmpFileStream();
|
383 |
+
for ($i = 0; $i <= 10000; $i++) {
|
384 |
+
fwrite($streamExample, sha1((string)$i));
|
385 |
+
if ($i % 100 === 0) {
|
386 |
+
fwrite($streamExample, "\n");
|
387 |
+
}
|
388 |
+
}
|
389 |
+
fclose($streamExample);
|
390 |
+
$shaExample = sha1_file($tmpExample);
|
391 |
+
$zip->addFileFromPath('sample.txt', $tmpExample);
|
392 |
+
unlink($tmpExample);
|
393 |
+
|
394 |
+
$zip->finish();
|
395 |
+
fclose($stream);
|
396 |
+
|
397 |
+
$tmpDir = $this->validateAndExtractZip($tmp);
|
398 |
+
|
399 |
+
$files = $this->getRecursiveFileList($tmpDir);
|
400 |
+
$this->assertEquals(array('sample.txt'), $files);
|
401 |
+
|
402 |
+
$this->assertEquals(sha1_file($tmpDir . '/sample.txt'), $shaExample, "SHA-1 Mismatch Method: {$method}");
|
403 |
+
}
|
404 |
+
|
405 |
+
public function testAddFileFromStream(): void
|
406 |
+
{
|
407 |
+
[$tmp, $stream] = $this->getTmpFileStream();
|
408 |
+
|
409 |
+
$options = new ArchiveOptions();
|
410 |
+
$options->setOutputStream($stream);
|
411 |
+
|
412 |
+
$zip = new ZipStream(null, $options);
|
413 |
+
|
414 |
+
// In this test we can't use temporary stream to feed data
|
415 |
+
// because zlib.deflate filter gives empty string before PHP 7
|
416 |
+
// it works fine with file stream
|
417 |
+
$streamExample = fopen(__FILE__, 'rb');
|
418 |
+
$zip->addFileFromStream('sample.txt', $streamExample);
|
419 |
+
// fclose($streamExample);
|
420 |
+
|
421 |
+
$fileOptions = new FileOptions();
|
422 |
+
$fileOptions->setMethod(Method::STORE());
|
423 |
+
|
424 |
+
$streamExample2 = fopen('php://temp', 'wb+');
|
425 |
+
fwrite($streamExample2, 'More Simple Sample Data');
|
426 |
+
rewind($streamExample2); // move the pointer back to the beginning of file.
|
427 |
+
$zip->addFileFromStream('test/sample.txt', $streamExample2, $fileOptions);
|
428 |
+
// fclose($streamExample2);
|
429 |
+
|
430 |
+
$zip->finish();
|
431 |
+
fclose($stream);
|
432 |
+
|
433 |
+
$tmpDir = $this->validateAndExtractZip($tmp);
|
434 |
+
|
435 |
+
$files = $this->getRecursiveFileList($tmpDir);
|
436 |
+
$this->assertEquals(array('sample.txt', 'test/sample.txt'), $files);
|
437 |
+
|
438 |
+
$this->assertStringEqualsFile(__FILE__, file_get_contents($tmpDir . '/sample.txt'));
|
439 |
+
$this->assertStringEqualsFile($tmpDir . '/test/sample.txt', 'More Simple Sample Data');
|
440 |
+
}
|
441 |
+
|
442 |
+
public function testAddFileFromStreamWithStorageMethod(): void
|
443 |
+
{
|
444 |
+
[$tmp, $stream] = $this->getTmpFileStream();
|
445 |
+
|
446 |
+
$options = new ArchiveOptions();
|
447 |
+
$options->setOutputStream($stream);
|
448 |
+
|
449 |
+
$zip = new ZipStream(null, $options);
|
450 |
+
|
451 |
+
$fileOptions = new FileOptions();
|
452 |
+
$fileOptions->setMethod(Method::STORE());
|
453 |
+
|
454 |
+
$streamExample = fopen('php://temp', 'wb+');
|
455 |
+
fwrite($streamExample, 'Sample String Data');
|
456 |
+
rewind($streamExample); // move the pointer back to the beginning of file.
|
457 |
+
$zip->addFileFromStream('sample.txt', $streamExample, $fileOptions);
|
458 |
+
// fclose($streamExample);
|
459 |
+
|
460 |
+
$streamExample2 = fopen('php://temp', 'bw+');
|
461 |
+
fwrite($streamExample2, 'More Simple Sample Data');
|
462 |
+
rewind($streamExample2); // move the pointer back to the beginning of file.
|
463 |
+
$zip->addFileFromStream('test/sample.txt', $streamExample2);
|
464 |
+
// fclose($streamExample2);
|
465 |
+
|
466 |
+
$zip->finish();
|
467 |
+
fclose($stream);
|
468 |
+
|
469 |
+
$zipArch = new \ZipArchive();
|
470 |
+
$zipArch->open($tmp);
|
471 |
+
|
472 |
+
$sample1 = $zipArch->statName('sample.txt');
|
473 |
+
$this->assertEquals(Method::STORE, $sample1['comp_method']);
|
474 |
+
|
475 |
+
$sample2 = $zipArch->statName('test/sample.txt');
|
476 |
+
$this->assertEquals(Method::DEFLATE, $sample2['comp_method']);
|
477 |
+
|
478 |
+
$zipArch->close();
|
479 |
+
}
|
480 |
+
|
481 |
+
public function testAddFileFromPsr7Stream(): void
|
482 |
+
{
|
483 |
+
[$tmp, $stream] = $this->getTmpFileStream();
|
484 |
+
|
485 |
+
$options = new ArchiveOptions();
|
486 |
+
$options->setOutputStream($stream);
|
487 |
+
|
488 |
+
$zip = new ZipStream(null, $options);
|
489 |
+
|
490 |
+
$body = 'Sample String Data';
|
491 |
+
$response = new Response(200, [], $body);
|
492 |
+
|
493 |
+
$fileOptions = new FileOptions();
|
494 |
+
$fileOptions->setMethod(Method::STORE());
|
495 |
+
|
496 |
+
$zip->addFileFromPsr7Stream('sample.json', $response->getBody(), $fileOptions);
|
497 |
+
$zip->finish();
|
498 |
+
fclose($stream);
|
499 |
+
|
500 |
+
$tmpDir = $this->validateAndExtractZip($tmp);
|
501 |
+
|
502 |
+
$files = $this->getRecursiveFileList($tmpDir);
|
503 |
+
$this->assertEquals(array('sample.json'), $files);
|
504 |
+
$this->assertStringEqualsFile($tmpDir . '/sample.json', $body);
|
505 |
+
}
|
506 |
+
|
507 |
+
public function testAddFileFromPsr7StreamWithFileSizeSet(): void
|
508 |
+
{
|
509 |
+
[$tmp, $stream] = $this->getTmpFileStream();
|
510 |
+
|
511 |
+
$options = new ArchiveOptions();
|
512 |
+
$options->setOutputStream($stream);
|
513 |
+
|
514 |
+
$zip = new ZipStream(null, $options);
|
515 |
+
|
516 |
+
$body = 'Sample String Data';
|
517 |
+
$fileSize = strlen($body);
|
518 |
+
// Add fake padding
|
519 |
+
$fakePadding = "\0\0\0\0\0\0";
|
520 |
+
$response = new Response(200, [], $body . $fakePadding);
|
521 |
+
|
522 |
+
$fileOptions = new FileOptions();
|
523 |
+
$fileOptions->setMethod(Method::STORE());
|
524 |
+
$fileOptions->setSize($fileSize);
|
525 |
+
$zip->addFileFromPsr7Stream('sample.json', $response->getBody(), $fileOptions);
|
526 |
+
$zip->finish();
|
527 |
+
fclose($stream);
|
528 |
+
|
529 |
+
$tmpDir = $this->validateAndExtractZip($tmp);
|
530 |
+
|
531 |
+
$files = $this->getRecursiveFileList($tmpDir);
|
532 |
+
$this->assertEquals(array('sample.json'), $files);
|
533 |
+
$this->assertStringEqualsFile($tmpDir . '/sample.json', $body);
|
534 |
+
}
|
535 |
+
|
536 |
+
public function testCreateArchiveWithFlushOptionSet(): void
|
537 |
+
{
|
538 |
+
[$tmp, $stream] = $this->getTmpFileStream();
|
539 |
+
|
540 |
+
$options = new ArchiveOptions();
|
541 |
+
$options->setOutputStream($stream);
|
542 |
+
$options->setFlushOutput(true);
|
543 |
+
|
544 |
+
$zip = new ZipStream(null, $options);
|
545 |
+
|
546 |
+
$zip->addFile('sample.txt', 'Sample String Data');
|
547 |
+
$zip->addFile('test/sample.txt', 'More Simple Sample Data');
|
548 |
+
|
549 |
+
$zip->finish();
|
550 |
+
fclose($stream);
|
551 |
+
|
552 |
+
$tmpDir = $this->validateAndExtractZip($tmp);
|
553 |
+
|
554 |
+
$files = $this->getRecursiveFileList($tmpDir);
|
555 |
+
$this->assertEquals(['sample.txt', 'test/sample.txt'], $files);
|
556 |
+
|
557 |
+
$this->assertStringEqualsFile($tmpDir . '/sample.txt', 'Sample String Data');
|
558 |
+
$this->assertStringEqualsFile($tmpDir . '/test/sample.txt', 'More Simple Sample Data');
|
559 |
+
}
|
560 |
+
}
|
vendor/maennchen/zipstream-php/test/bootstrap.php
ADDED
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
declare(strict_types=1);
|
3 |
+
|
4 |
+
date_default_timezone_set('UTC');
|
5 |
+
|
6 |
+
require __DIR__ . '/../vendor/autoload.php';
|
vendor/maennchen/zipstream-php/test/bug/BugHonorFileTimeTest.php
ADDED
@@ -0,0 +1,39 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
declare(strict_types=1);
|
3 |
+
|
4 |
+
namespace BugHonorFileTimeTest;
|
5 |
+
|
6 |
+
use DateTime;
|
7 |
+
use PHPUnit\Framework\TestCase;
|
8 |
+
use ZipStream\Option\{
|
9 |
+
Archive,
|
10 |
+
File
|
11 |
+
};
|
12 |
+
use ZipStream\ZipStream;
|
13 |
+
|
14 |
+
use function fopen;
|
15 |
+
|
16 |
+
/**
|
17 |
+
* Asserts that specified last-modified timestamps are not overwritten when a
|
18 |
+
* file is added
|
19 |
+
*/
|
20 |
+
class BugHonorFileTimeTest extends TestCase
|
21 |
+
{
|
22 |
+
public function testHonorsFileTime(): void
|
23 |
+
{
|
24 |
+
$archiveOpt = new Archive();
|
25 |
+
$fileOpt = new File();
|
26 |
+
$expectedTime = new DateTime('2019-04-21T19:25:00-0800');
|
27 |
+
|
28 |
+
$archiveOpt->setOutputStream(fopen('php://memory', 'wb'));
|
29 |
+
$fileOpt->setTime(clone $expectedTime);
|
30 |
+
|
31 |
+
$zip = new ZipStream(null, $archiveOpt);
|
32 |
+
|
33 |
+
$zip->addFile('sample.txt', 'Sample', $fileOpt);
|
34 |
+
|
35 |
+
$zip->finish();
|
36 |
+
|
37 |
+
$this->assertEquals($expectedTime, $fileOpt->getTime());
|
38 |
+
}
|
39 |
+
}
|
vendor/myclabs/php-enum/LICENSE
ADDED
@@ -0,0 +1,18 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
The MIT License (MIT)
|
2 |
+
|
3 |
+
Copyright (c) 2015 My C-Labs
|
4 |
+
|
5 |
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
|
6 |
+
associated documentation files (the "Software"), to deal in the Software without restriction,
|
7 |
+
including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
8 |
+
and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
|
9 |
+
subject to the following conditions:
|
10 |
+
|
11 |
+
The above copyright notice and this permission notice shall be included in all copies or substantial
|
12 |
+
portions of the Software.
|
13 |
+
|
14 |
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
|
15 |
+
NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
16 |
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
17 |
+
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
18 |
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
vendor/myclabs/php-enum/README.md
ADDED
@@ -0,0 +1,131 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# PHP Enum implementation inspired from SplEnum
|
2 |
+
|
3 |
+
[![Build Status](https://travis-ci.org/myclabs/php-enum.png?branch=master)](https://travis-ci.org/myclabs/php-enum)
|
4 |
+
[![Latest Stable Version](https://poser.pugx.org/myclabs/php-enum/version.png)](https://packagist.org/packages/myclabs/php-enum)
|
5 |
+
[![Total Downloads](https://poser.pugx.org/myclabs/php-enum/downloads.png)](https://packagist.org/packages/myclabs/php-enum)
|
6 |
+
|
7 |
+
Maintenance for this project is [supported via Tidelift](https://tidelift.com/subscription/pkg/packagist-myclabs-php-enum?utm_source=packagist-myclabs-php-enum&utm_medium=referral&utm_campaign=readme).
|
8 |
+
|
9 |
+
## Why?
|
10 |
+
|
11 |
+
First, and mainly, `SplEnum` is not integrated to PHP, you have to install the extension separately.
|
12 |
+
|
13 |
+
Using an enum instead of class constants provides the following advantages:
|
14 |
+
|
15 |
+
- You can type-hint: `function setAction(Action $action) {`
|
16 |
+
- You can enrich the enum with methods (e.g. `format`, `parse`, …)
|
17 |
+
- You can extend the enum to add new values (make your enum `final` to prevent it)
|
18 |
+
- You can get a list of all the possible values (see below)
|
19 |
+
|
20 |
+
This Enum class is not intended to replace class constants, but only to be used when it makes sense.
|
21 |
+
|
22 |
+
## Installation
|
23 |
+
|
24 |
+
```
|
25 |
+
composer require myclabs/php-enum
|
26 |
+
```
|
27 |
+
|
28 |
+
## Declaration
|
29 |
+
|
30 |
+
```php
|
31 |
+
use MyCLabs\Enum\Enum;
|
32 |
+
|
33 |
+
/**
|
34 |
+
* Action enum
|
35 |
+
*/
|
36 |
+
class Action extends Enum
|
37 |
+
{
|
38 |
+
private const VIEW = 'view';
|
39 |
+
private const EDIT = 'edit';
|
40 |
+
}
|
41 |
+
```
|
42 |
+
|
43 |
+
## Usage
|
44 |
+
|
45 |
+
```php
|
46 |
+
$action = Action::VIEW();
|
47 |
+
|
48 |
+
// or with a dynamic key:
|
49 |
+
$action = Action::$key();
|
50 |
+
// or with a dynamic value:
|
51 |
+
$action = new Action($value);
|
52 |
+
```
|
53 |
+
|
54 |
+
As you can see, static methods are automatically implemented to provide quick access to an enum value.
|
55 |
+
|
56 |
+
One advantage over using class constants is to be able to type-hint enum values:
|
57 |
+
|
58 |
+
```php
|
59 |
+
function setAction(Action $action) {
|
60 |
+
// ...
|
61 |
+
}
|
62 |
+
```
|
63 |
+
|
64 |
+
## Documentation
|
65 |
+
|
66 |
+
- `__construct()` The constructor checks that the value exist in the enum
|
67 |
+
- `__toString()` You can `echo $myValue`, it will display the enum value (value of the constant)
|
68 |
+
- `getValue()` Returns the current value of the enum
|
69 |
+
- `getKey()` Returns the key of the current value on Enum
|
70 |
+
- `equals()` Tests whether enum instances are equal (returns `true` if enum values are equal, `false` otherwise)
|
71 |
+
|
72 |
+
Static methods:
|
73 |
+
|
74 |
+
- `toArray()` method Returns all possible values as an array (constant name in key, constant value in value)
|
75 |
+
- `keys()` Returns the names (keys) of all constants in the Enum class
|
76 |
+
- `values()` Returns instances of the Enum class of all Enum constants (constant name in key, Enum instance in value)
|
77 |
+
- `isValid()` Check if tested value is valid on enum set
|
78 |
+
- `isValidKey()` Check if tested key is valid on enum set
|
79 |
+
- `search()` Return key for searched value
|
80 |
+
|
81 |
+
### Static methods
|
82 |
+
|
83 |
+
```php
|
84 |
+
class Action extends Enum
|
85 |
+
{
|
86 |
+
private const VIEW = 'view';
|
87 |
+
private const EDIT = 'edit';
|
88 |
+
}
|
89 |
+
|
90 |
+
// Static method:
|
91 |
+
$action = Action::VIEW();
|
92 |
+
$action = Action::EDIT();
|
93 |
+
```
|
94 |
+
|
95 |
+
Static method helpers are implemented using [`__callStatic()`](http://www.php.net/manual/en/language.oop5.overloading.php#object.callstatic).
|
96 |
+
|
97 |
+
If you care about IDE autocompletion, you can either implement the static methods yourself:
|
98 |
+
|
99 |
+
```php
|
100 |
+
class Action extends Enum
|
101 |
+
{
|
102 |
+
private const VIEW = 'view';
|
103 |
+
|
104 |
+
/**
|
105 |
+
* @return Action
|
106 |
+
*/
|
107 |
+
public static function VIEW() {
|
108 |
+
return new Action(self::VIEW);
|
109 |
+
}
|
110 |
+
}
|
111 |
+
```
|
112 |
+
|
113 |
+
or you can use phpdoc (this is supported in PhpStorm for example):
|
114 |
+
|
115 |
+
```php
|
116 |
+
/**
|
117 |
+
* @method static Action VIEW()
|
118 |
+
* @method static Action EDIT()
|
119 |
+
*/
|
120 |
+
class Action extends Enum
|
121 |
+
{
|
122 |
+
private const VIEW = 'view';
|
123 |
+
private const EDIT = 'edit';
|
124 |
+
}
|
125 |
+
```
|
126 |
+
|
127 |
+
## Related projects
|
128 |
+
|
129 |
+
- [Doctrine enum mapping](https://github.com/acelaya/doctrine-enum-type)
|
130 |
+
- [Symfony ParamConverter integration](https://github.com/Ex3v/MyCLabsEnumParamConverter)
|
131 |
+
- [PHPStan integration](https://github.com/timeweb/phpstan-enum)
|
vendor/myclabs/php-enum/SECURITY.md
ADDED
@@ -0,0 +1,11 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# Security Policy
|
2 |
+
|
3 |
+
## Supported Versions
|
4 |
+
|
5 |
+
Only the latest stable release is supported.
|
6 |
+
|
7 |
+
## Reporting a Vulnerability
|
8 |
+
|
9 |
+
To report a security vulnerability, please use the [Tidelift security contact](https://tidelift.com/security).
|
10 |
+
|
11 |
+
Tidelift will coordinate the fix and disclosure.
|
vendor/myclabs/php-enum/composer.json
ADDED
@@ -0,0 +1,32 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{
|
2 |
+
"name": "myclabs/php-enum",
|
3 |
+
"type": "library",
|
4 |
+
"description": "PHP Enum implementation",
|
5 |
+
"keywords": ["enum"],
|
6 |
+
"homepage": "http://github.com/myclabs/php-enum",
|
7 |
+
"license": "MIT",
|
8 |
+
"authors": [
|
9 |
+
{
|
10 |
+
"name": "PHP Enum contributors",
|
11 |
+
"homepage": "https://github.com/myclabs/php-enum/graphs/contributors"
|
12 |
+
}
|
13 |
+
],
|
14 |
+
"autoload": {
|
15 |
+
"psr-4": {
|
16 |
+
"MyCLabs\\Enum\\": "src/"
|
17 |
+
}
|
18 |
+
},
|
19 |
+
"autoload-dev": {
|
20 |
+
"psr-4": {
|
21 |
+
"MyCLabs\\Tests\\Enum\\": "tests/"
|
22 |
+
}
|
23 |
+
},
|
24 |
+
"require": {
|
25 |
+
"php": ">=7.1",
|
26 |
+
"ext-json": "*"
|
27 |
+
},
|
28 |
+
"require-dev": {
|
29 |
+
"phpunit/phpunit": "^4.8.35|^5.7|^6.0",
|
30 |
+
"squizlabs/php_codesniffer": "1.*"
|
31 |
+
}
|
32 |
+
}
|
vendor/myclabs/php-enum/src/Enum.php
ADDED
@@ -0,0 +1,205 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* @link http://github.com/myclabs/php-enum
|
4 |
+
* @license http://www.opensource.org/licenses/mit-license.php MIT (see the LICENSE file)
|
5 |
+
*/
|
6 |
+
|
7 |
+
namespace MyCLabs\Enum;
|
8 |
+
|
9 |
+
/**
|
10 |
+
* Base Enum class
|
11 |
+
*
|
12 |
+
* Create an enum by implementing this class and adding class constants.
|
13 |
+
*
|
14 |
+
* @author Matthieu Napoli <matthieu@mnapoli.fr>
|
15 |
+
* @author Daniel Costa <danielcosta@gmail.com>
|
16 |
+
* @author Mirosław Filip <mirfilip@gmail.com>
|
17 |
+
*/
|
18 |
+
abstract class Enum implements \JsonSerializable
|
19 |
+
{
|
20 |
+
/**
|
21 |
+
* Enum value
|
22 |
+
*
|
23 |
+
* @var mixed
|
24 |
+
*/
|
25 |
+
protected $value;
|
26 |
+
|
27 |
+
/**
|
28 |
+
* Store existing constants in a static cache per object.
|
29 |
+
*
|
30 |
+
* @var array
|
31 |
+
*/
|
32 |
+
protected static $cache = [];
|
33 |
+
|
34 |
+
/**
|
35 |
+
* Creates a new value of some type
|
36 |
+
*
|
37 |
+
* @param mixed $value
|
38 |
+
*
|
39 |
+
* @throws \UnexpectedValueException if incompatible type is given.
|
40 |
+
*/
|
41 |
+
public function __construct($value)
|
42 |
+
{
|
43 |
+
if ($value instanceof static) {
|
44 |
+
$value = $value->getValue();
|
45 |
+
}
|
46 |
+
|
47 |
+
if (!$this->isValid($value)) {
|
48 |
+
throw new \UnexpectedValueException("Value '$value' is not part of the enum " . \get_called_class());
|
49 |
+
}
|
50 |
+
|
51 |
+
$this->value = $value;
|
52 |
+
}
|
53 |
+
|
54 |
+
/**
|
55 |
+
* @return mixed
|
56 |
+
*/
|
57 |
+
public function getValue()
|
58 |
+
{
|
59 |
+
return $this->value;
|
60 |
+
}
|
61 |
+
|
62 |
+
/**
|
63 |
+
* Returns the enum key (i.e. the constant name).
|
64 |
+
*
|
65 |
+
* @return mixed
|
66 |
+
*/
|
67 |
+
public function getKey()
|
68 |
+
{
|
69 |
+
return static::search($this->value);
|
70 |
+
}
|
71 |
+
|
72 |
+
/**
|
73 |
+
* @return string
|
74 |
+
*/
|
75 |
+
public function __toString()
|
76 |
+
{
|
77 |
+
return (string)$this->value;
|
78 |
+
}
|
79 |
+
|
80 |
+
/**
|
81 |
+
* Determines if Enum should be considered equal with the variable passed as a parameter.
|
82 |
+
* Returns false if an argument is an object of different class or not an object.
|
83 |
+
*
|
84 |
+
* This method is final, for more information read https://github.com/myclabs/php-enum/issues/4
|
85 |
+
*
|
86 |
+
* @return bool
|
87 |
+
*/
|
88 |
+
final public function equals($variable = null): bool
|
89 |
+
{
|
90 |
+
return $variable instanceof self
|
91 |
+
&& $this->getValue() === $variable->getValue()
|
92 |
+
&& \get_called_class() === \get_class($variable);
|
93 |
+
}
|
94 |
+
|
95 |
+
/**
|
96 |
+
* Returns the names (keys) of all constants in the Enum class
|
97 |
+
*
|
98 |
+
* @return array
|
99 |
+
*/
|
100 |
+
public static function keys()
|
101 |
+
{
|
102 |
+
return \array_keys(static::toArray());
|
103 |
+
}
|
104 |
+
|
105 |
+
/**
|
106 |
+
* Returns instances of the Enum class of all Enum constants
|
107 |
+
*
|
108 |
+
* @return static[] Constant name in key, Enum instance in value
|
109 |
+
*/
|
110 |
+
public static function values()
|
111 |
+
{
|
112 |
+
$values = array();
|
113 |
+
|
114 |
+
foreach (static::toArray() as $key => $value) {
|
115 |
+
$values[$key] = new static($value);
|
116 |
+
}
|
117 |
+
|
118 |
+
return $values;
|
119 |
+
}
|
120 |
+
|
121 |
+
/**
|
122 |
+
* Returns all possible values as an array
|
123 |
+
*
|
124 |
+
* @return array Constant name in key, constant value in value
|
125 |
+
*/
|
126 |
+
public static function toArray()
|
127 |
+
{
|
128 |
+
$class = \get_called_class();
|
129 |
+
if (!isset(static::$cache[$class])) {
|
130 |
+
$reflection = new \ReflectionClass($class);
|
131 |
+
static::$cache[$class] = $reflection->getConstants();
|
132 |
+
}
|
133 |
+
|
134 |
+
return static::$cache[$class];
|
135 |
+
}
|
136 |
+
|
137 |
+
/**
|
138 |
+
* Check if is valid enum value
|
139 |
+
*
|
140 |
+
* @param $value
|
141 |
+
*
|
142 |
+
* @return bool
|
143 |
+
*/
|
144 |
+
public static function isValid($value)
|
145 |
+
{
|
146 |
+
return \in_array($value, static::toArray(), true);
|
147 |
+
}
|
148 |
+
|
149 |
+
/**
|
150 |
+
* Check if is valid enum key
|
151 |
+
*
|
152 |
+
* @param $key
|
153 |
+
*
|
154 |
+
* @return bool
|
155 |
+
*/
|
156 |
+
public static function isValidKey($key)
|
157 |
+
{
|
158 |
+
$array = static::toArray();
|
159 |
+
|
160 |
+
return isset($array[$key]) || \array_key_exists($key, $array);
|
161 |
+
}
|
162 |
+
|
163 |
+
/**
|
164 |
+
* Return key for value
|
165 |
+
*
|
166 |
+
* @param $value
|
167 |
+
*
|
168 |
+
* @return mixed
|
169 |
+
*/
|
170 |
+
public static function search($value)
|
171 |
+
{
|
172 |
+
return \array_search($value, static::toArray(), true);
|
173 |
+
}
|
174 |
+
|
175 |
+
/**
|
176 |
+
* Returns a value when called statically like so: MyEnum::SOME_VALUE() given SOME_VALUE is a class constant
|
177 |
+
*
|
178 |
+
* @param string $name
|
179 |
+
* @param array $arguments
|
180 |
+
*
|
181 |
+
* @return static
|
182 |
+
* @throws \BadMethodCallException
|
183 |
+
*/
|
184 |
+
public static function __callStatic($name, $arguments)
|
185 |
+
{
|
186 |
+
$array = static::toArray();
|
187 |
+
if (isset($array[$name]) || \array_key_exists($name, $array)) {
|
188 |
+
return new static($array[$name]);
|
189 |
+
}
|
190 |
+
|
191 |
+
throw new \BadMethodCallException("No static method or enum constant '$name' in class " . \get_called_class());
|
192 |
+
}
|
193 |
+
|
194 |
+
/**
|
195 |
+
* Specify data which should be serialized to JSON. This method returns data that can be serialized by json_encode()
|
196 |
+
* natively.
|
197 |
+
*
|
198 |
+
* @return mixed
|
199 |
+
* @link http://php.net/manual/en/jsonserializable.jsonserialize.php
|
200 |
+
*/
|
201 |
+
public function jsonSerialize()
|
202 |
+
{
|
203 |
+
return $this->getValue();
|
204 |
+
}
|
205 |
+
}
|
vendor/myclabs/php-enum/src/PHPUnit/Comparator.php
ADDED
@@ -0,0 +1,54 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace MyCLabs\Enum\PHPUnit;
|
4 |
+
|
5 |
+
use MyCLabs\Enum\Enum;
|
6 |
+
use SebastianBergmann\Comparator\ComparisonFailure;
|
7 |
+
|
8 |
+
/**
|
9 |
+
* Use this Comparator to get nice output when using PHPUnit assertEquals() with Enums.
|
10 |
+
*
|
11 |
+
* Add this to your PHPUnit bootstrap PHP file:
|
12 |
+
*
|
13 |
+
* \SebastianBergmann\Comparator\Factory::getInstance()->register(new \MyCLabs\Enum\PHPUnit\Comparator());
|
14 |
+
*/
|
15 |
+
final class Comparator extends \SebastianBergmann\Comparator\Comparator
|
16 |
+
{
|
17 |
+
public function accepts($expected, $actual)
|
18 |
+
{
|
19 |
+
return $expected instanceof Enum && (
|
20 |
+
$actual instanceof Enum || $actual === null
|
21 |
+
);
|
22 |
+
}
|
23 |
+
|
24 |
+
/**
|
25 |
+
* @param Enum $expected
|
26 |
+
* @param Enum|null $actual
|
27 |
+
*
|
28 |
+
* @return void
|
29 |
+
*/
|
30 |
+
public function assertEquals($expected, $actual, $delta = 0.0, $canonicalize = false, $ignoreCase = false)
|
31 |
+
{
|
32 |
+
if ($expected->equals($actual)) {
|
33 |
+
return;
|
34 |
+
}
|
35 |
+
|
36 |
+
throw new ComparisonFailure(
|
37 |
+
$expected,
|
38 |
+
$actual,
|
39 |
+
$this->formatEnum($expected),
|
40 |
+
$this->formatEnum($actual),
|
41 |
+
false,
|
42 |
+
'Failed asserting that two Enums are equal.'
|
43 |
+
);
|
44 |
+
}
|
45 |
+
|
46 |
+
private function formatEnum(Enum $enum = null)
|
47 |
+
{
|
48 |
+
if ($enum === null) {
|
49 |
+
return "null";
|
50 |
+
}
|
51 |
+
|
52 |
+
return get_class($enum)."::{$enum->getKey()}()";
|
53 |
+
}
|
54 |
+
}
|
vendor/psr/http-message/CHANGELOG.md
ADDED
@@ -0,0 +1,36 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# Changelog
|
2 |
+
|
3 |
+
All notable changes to this project will be documented in this file, in reverse chronological order by release.
|
4 |
+
|
5 |
+
## 1.0.1 - 2016-08-06
|
6 |
+
|
7 |
+
### Added
|
8 |
+
|
9 |
+
- Nothing.
|
10 |
+
|
11 |
+
### Deprecated
|
12 |
+
|
13 |
+
- Nothing.
|
14 |
+
|
15 |
+
### Removed
|
16 |
+
|
17 |
+
- Nothing.
|
18 |
+
|
19 |
+
### Fixed
|
20 |
+
|
21 |
+
- Updated all `@return self` annotation references in interfaces to use
|
22 |
+
`@return static`, which more closelly follows the semantics of the
|
23 |
+
specification.
|
24 |
+
- Updated the `MessageInterface::getHeaders()` return annotation to use the
|
25 |
+
value `string[][]`, indicating the format is a nested array of strings.
|
26 |
+
- Updated the `@link` annotation for `RequestInterface::withRequestTarget()`
|
27 |
+
to point to the correct section of RFC 7230.
|
28 |
+
- Updated the `ServerRequestInterface::withUploadedFiles()` parameter annotation
|
29 |
+
to add the parameter name (`$uploadedFiles`).
|
30 |
+
- Updated a `@throws` annotation for the `UploadedFileInterface::moveTo()`
|
31 |
+
method to correctly reference the method parameter (it was referencing an
|
32 |
+
incorrect parameter name previously).
|
33 |
+
|
34 |
+
## 1.0.0 - 2016-05-18
|
35 |
+
|
36 |
+
Initial stable release; reflects accepted PSR-7 specification.
|
vendor/psr/http-message/LICENSE
ADDED
@@ -0,0 +1,19 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
Copyright (c) 2014 PHP Framework Interoperability Group
|
2 |
+
|
3 |
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
4 |
+
of this software and associated documentation files (the "Software"), to deal
|
5 |
+
in the Software without restriction, including without limitation the rights
|
6 |
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
7 |
+
copies of the Software, and to permit persons to whom the Software is
|
8 |
+
furnished to do so, subject to the following conditions:
|
9 |
+
|
10 |
+
The above copyright notice and this permission notice shall be included in
|
11 |
+
all copies or substantial portions of the Software.
|
12 |
+
|
13 |
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14 |
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15 |
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
16 |
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
17 |
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
18 |
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
19 |
+
THE SOFTWARE.
|
vendor/psr/http-message/README.md
ADDED
@@ -0,0 +1,13 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
PSR Http Message
|
2 |
+
================
|
3 |
+
|
4 |
+
This repository holds all interfaces/classes/traits related to
|
5 |
+
[PSR-7](http://www.php-fig.org/psr/psr-7/).
|
6 |
+
|
7 |
+
Note that this is not a HTTP message implementation of its own. It is merely an
|
8 |
+
interface that describes a HTTP message. See the specification for more details.
|
9 |
+
|
10 |
+
Usage
|
11 |
+
-----
|
12 |
+
|
13 |
+
We'll certainly need some stuff in here.
|
vendor/psr/http-message/composer.json
ADDED
@@ -0,0 +1,26 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{
|
2 |
+
"name": "psr/http-message",
|
3 |
+
"description": "Common interface for HTTP messages",
|
4 |
+
"keywords": ["psr", "psr-7", "http", "http-message", "request", "response"],
|
5 |
+
"homepage": "https://github.com/php-fig/http-message",
|
6 |
+
"license": "MIT",
|
7 |
+
"authors": [
|
8 |
+
{
|
9 |
+
"name": "PHP-FIG",
|
10 |
+
"homepage": "http://www.php-fig.org/"
|
11 |
+
}
|
12 |
+
],
|
13 |
+
"require": {
|
14 |
+
"php": ">=5.3.0"
|
15 |
+
},
|
16 |
+
"autoload": {
|
17 |
+
"psr-4": {
|
18 |
+
"Psr\\Http\\Message\\": "src/"
|
19 |
+
}
|
20 |
+
},
|
21 |
+
"extra": {
|
22 |
+
"branch-alias": {
|
23 |
+
"dev-master": "1.0.x-dev"
|
24 |
+
}
|
25 |
+
}
|
26 |
+
}
|
vendor/psr/http-message/src/MessageInterface.php
ADDED
@@ -0,0 +1,187 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace Psr\Http\Message;
|
4 |
+
|
5 |
+
/**
|
6 |
+
* HTTP messages consist of requests from a client to a server and responses
|
7 |
+
* from a server to a client. This interface defines the methods common to
|
8 |
+
* each.
|
9 |
+
*
|
10 |
+
* Messages are considered immutable; all methods that might change state MUST
|
11 |
+
* be implemented such that they retain the internal state of the current
|
12 |
+
* message and return an instance that contains the changed state.
|
13 |
+
*
|
14 |
+
* @link http://www.ietf.org/rfc/rfc7230.txt
|
15 |
+
* @link http://www.ietf.org/rfc/rfc7231.txt
|
16 |
+
*/
|
17 |
+
interface MessageInterface
|
18 |
+
{
|
19 |
+
/**
|
20 |
+
* Retrieves the HTTP protocol version as a string.
|
21 |
+
*
|
22 |
+
* The string MUST contain only the HTTP version number (e.g., "1.1", "1.0").
|
23 |
+
*
|
24 |
+
* @return string HTTP protocol version.
|
25 |
+
*/
|
26 |
+
public function getProtocolVersion();
|
27 |
+
|
28 |
+
/**
|
29 |
+
* Return an instance with the specified HTTP protocol version.
|
30 |
+
*
|
31 |
+
* The version string MUST contain only the HTTP version number (e.g.,
|
32 |
+
* "1.1", "1.0").
|
33 |
+
*
|
34 |
+
* This method MUST be implemented in such a way as to retain the
|
35 |
+
* immutability of the message, and MUST return an instance that has the
|
36 |
+
* new protocol version.
|
37 |
+
*
|
38 |
+
* @param string $version HTTP protocol version
|
39 |
+
* @return static
|
40 |
+
*/
|
41 |
+
public function withProtocolVersion($version);
|
42 |
+
|
43 |
+
/**
|
44 |
+
* Retrieves all message header values.
|
45 |
+
*
|
46 |
+
* The keys represent the header name as it will be sent over the wire, and
|
47 |
+
* each value is an array of strings associated with the header.
|
48 |
+
*
|
49 |
+
* // Represent the headers as a string
|
50 |
+
* foreach ($message->getHeaders() as $name => $values) {
|
51 |
+
* echo $name . ": " . implode(", ", $values);
|
52 |
+
* }
|
53 |
+
*
|
54 |
+
* // Emit headers iteratively:
|
55 |
+
* foreach ($message->getHeaders() as $name => $values) {
|
56 |
+
* foreach ($values as $value) {
|
57 |
+
* header(sprintf('%s: %s', $name, $value), false);
|
58 |
+
* }
|
59 |
+
* }
|
60 |
+
*
|
61 |
+
* While header names are not case-sensitive, getHeaders() will preserve the
|
62 |
+
* exact case in which headers were originally specified.
|
63 |
+
*
|
64 |
+
* @return string[][] Returns an associative array of the message's headers. Each
|
65 |
+
* key MUST be a header name, and each value MUST be an array of strings
|
66 |
+
* for that header.
|
67 |
+
*/
|
68 |
+
public function getHeaders();
|
69 |
+
|
70 |
+
/**
|
71 |
+
* Checks if a header exists by the given case-insensitive name.
|
72 |
+
*
|
73 |
+
* @param string $name Case-insensitive header field name.
|
74 |
+
* @return bool Returns true if any header names match the given header
|
75 |
+
* name using a case-insensitive string comparison. Returns false if
|
76 |
+
* no matching header name is found in the message.
|
77 |
+
*/
|
78 |
+
public function hasHeader($name);
|
79 |
+
|
80 |
+
/**
|
81 |
+
* Retrieves a message header value by the given case-insensitive name.
|
82 |
+
*
|
83 |
+
* This method returns an array of all the header values of the given
|
84 |
+
* case-insensitive header name.
|
85 |
+
*
|
86 |
+
* If the header does not appear in the message, this method MUST return an
|
87 |
+
* empty array.
|
88 |
+
*
|
89 |
+
* @param string $name Case-insensitive header field name.
|
90 |
+
* @return string[] An array of string values as provided for the given
|
91 |
+
* header. If the header does not appear in the message, this method MUST
|
92 |
+
* return an empty array.
|
93 |
+
*/
|
94 |
+
public function getHeader($name);
|
95 |
+
|
96 |
+
/**
|
97 |
+
* Retrieves a comma-separated string of the values for a single header.
|
98 |
+
*
|
99 |
+
* This method returns all of the header values of the given
|
100 |
+
* case-insensitive header name as a string concatenated together using
|
101 |
+
* a comma.
|
102 |
+
*
|
103 |
+
* NOTE: Not all header values may be appropriately represented using
|
104 |
+
* comma concatenation. For such headers, use getHeader() instead
|
105 |
+
* and supply your own delimiter when concatenating.
|
106 |
+
*
|
107 |
+
* If the header does not appear in the message, this method MUST return
|
108 |
+
* an empty string.
|
109 |
+
*
|
110 |
+
* @param string $name Case-insensitive header field name.
|
111 |
+
* @return string A string of values as provided for the given header
|
112 |
+
* concatenated together using a comma. If the header does not appear in
|
113 |
+
* the message, this method MUST return an empty string.
|
114 |
+
*/
|
115 |
+
public function getHeaderLine($name);
|
116 |
+
|
117 |
+
/**
|
118 |
+
* Return an instance with the provided value replacing the specified header.
|
119 |
+
*
|
120 |
+
* While header names are case-insensitive, the casing of the header will
|
121 |
+
* be preserved by this function, and returned from getHeaders().
|
122 |
+
*
|
123 |
+
* This method MUST be implemented in such a way as to retain the
|
124 |
+
* immutability of the message, and MUST return an instance that has the
|
125 |
+
* new and/or updated header and value.
|
126 |
+
*
|
127 |
+
* @param string $name Case-insensitive header field name.
|
128 |
+
* @param string|string[] $value Header value(s).
|
129 |
+
* @return static
|
130 |
+
* @throws \InvalidArgumentException for invalid header names or values.
|
131 |
+
*/
|
132 |
+
public function withHeader($name, $value);
|
133 |
+
|
134 |
+
/**
|
135 |
+
* Return an instance with the specified header appended with the given value.
|
136 |
+
*
|
137 |
+
* Existing values for the specified header will be maintained. The new
|
138 |
+
* value(s) will be appended to the existing list. If the header did not
|
139 |
+
* exist previously, it will be added.
|
140 |
+
*
|
141 |
+
* This method MUST be implemented in such a way as to retain the
|
142 |
+
* immutability of the message, and MUST return an instance that has the
|
143 |
+
* new header and/or value.
|
144 |
+
*
|
145 |
+
* @param string $name Case-insensitive header field name to add.
|
146 |
+
* @param string|string[] $value Header value(s).
|
147 |
+
* @return static
|
148 |
+
* @throws \InvalidArgumentException for invalid header names or values.
|
149 |
+
*/
|
150 |
+
public function withAddedHeader($name, $value);
|
151 |
+
|
152 |
+
/**
|
153 |
+
* Return an instance without the specified header.
|
154 |
+
*
|
155 |
+
* Header resolution MUST be done without case-sensitivity.
|
156 |
+
*
|
157 |
+
* This method MUST be implemented in such a way as to retain the
|
158 |
+
* immutability of the message, and MUST return an instance that removes
|
159 |
+
* the named header.
|
160 |
+
*
|
161 |
+
* @param string $name Case-insensitive header field name to remove.
|
162 |
+
* @return static
|
163 |
+
*/
|
164 |
+
public function withoutHeader($name);
|
165 |
+
|
166 |
+
/**
|
167 |
+
* Gets the body of the message.
|
168 |
+
*
|
169 |
+
* @return StreamInterface Returns the body as a stream.
|
170 |
+
*/
|
171 |
+
public function getBody();
|
172 |
+
|
173 |
+
/**
|
174 |
+
* Return an instance with the specified message body.
|
175 |
+
*
|
176 |
+
* The body MUST be a StreamInterface object.
|
177 |
+
*
|
178 |
+
* This method MUST be implemented in such a way as to retain the
|
179 |
+
* immutability of the message, and MUST return a new instance that has the
|
180 |
+
* new body stream.
|
181 |
+
*
|
182 |
+
* @param StreamInterface $body Body.
|
183 |
+
* @return static
|
184 |
+
* @throws \InvalidArgumentException When the body is not valid.
|
185 |
+
*/
|
186 |
+
public function withBody(StreamInterface $body);
|
187 |
+
}
|
vendor/psr/http-message/src/RequestInterface.php
ADDED
@@ -0,0 +1,129 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace Psr\Http\Message;
|
4 |
+
|
5 |
+
/**
|
6 |
+
* Representation of an outgoing, client-side request.
|
7 |
+
*
|
8 |
+
* Per the HTTP specification, this interface includes properties for
|
9 |
+
* each of the following:
|
10 |
+
*
|
11 |
+
* - Protocol version
|
12 |
+
* - HTTP method
|
13 |
+
* - URI
|
14 |
+
* - Headers
|
15 |
+
* - Message body
|
16 |
+
*
|
17 |
+
* During construction, implementations MUST attempt to set the Host header from
|
18 |
+
* a provided URI if no Host header is provided.
|
19 |
+
*
|
20 |
+
* Requests are considered immutable; all methods that might change state MUST
|
21 |
+
* be implemented such that they retain the internal state of the current
|
22 |
+
* message and return an instance that contains the changed state.
|
23 |
+
*/
|
24 |
+
interface RequestInterface extends MessageInterface
|
25 |
+
{
|
26 |
+
/**
|
27 |
+
* Retrieves the message's request target.
|
28 |
+
*
|
29 |
+
* Retrieves the message's request-target either as it will appear (for
|
30 |
+
* clients), as it appeared at request (for servers), or as it was
|
31 |
+
* specified for the instance (see withRequestTarget()).
|
32 |
+
*
|
33 |
+
* In most cases, this will be the origin-form of the composed URI,
|
34 |
+
* unless a value was provided to the concrete implementation (see
|
35 |
+
* withRequestTarget() below).
|
36 |
+
*
|
37 |
+
* If no URI is available, and no request-target has been specifically
|
38 |
+
* provided, this method MUST return the string "/".
|
39 |
+
*
|
40 |
+
* @return string
|
41 |
+
*/
|
42 |
+
public function getRequestTarget();
|
43 |
+
|
44 |
+
/**
|
45 |
+
* Return an instance with the specific request-target.
|
46 |
+
*
|
47 |
+
* If the request needs a non-origin-form request-target — e.g., for
|
48 |
+
* specifying an absolute-form, authority-form, or asterisk-form —
|
49 |
+
* this method may be used to create an instance with the specified
|
50 |
+
* request-target, verbatim.
|
51 |
+
*
|
52 |
+
* This method MUST be implemented in such a way as to retain the
|
53 |
+
* immutability of the message, and MUST return an instance that has the
|
54 |
+
* changed request target.
|
55 |
+
*
|
56 |
+
* @link http://tools.ietf.org/html/rfc7230#section-5.3 (for the various
|
57 |
+
* request-target forms allowed in request messages)
|
58 |
+
* @param mixed $requestTarget
|
59 |
+
* @return static
|
60 |
+
*/
|
61 |
+
public function withRequestTarget($requestTarget);
|
62 |
+
|
63 |
+
/**
|
64 |
+
* Retrieves the HTTP method of the request.
|
65 |
+
*
|
66 |
+
* @return string Returns the request method.
|
67 |
+
*/
|
68 |
+
public function getMethod();
|
69 |
+
|
70 |
+
/**
|
71 |
+
* Return an instance with the provided HTTP method.
|
72 |
+
*
|
73 |
+
* While HTTP method names are typically all uppercase characters, HTTP
|
74 |
+
* method names are case-sensitive and thus implementations SHOULD NOT
|
75 |
+
* modify the given string.
|
76 |
+
*
|
77 |
+
* This method MUST be implemented in such a way as to retain the
|
78 |
+
* immutability of the message, and MUST return an instance that has the
|
79 |
+
* changed request method.
|
80 |
+
*
|
81 |
+
* @param string $method Case-sensitive method.
|
82 |
+
* @return static
|
83 |
+
* @throws \InvalidArgumentException for invalid HTTP methods.
|
84 |
+
*/
|
85 |
+
public function withMethod($method);
|
86 |
+
|
87 |
+
/**
|
88 |
+
* Retrieves the URI instance.
|
89 |
+
*
|
90 |
+
* This method MUST return a UriInterface instance.
|
91 |
+
*
|
92 |
+
* @link http://tools.ietf.org/html/rfc3986#section-4.3
|
93 |
+
* @return UriInterface Returns a UriInterface instance
|
94 |
+
* representing the URI of the request.
|
95 |
+
*/
|
96 |
+
public function getUri();
|
97 |
+
|
98 |
+
/**
|
99 |
+
* Returns an instance with the provided URI.
|
100 |
+
*
|
101 |
+
* This method MUST update the Host header of the returned request by
|
102 |
+
* default if the URI contains a host component. If the URI does not
|
103 |
+
* contain a host component, any pre-existing Host header MUST be carried
|
104 |
+
* over to the returned request.
|
105 |
+
*
|
106 |
+
* You can opt-in to preserving the original state of the Host header by
|
107 |
+
* setting `$preserveHost` to `true`. When `$preserveHost` is set to
|
108 |
+
* `true`, this method interacts with the Host header in the following ways:
|
109 |
+
*
|
110 |
+
* - If the Host header is missing or empty, and the new URI contains
|
111 |
+
* a host component, this method MUST update the Host header in the returned
|
112 |
+
* request.
|
113 |
+
* - If the Host header is missing or empty, and the new URI does not contain a
|
114 |
+
* host component, this method MUST NOT update the Host header in the returned
|
115 |
+
* request.
|
116 |
+
* - If a Host header is present and non-empty, this method MUST NOT update
|
117 |
+
* the Host header in the returned request.
|
118 |
+
*
|
119 |
+
* This method MUST be implemented in such a way as to retain the
|
120 |
+
* immutability of the message, and MUST return an instance that has the
|
121 |
+
* new UriInterface instance.
|
122 |
+
*
|
123 |
+
* @link http://tools.ietf.org/html/rfc3986#section-4.3
|
124 |
+
* @param UriInterface $uri New request URI to use.
|
125 |
+
* @param bool $preserveHost Preserve the original state of the Host header.
|
126 |
+
* @return static
|
127 |
+
*/
|
128 |
+
public function withUri(UriInterface $uri, $preserveHost = false);
|
129 |
+
}
|
vendor/psr/http-message/src/ResponseInterface.php
ADDED
@@ -0,0 +1,68 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace Psr\Http\Message;
|
4 |
+
|
5 |
+
/**
|
6 |
+
* Representation of an outgoing, server-side response.
|
7 |
+
*
|
8 |
+
* Per the HTTP specification, this interface includes properties for
|
9 |
+
* each of the following:
|
10 |
+
*
|
11 |
+
* - Protocol version
|
12 |
+
* - Status code and reason phrase
|
13 |
+
* - Headers
|
14 |
+
* - Message body
|
15 |
+
*
|
16 |
+
* Responses are considered immutable; all methods that might change state MUST
|
17 |
+
* be implemented such that they retain the internal state of the current
|
18 |
+
* message and return an instance that contains the changed state.
|
19 |
+
*/
|
20 |
+
interface ResponseInterface extends MessageInterface
|
21 |
+
{
|
22 |
+
/**
|
23 |
+
* Gets the response status code.
|
24 |
+
*
|
25 |
+
* The status code is a 3-digit integer result code of the server's attempt
|
26 |
+
* to understand and satisfy the request.
|
27 |
+
*
|
28 |
+
* @return int Status code.
|
29 |
+
*/
|
30 |
+
public function getStatusCode();
|
31 |
+
|
32 |
+
/**
|
33 |
+
* Return an instance with the specified status code and, optionally, reason phrase.
|
34 |
+
*
|
35 |
+
* If no reason phrase is specified, implementations MAY choose to default
|
36 |
+
* to the RFC 7231 or IANA recommended reason phrase for the response's
|
37 |
+
* status code.
|
38 |
+
*
|
39 |
+
* This method MUST be implemented in such a way as to retain the
|
40 |
+
* immutability of the message, and MUST return an instance that has the
|
41 |
+
* updated status and reason phrase.
|
42 |
+
*
|
43 |
+
* @link http://tools.ietf.org/html/rfc7231#section-6
|
44 |
+
* @link http://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml
|
45 |
+
* @param int $code The 3-digit integer result code to set.
|
46 |
+
* @param string $reasonPhrase The reason phrase to use with the
|
47 |
+
* provided status code; if none is provided, implementations MAY
|
48 |
+
* use the defaults as suggested in the HTTP specification.
|
49 |
+
* @return static
|
50 |
+
* @throws \InvalidArgumentException For invalid status code arguments.
|
51 |
+
*/
|
52 |
+
public function withStatus($code, $reasonPhrase = '');
|
53 |
+
|
54 |
+
/**
|
55 |
+
* Gets the response reason phrase associated with the status code.
|
56 |
+
*
|
57 |
+
* Because a reason phrase is not a required element in a response
|
58 |
+
* status line, the reason phrase value MAY be null. Implementations MAY
|
59 |
+
* choose to return the default RFC 7231 recommended reason phrase (or those
|
60 |
+
* listed in the IANA HTTP Status Code Registry) for the response's
|
61 |
+
* status code.
|
62 |
+
*
|
63 |
+
* @link http://tools.ietf.org/html/rfc7231#section-6
|
64 |
+
* @link http://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml
|
65 |
+
* @return string Reason phrase; must return an empty string if none present.
|
66 |
+
*/
|
67 |
+
public function getReasonPhrase();
|
68 |
+
}
|
vendor/psr/http-message/src/ServerRequestInterface.php
ADDED
@@ -0,0 +1,261 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace Psr\Http\Message;
|
4 |
+
|
5 |
+
/**
|
6 |
+
* Representation of an incoming, server-side HTTP request.
|
7 |
+
*
|
8 |
+
* Per the HTTP specification, this interface includes properties for
|
9 |
+
* each of the following:
|
10 |
+
*
|
11 |
+
* - Protocol version
|
12 |
+
* - HTTP method
|
13 |
+
* - URI
|
14 |
+
* - Headers
|
15 |
+
* - Message body
|
16 |
+
*
|
17 |
+
* Additionally, it encapsulates all data as it has arrived to the
|
18 |
+
* application from the CGI and/or PHP environment, including:
|
19 |
+
*
|
20 |
+
* - The values represented in $_SERVER.
|
21 |
+
* - Any cookies provided (generally via $_COOKIE)
|
22 |
+
* - Query string arguments (generally via $_GET, or as parsed via parse_str())
|
23 |
+
* - Upload files, if any (as represented by $_FILES)
|
24 |
+
* - Deserialized body parameters (generally from $_POST)
|
25 |
+
*
|
26 |
+
* $_SERVER values MUST be treated as immutable, as they represent application
|
27 |
+
* state at the time of request; as such, no methods are provided to allow
|
28 |
+
* modification of those values. The other values provide such methods, as they
|
29 |
+
* can be restored from $_SERVER or the request body, and may need treatment
|
30 |
+
* during the application (e.g., body parameters may be deserialized based on
|
31 |
+
* content type).
|
32 |
+
*
|
33 |
+
* Additionally, this interface recognizes the utility of introspecting a
|
34 |
+
* request to derive and match additional parameters (e.g., via URI path
|
35 |
+
* matching, decrypting cookie values, deserializing non-form-encoded body
|
36 |
+
* content, matching authorization headers to users, etc). These parameters
|
37 |
+
* are stored in an "attributes" property.
|
38 |
+
*
|
39 |
+
* Requests are considered immutable; all methods that might change state MUST
|
40 |
+
* be implemented such that they retain the internal state of the current
|
41 |
+
* message and return an instance that contains the changed state.
|
42 |
+
*/
|
43 |
+
interface ServerRequestInterface extends RequestInterface
|
44 |
+
{
|
45 |
+
/**
|
46 |
+
* Retrieve server parameters.
|
47 |
+
*
|
48 |
+
* Retrieves data related to the incoming request environment,
|
49 |
+
* typically derived from PHP's $_SERVER superglobal. The data IS NOT
|
50 |
+
* REQUIRED to originate from $_SERVER.
|
51 |
+
*
|
52 |
+
* @return array
|
53 |
+
*/
|
54 |
+
public function getServerParams();
|
55 |
+
|
56 |
+
/**
|
57 |
+
* Retrieve cookies.
|
58 |
+
*
|
59 |
+
* Retrieves cookies sent by the client to the server.
|
60 |
+
*
|
61 |
+
* The data MUST be compatible with the structure of the $_COOKIE
|
62 |
+
* superglobal.
|
63 |
+
*
|
64 |
+
* @return array
|
65 |
+
*/
|
66 |
+
public function getCookieParams();
|
67 |
+
|
68 |
+
/**
|
69 |
+
* Return an instance with the specified cookies.
|
70 |
+
*
|
71 |
+
* The data IS NOT REQUIRED to come from the $_COOKIE superglobal, but MUST
|
72 |
+
* be compatible with the structure of $_COOKIE. Typically, this data will
|
73 |
+
* be injected at instantiation.
|
74 |
+
*
|
75 |
+
* This method MUST NOT update the related Cookie header of the request
|
76 |
+
* instance, nor related values in the server params.
|
77 |
+
*
|
78 |
+
* This method MUST be implemented in such a way as to retain the
|
79 |
+
* immutability of the message, and MUST return an instance that has the
|
80 |
+
* updated cookie values.
|
81 |
+
*
|
82 |
+
* @param array $cookies Array of key/value pairs representing cookies.
|
83 |
+
* @return static
|
84 |
+
*/
|
85 |
+
public function withCookieParams(array $cookies);
|
86 |
+
|
87 |
+
/**
|
88 |
+
* Retrieve query string arguments.
|
89 |
+
*
|
90 |
+
* Retrieves the deserialized query string arguments, if any.
|
91 |
+
*
|
92 |
+
* Note: the query params might not be in sync with the URI or server
|
93 |
+
* params. If you need to ensure you are only getting the original
|
94 |
+
* values, you may need to parse the query string from `getUri()->getQuery()`
|
95 |
+
* or from the `QUERY_STRING` server param.
|
96 |
+
*
|
97 |
+
* @return array
|
98 |
+
*/
|
99 |
+
public function getQueryParams();
|
100 |
+
|
101 |
+
/**
|
102 |
+
* Return an instance with the specified query string arguments.
|
103 |
+
*
|
104 |
+
* These values SHOULD remain immutable over the course of the incoming
|
105 |
+
* request. They MAY be injected during instantiation, such as from PHP's
|
106 |
+
* $_GET superglobal, or MAY be derived from some other value such as the
|
107 |
+
* URI. In cases where the arguments are parsed from the URI, the data
|
108 |
+
* MUST be compatible with what PHP's parse_str() would return for
|
109 |
+
* purposes of how duplicate query parameters are handled, and how nested
|
110 |
+
* sets are handled.
|
111 |
+
*
|
112 |
+
* Setting query string arguments MUST NOT change the URI stored by the
|
113 |
+
* request, nor the values in the server params.
|
114 |
+
*
|
115 |
+
* This method MUST be implemented in such a way as to retain the
|
116 |
+
* immutability of the message, and MUST return an instance that has the
|
117 |
+
* updated query string arguments.
|
118 |
+
*
|
119 |
+
* @param array $query Array of query string arguments, typically from
|
120 |
+
* $_GET.
|
121 |
+
* @return static
|
122 |
+
*/
|
123 |
+
public function withQueryParams(array $query);
|
124 |
+
|
125 |
+
/**
|
126 |
+
* Retrieve normalized file upload data.
|
127 |
+
*
|
128 |
+
* This method returns upload metadata in a normalized tree, with each leaf
|
129 |
+
* an instance of Psr\Http\Message\UploadedFileInterface.
|
130 |
+
*
|
131 |
+
* These values MAY be prepared from $_FILES or the message body during
|
132 |
+
* instantiation, or MAY be injected via withUploadedFiles().
|
133 |
+
*
|
134 |
+
* @return array An array tree of UploadedFileInterface instances; an empty
|
135 |
+
* array MUST be returned if no data is present.
|
136 |
+
*/
|
137 |
+
public function getUploadedFiles();
|
138 |
+
|
139 |
+
/**
|
140 |
+
* Create a new instance with the specified uploaded files.
|
141 |
+
*
|
142 |
+
* This method MUST be implemented in such a way as to retain the
|
143 |
+
* immutability of the message, and MUST return an instance that has the
|
144 |
+
* updated body parameters.
|
145 |
+
*
|
146 |
+
* @param array $uploadedFiles An array tree of UploadedFileInterface instances.
|
147 |
+
* @return static
|
148 |
+
* @throws \InvalidArgumentException if an invalid structure is provided.
|
149 |
+
*/
|
150 |
+
public function withUploadedFiles(array $uploadedFiles);
|
151 |
+
|
152 |
+
/**
|
153 |
+
* Retrieve any parameters provided in the request body.
|
154 |
+
*
|
155 |
+
* If the request Content-Type is either application/x-www-form-urlencoded
|
156 |
+
* or multipart/form-data, and the request method is POST, this method MUST
|
157 |
+
* return the contents of $_POST.
|
158 |
+
*
|
159 |
+
* Otherwise, this method may return any results of deserializing
|
160 |
+
* the request body content; as parsing returns structured content, the
|
161 |
+
* potential types MUST be arrays or objects only. A null value indicates
|
162 |
+
* the absence of body content.
|
163 |
+
*
|
164 |
+
* @return null|array|object The deserialized body parameters, if any.
|
165 |
+
* These will typically be an array or object.
|
166 |
+
*/
|
167 |
+
public function getParsedBody();
|
168 |
+
|
169 |
+
/**
|
170 |
+
* Return an instance with the specified body parameters.
|
171 |
+
*
|
172 |
+
* These MAY be injected during instantiation.
|
173 |
+
*
|
174 |
+
* If the request Content-Type is either application/x-www-form-urlencoded
|
175 |
+
* or multipart/form-data, and the request method is POST, use this method
|
176 |
+
* ONLY to inject the contents of $_POST.
|
177 |
+
*
|
178 |
+
* The data IS NOT REQUIRED to come from $_POST, but MUST be the results of
|
179 |
+
* deserializing the request body content. Deserialization/parsing returns
|
180 |
+
* structured data, and, as such, this method ONLY accepts arrays or objects,
|
181 |
+
* or a null value if nothing was available to parse.
|
182 |
+
*
|
183 |
+
* As an example, if content negotiation determines that the request data
|
184 |
+
* is a JSON payload, this method could be used to create a request
|
185 |
+
* instance with the deserialized parameters.
|
186 |
+
*
|
187 |
+
* This method MUST be implemented in such a way as to retain the
|
188 |
+
* immutability of the message, and MUST return an instance that has the
|
189 |
+
* updated body parameters.
|
190 |
+
*
|
191 |
+
* @param null|array|object $data The deserialized body data. This will
|
192 |
+
* typically be in an array or object.
|
193 |
+
* @return static
|
194 |
+
* @throws \InvalidArgumentException if an unsupported argument type is
|
195 |
+
* provided.
|
196 |
+
*/
|
197 |
+
public function withParsedBody($data);
|
198 |
+
|
199 |
+
/**
|
200 |
+
* Retrieve attributes derived from the request.
|
201 |
+
*
|
202 |
+
* The request "attributes" may be used to allow injection of any
|
203 |
+
* parameters derived from the request: e.g., the results of path
|
204 |
+
* match operations; the results of decrypting cookies; the results of
|
205 |
+
* deserializing non-form-encoded message bodies; etc. Attributes
|
206 |
+
* will be application and request specific, and CAN be mutable.
|
207 |
+
*
|
208 |
+
* @return array Attributes derived from the request.
|
209 |
+
*/
|
210 |
+
public function getAttributes();
|
211 |
+
|
212 |
+
/**
|
213 |
+
* Retrieve a single derived request attribute.
|
214 |
+
*
|
215 |
+
* Retrieves a single derived request attribute as described in
|
216 |
+
* getAttributes(). If the attribute has not been previously set, returns
|
217 |
+
* the default value as provided.
|
218 |
+
*
|
219 |
+
* This method obviates the need for a hasAttribute() method, as it allows
|
220 |
+
* specifying a default value to return if the attribute is not found.
|
221 |
+
*
|
222 |
+
* @see getAttributes()
|
223 |
+
* @param string $name The attribute name.
|
224 |
+
* @param mixed $default Default value to return if the attribute does not exist.
|
225 |
+
* @return mixed
|
226 |
+
*/
|
227 |
+
public function getAttribute($name, $default = null);
|
228 |
+
|
229 |
+
/**
|
230 |
+
* Return an instance with the specified derived request attribute.
|
231 |
+
*
|
232 |
+
* This method allows setting a single derived request attribute as
|
233 |
+
* described in getAttributes().
|
234 |
+
*
|
235 |
+
* This method MUST be implemented in such a way as to retain the
|
236 |
+
* immutability of the message, and MUST return an instance that has the
|
237 |
+
* updated attribute.
|
238 |
+
*
|
239 |
+
* @see getAttributes()
|
240 |
+
* @param string $name The attribute name.
|
241 |
+
* @param mixed $value The value of the attribute.
|
242 |
+
* @return static
|
243 |
+
*/
|
244 |
+
public function withAttribute($name, $value);
|
245 |
+
|
246 |
+
/**
|
247 |
+
* Return an instance that removes the specified derived request attribute.
|
248 |
+
*
|
249 |
+
* This method allows removing a single derived request attribute as
|
250 |
+
* described in getAttributes().
|
251 |
+
*
|
252 |
+
* This method MUST be implemented in such a way as to retain the
|
253 |
+
* immutability of the message, and MUST return an instance that removes
|
254 |
+
* the attribute.
|
255 |
+
*
|
256 |
+
* @see getAttributes()
|
257 |
+
* @param string $name The attribute name.
|
258 |
+
* @return static
|
259 |
+
*/
|
260 |
+
public function withoutAttribute($name);
|
261 |
+
}
|
vendor/psr/http-message/src/StreamInterface.php
ADDED
@@ -0,0 +1,158 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace Psr\Http\Message;
|
4 |
+
|
5 |
+
/**
|
6 |
+
* Describes a data stream.
|
7 |
+
*
|
8 |
+
* Typically, an instance will wrap a PHP stream; this interface provides
|
9 |
+
* a wrapper around the most common operations, including serialization of
|
10 |
+
* the entire stream to a string.
|
11 |
+
*/
|
12 |
+
interface StreamInterface
|
13 |
+
{
|
14 |
+
/**
|
15 |
+
* Reads all data from the stream into a string, from the beginning to end.
|
16 |
+
*
|
17 |
+
* This method MUST attempt to seek to the beginning of the stream before
|
18 |
+
* reading data and read the stream until the end is reached.
|
19 |
+
*
|
20 |
+
* Warning: This could attempt to load a large amount of data into memory.
|
21 |
+
*
|
22 |
+
* This method MUST NOT raise an exception in order to conform with PHP's
|
23 |
+
* string casting operations.
|
24 |
+
*
|
25 |
+
* @see http://php.net/manual/en/language.oop5.magic.php#object.tostring
|
26 |
+
* @return string
|
27 |
+
*/
|
28 |
+
public function __toString();
|
29 |
+
|
30 |
+
/**
|
31 |
+
* Closes the stream and any underlying resources.
|
32 |
+
*
|
33 |
+
* @return void
|
34 |
+
*/
|
35 |
+
public function close();
|
36 |
+
|
37 |
+
/**
|
38 |
+
* Separates any underlying resources from the stream.
|
39 |
+
*
|
40 |
+
* After the stream has been detached, the stream is in an unusable state.
|
41 |
+
*
|
42 |
+
* @return resource|null Underlying PHP stream, if any
|
43 |
+
*/
|
44 |
+
public function detach();
|
45 |
+
|
46 |
+
/**
|
47 |
+
* Get the size of the stream if known.
|
48 |
+
*
|
49 |
+
* @return int|null Returns the size in bytes if known, or null if unknown.
|
50 |
+
*/
|
51 |
+
public function getSize();
|
52 |
+
|
53 |
+
/**
|
54 |
+
* Returns the current position of the file read/write pointer
|
55 |
+
*
|
56 |
+
* @return int Position of the file pointer
|
57 |
+
* @throws \RuntimeException on error.
|
58 |
+
*/
|
59 |
+
public function tell();
|
60 |
+
|
61 |
+
/**
|
62 |
+
* Returns true if the stream is at the end of the stream.
|
63 |
+
*
|
64 |
+
* @return bool
|
65 |
+
*/
|
66 |
+
public function eof();
|
67 |
+
|
68 |
+
/**
|
69 |
+
* Returns whether or not the stream is seekable.
|
70 |
+
*
|
71 |
+
* @return bool
|
72 |
+
*/
|
73 |
+
public function isSeekable();
|
74 |
+
|
75 |
+
/**
|
76 |
+
* Seek to a position in the stream.
|
77 |
+
*
|
78 |
+
* @link http://www.php.net/manual/en/function.fseek.php
|
79 |
+
* @param int $offset Stream offset
|
80 |
+
* @param int $whence Specifies how the cursor position will be calculated
|
81 |
+
* based on the seek offset. Valid values are identical to the built-in
|
82 |
+
* PHP $whence values for `fseek()`. SEEK_SET: Set position equal to
|
83 |
+
* offset bytes SEEK_CUR: Set position to current location plus offset
|
84 |
+
* SEEK_END: Set position to end-of-stream plus offset.
|
85 |
+
* @throws \RuntimeException on failure.
|
86 |
+
*/
|
87 |
+
public function seek($offset, $whence = SEEK_SET);
|
88 |
+
|
89 |
+
/**
|
90 |
+
* Seek to the beginning of the stream.
|
91 |
+
*
|
92 |
+
* If the stream is not seekable, this method will raise an exception;
|
93 |
+
* otherwise, it will perform a seek(0).
|
94 |
+
*
|
95 |
+
* @see seek()
|
96 |
+
* @link http://www.php.net/manual/en/function.fseek.php
|
97 |
+
* @throws \RuntimeException on failure.
|
98 |
+
*/
|
99 |
+
public function rewind();
|
100 |
+
|
101 |
+
/**
|
102 |
+
* Returns whether or not the stream is writable.
|
103 |
+
*
|
104 |
+
* @return bool
|
105 |
+
*/
|
106 |
+
public function isWritable();
|
107 |
+
|
108 |
+
/**
|
109 |
+
* Write data to the stream.
|
110 |
+
*
|
111 |
+
* @param string $string The string that is to be written.
|
112 |
+
* @return int Returns the number of bytes written to the stream.
|
113 |
+
* @throws \RuntimeException on failure.
|
114 |
+
*/
|
115 |
+
public function write($string);
|
116 |
+
|
117 |
+
/**
|
118 |
+
* Returns whether or not the stream is readable.
|
119 |
+
*
|
120 |
+
* @return bool
|
121 |
+
*/
|
122 |
+
public function isReadable();
|
123 |
+
|
124 |
+
/**
|
125 |
+
* Read data from the stream.
|
126 |
+
*
|
127 |
+
* @param int $length Read up to $length bytes from the object and return
|
128 |
+
* them. Fewer than $length bytes may be returned if underlying stream
|
129 |
+
* call returns fewer bytes.
|
130 |
+
* @return string Returns the data read from the stream, or an empty string
|
131 |
+
* if no bytes are available.
|
132 |
+
* @throws \RuntimeException if an error occurs.
|
133 |
+
*/
|
134 |
+
public function read($length);
|
135 |
+
|
136 |
+
/**
|
137 |
+
* Returns the remaining contents in a string
|
138 |
+
*
|
139 |
+
* @return string
|
140 |
+
* @throws \RuntimeException if unable to read or an error occurs while
|
141 |
+
* reading.
|
142 |
+
*/
|
143 |
+
public function getContents();
|
144 |
+
|
145 |
+
/**
|
146 |
+
* Get stream metadata as an associative array or retrieve a specific key.
|
147 |
+
*
|
148 |
+
* The keys returned are identical to the keys returned from PHP's
|
149 |
+
* stream_get_meta_data() function.
|
150 |
+
*
|
151 |
+
* @link http://php.net/manual/en/function.stream-get-meta-data.php
|
152 |
+
* @param string $key Specific metadata to retrieve.
|
153 |
+
* @return array|mixed|null Returns an associative array if no key is
|
154 |
+
* provided. Returns a specific key value if a key is provided and the
|
155 |
+
* value is found, or null if the key is not found.
|
156 |
+
*/
|
157 |
+
public function getMetadata($key = null);
|
158 |
+
}
|
vendor/psr/http-message/src/UploadedFileInterface.php
ADDED
@@ -0,0 +1,123 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace Psr\Http\Message;
|
4 |
+
|
5 |
+
/**
|
6 |
+
* Value object representing a file uploaded through an HTTP request.
|
7 |
+
*
|
8 |
+
* Instances of this interface are considered immutable; all methods that
|
9 |
+
* might change state MUST be implemented such that they retain the internal
|
10 |
+
* state of the current instance and return an instance that contains the
|
11 |
+
* changed state.
|
12 |
+
*/
|
13 |
+
interface UploadedFileInterface
|
14 |
+
{
|
15 |
+
/**
|
16 |
+
* Retrieve a stream representing the uploaded file.
|
17 |
+
*
|
18 |
+
* This method MUST return a StreamInterface instance, representing the
|
19 |
+
* uploaded file. The purpose of this method is to allow utilizing native PHP
|
20 |
+
* stream functionality to manipulate the file upload, such as
|
21 |
+
* stream_copy_to_stream() (though the result will need to be decorated in a
|
22 |
+
* native PHP stream wrapper to work with such functions).
|
23 |
+
*
|
24 |
+
* If the moveTo() method has been called previously, this method MUST raise
|
25 |
+
* an exception.
|
26 |
+
*
|
27 |
+
* @return StreamInterface Stream representation of the uploaded file.
|
28 |
+
* @throws \RuntimeException in cases when no stream is available or can be
|
29 |
+
* created.
|
30 |
+
*/
|
31 |
+
public function getStream();
|
32 |
+
|
33 |
+
/**
|
34 |
+
* Move the uploaded file to a new location.
|
35 |
+
*
|
36 |
+
* Use this method as an alternative to move_uploaded_file(). This method is
|
37 |
+
* guaranteed to work in both SAPI and non-SAPI environments.
|
38 |
+
* Implementations must determine which environment they are in, and use the
|
39 |
+
* appropriate method (move_uploaded_file(), rename(), or a stream
|
40 |
+
* operation) to perform the operation.
|
41 |
+
*
|
42 |
+
* $targetPath may be an absolute path, or a relative path. If it is a
|
43 |
+
* relative path, resolution should be the same as used by PHP's rename()
|
44 |
+
* function.
|
45 |
+
*
|
46 |
+
* The original file or stream MUST be removed on completion.
|
47 |
+
*
|
48 |
+
* If this method is called more than once, any subsequent calls MUST raise
|
49 |
+
* an exception.
|
50 |
+
*
|
51 |
+
* When used in an SAPI environment where $_FILES is populated, when writing
|
52 |
+
* files via moveTo(), is_uploaded_file() and move_uploaded_file() SHOULD be
|
53 |
+
* used to ensure permissions and upload status are verified correctly.
|
54 |
+
*
|
55 |
+
* If you wish to move to a stream, use getStream(), as SAPI operations
|
56 |
+
* cannot guarantee writing to stream destinations.
|
57 |
+
*
|
58 |
+
* @see http://php.net/is_uploaded_file
|
59 |
+
* @see http://php.net/move_uploaded_file
|
60 |
+
* @param string $targetPath Path to which to move the uploaded file.
|
61 |
+
* @throws \InvalidArgumentException if the $targetPath specified is invalid.
|
62 |
+
* @throws \RuntimeException on any error during the move operation, or on
|
63 |
+
* the second or subsequent call to the method.
|
64 |
+
*/
|
65 |
+
public function moveTo($targetPath);
|
66 |
+
|
67 |
+
/**
|
68 |
+
* Retrieve the file size.
|
69 |
+
*
|
70 |
+
* Implementations SHOULD return the value stored in the "size" key of
|
71 |
+
* the file in the $_FILES array if available, as PHP calculates this based
|
72 |
+
* on the actual size transmitted.
|
73 |
+
*
|
74 |
+
* @return int|null The file size in bytes or null if unknown.
|
75 |
+
*/
|
76 |
+
public function getSize();
|
77 |
+
|
78 |
+
/**
|
79 |
+
* Retrieve the error associated with the uploaded file.
|
80 |
+
*
|
81 |
+
* The return value MUST be one of PHP's UPLOAD_ERR_XXX constants.
|
82 |
+
*
|
83 |
+
* If the file was uploaded successfully, this method MUST return
|
84 |
+
* UPLOAD_ERR_OK.
|
85 |
+
*
|
86 |
+
* Implementations SHOULD return the value stored in the "error" key of
|
87 |
+
* the file in the $_FILES array.
|
88 |
+
*
|
89 |
+
* @see http://php.net/manual/en/features.file-upload.errors.php
|
90 |
+
* @return int One of PHP's UPLOAD_ERR_XXX constants.
|
91 |
+
*/
|
92 |
+
public function getError();
|
93 |
+
|
94 |
+
/**
|
95 |
+
* Retrieve the filename sent by the client.
|
96 |
+
*
|
97 |
+
* Do not trust the value returned by this method. A client could send
|
98 |
+
* a malicious filename with the intention to corrupt or hack your
|
99 |
+
* application.
|
100 |
+
*
|
101 |
+
* Implementations SHOULD return the value stored in the "name" key of
|
102 |
+
* the file in the $_FILES array.
|
103 |
+
*
|
104 |
+
* @return string|null The filename sent by the client or null if none
|
105 |
+
* was provided.
|
106 |
+
*/
|
107 |
+
public function getClientFilename();
|
108 |
+
|
109 |
+
/**
|
110 |
+
* Retrieve the media type sent by the client.
|
111 |
+
*
|
112 |
+
* Do not trust the value returned by this method. A client could send
|
113 |
+
* a malicious media type with the intention to corrupt or hack your
|
114 |
+
* application.
|
115 |
+
*
|
116 |
+
* Implementations SHOULD return the value stored in the "type" key of
|
117 |
+
* the file in the $_FILES array.
|
118 |
+
*
|
119 |
+
* @return string|null The media type sent by the client or null if none
|
120 |
+
* was provided.
|
121 |
+
*/
|
122 |
+
public function getClientMediaType();
|
123 |
+
}
|
vendor/psr/http-message/src/UriInterface.php
ADDED
@@ -0,0 +1,323 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace Psr\Http\Message;
|
3 |
+
|
4 |
+
/**
|
5 |
+
* Value object representing a URI.
|
6 |
+
*
|
7 |
+
* This interface is meant to represent URIs according to RFC 3986 and to
|
8 |
+
* provide methods for most common operations. Additional functionality for
|
9 |
+
* working with URIs can be provided on top of the interface or externally.
|
10 |
+
* Its primary use is for HTTP requests, but may also be used in other
|
11 |
+
* contexts.
|
12 |
+
*
|
13 |
+
* Instances of this interface are considered immutable; all methods that
|
14 |
+
* might change state MUST be implemented such that they retain the internal
|
15 |
+
* state of the current instance and return an instance that contains the
|
16 |
+
* changed state.
|
17 |
+
*
|
18 |
+
* Typically the Host header will be also be present in the request message.
|
19 |
+
* For server-side requests, the scheme will typically be discoverable in the
|
20 |
+
* server parameters.
|
21 |
+
*
|
22 |
+
* @link http://tools.ietf.org/html/rfc3986 (the URI specification)
|
23 |
+
*/
|
24 |
+
interface UriInterface
|
25 |
+
{
|
26 |
+
/**
|
27 |
+
* Retrieve the scheme component of the URI.
|
28 |
+
*
|
29 |
+
* If no scheme is present, this method MUST return an empty string.
|
30 |
+
*
|
31 |
+
* The value returned MUST be normalized to lowercase, per RFC 3986
|
32 |
+
* Section 3.1.
|
33 |
+
*
|
34 |
+
* The trailing ":" character is not part of the scheme and MUST NOT be
|
35 |
+
* added.
|
36 |
+
*
|
37 |
+
* @see https://tools.ietf.org/html/rfc3986#section-3.1
|
38 |
+
* @return string The URI scheme.
|
39 |
+
*/
|
40 |
+
public function getScheme();
|
41 |
+
|
42 |
+
/**
|
43 |
+
* Retrieve the authority component of the URI.
|
44 |
+
*
|
45 |
+
* If no authority information is present, this method MUST return an empty
|
46 |
+
* string.
|
47 |
+
*
|
48 |
+
* The authority syntax of the URI is:
|
49 |
+
*
|
50 |
+
* <pre>
|
51 |
+
* [user-info@]host[:port]
|
52 |
+
* </pre>
|
53 |
+
*
|
54 |
+
* If the port component is not set or is the standard port for the current
|
55 |
+
* scheme, it SHOULD NOT be included.
|
56 |
+
*
|
57 |
+
* @see https://tools.ietf.org/html/rfc3986#section-3.2
|
58 |
+
* @return string The URI authority, in "[user-info@]host[:port]" format.
|
59 |
+
*/
|
60 |
+
public function getAuthority();
|
61 |
+
|
62 |
+
/**
|
63 |
+
* Retrieve the user information component of the URI.
|
64 |
+
*
|
65 |
+
* If no user information is present, this method MUST return an empty
|
66 |
+
* string.
|
67 |
+
*
|
68 |
+
* If a user is present in the URI, this will return that value;
|
69 |
+
* additionally, if the password is also present, it will be appended to the
|
70 |
+
* user value, with a colon (":") separating the values.
|
71 |
+
*
|
72 |
+
* The trailing "@" character is not part of the user information and MUST
|
73 |
+
* NOT be added.
|
74 |
+
*
|
75 |
+
* @return string The URI user information, in "username[:password]" format.
|
76 |
+
*/
|
77 |
+
public function getUserInfo();
|
78 |
+
|
79 |
+
/**
|
80 |
+
* Retrieve the host component of the URI.
|
81 |
+
*
|
82 |
+
* If no host is present, this method MUST return an empty string.
|
83 |
+
*
|
84 |
+
* The value returned MUST be normalized to lowercase, per RFC 3986
|
85 |
+
* Section 3.2.2.
|
86 |
+
*
|
87 |
+
* @see http://tools.ietf.org/html/rfc3986#section-3.2.2
|
88 |
+
* @return string The URI host.
|
89 |
+
*/
|
90 |
+
public function getHost();
|
91 |
+
|
92 |
+
/**
|
93 |
+
* Retrieve the port component of the URI.
|
94 |
+
*
|
95 |
+
* If a port is present, and it is non-standard for the current scheme,
|
96 |
+
* this method MUST return it as an integer. If the port is the standard port
|
97 |
+
* used with the current scheme, this method SHOULD return null.
|
98 |
+
*
|
99 |
+
* If no port is present, and no scheme is present, this method MUST return
|
100 |
+
* a null value.
|
101 |
+
*
|
102 |
+
* If no port is present, but a scheme is present, this method MAY return
|
103 |
+
* the standard port for that scheme, but SHOULD return null.
|
104 |
+
*
|
105 |
+
* @return null|int The URI port.
|
106 |
+
*/
|
107 |
+
public function getPort();
|
108 |
+
|
109 |
+
/**
|
110 |
+
* Retrieve the path component of the URI.
|
111 |
+
*
|
112 |
+
* The path can either be empty or absolute (starting with a slash) or
|
113 |
+
* rootless (not starting with a slash). Implementations MUST support all
|
114 |
+
* three syntaxes.
|
115 |
+
*
|
116 |
+
* Normally, the empty path "" and absolute path "/" are considered equal as
|
117 |
+
* defined in RFC 7230 Section 2.7.3. But this method MUST NOT automatically
|
118 |
+
* do this normalization because in contexts with a trimmed base path, e.g.
|
119 |
+
* the front controller, this difference becomes significant. It's the task
|
120 |
+
* of the user to handle both "" and "/".
|
121 |
+
*
|
122 |
+
* The value returned MUST be percent-encoded, but MUST NOT double-encode
|
123 |
+
* any characters. To determine what characters to encode, please refer to
|
124 |
+
* RFC 3986, Sections 2 and 3.3.
|
125 |
+
*
|
126 |
+
* As an example, if the value should include a slash ("/") not intended as
|
127 |
+
* delimiter between path segments, that value MUST be passed in encoded
|
128 |
+
* form (e.g., "%2F") to the instance.
|
129 |
+
*
|
130 |
+
* @see https://tools.ietf.org/html/rfc3986#section-2
|
131 |
+
* @see https://tools.ietf.org/html/rfc3986#section-3.3
|
132 |
+
* @return string The URI path.
|
133 |
+
*/
|
134 |
+
public function getPath();
|
135 |
+
|
136 |
+
/**
|
137 |
+
* Retrieve the query string of the URI.
|
138 |
+
*
|
139 |
+
* If no query string is present, this method MUST return an empty string.
|
140 |
+
*
|
141 |
+
* The leading "?" character is not part of the query and MUST NOT be
|
142 |
+
* added.
|
143 |
+
*
|
144 |
+
* The value returned MUST be percent-encoded, but MUST NOT double-encode
|
145 |
+
* any characters. To determine what characters to encode, please refer to
|
146 |
+
* RFC 3986, Sections 2 and 3.4.
|
147 |
+
*
|
148 |
+
* As an example, if a value in a key/value pair of the query string should
|
149 |
+
* include an ampersand ("&") not intended as a delimiter between values,
|
150 |
+
* that value MUST be passed in encoded form (e.g., "%26") to the instance.
|
151 |
+
*
|
152 |
+
* @see https://tools.ietf.org/html/rfc3986#section-2
|
153 |
+
* @see https://tools.ietf.org/html/rfc3986#section-3.4
|
154 |
+
* @return string The URI query string.
|
155 |
+
*/
|
156 |
+
public function getQuery();
|
157 |
+
|
158 |
+
/**
|
159 |
+
* Retrieve the fragment component of the URI.
|
160 |
+
*
|
161 |
+
* If no fragment is present, this method MUST return an empty string.
|
162 |
+
*
|
163 |
+
* The leading "#" character is not part of the fragment and MUST NOT be
|
164 |
+
* added.
|
165 |
+
*
|
166 |
+
* The value returned MUST be percent-encoded, but MUST NOT double-encode
|
167 |
+
* any characters. To determine what characters to encode, please refer to
|
168 |
+
* RFC 3986, Sections 2 and 3.5.
|
169 |
+
*
|
170 |
+
* @see https://tools.ietf.org/html/rfc3986#section-2
|
171 |
+
* @see https://tools.ietf.org/html/rfc3986#section-3.5
|
172 |
+
* @return string The URI fragment.
|
173 |
+
*/
|
174 |
+
public function getFragment();
|
175 |
+
|
176 |
+
/**
|
177 |
+
* Return an instance with the specified scheme.
|
178 |
+
*
|
179 |
+
* This method MUST retain the state of the current instance, and return
|
180 |
+
* an instance that contains the specified scheme.
|
181 |
+
*
|
182 |
+
* Implementations MUST support the schemes "http" and "https" case
|
183 |
+
* insensitively, and MAY accommodate other schemes if required.
|
184 |
+
*
|
185 |
+
* An empty scheme is equivalent to removing the scheme.
|
186 |
+
*
|
187 |
+
* @param string $scheme The scheme to use with the new instance.
|
188 |
+
* @return static A new instance with the specified scheme.
|
189 |
+
* @throws \InvalidArgumentException for invalid or unsupported schemes.
|
190 |
+
*/
|
191 |
+
public function withScheme($scheme);
|
192 |
+
|
193 |
+
/**
|
194 |
+
* Return an instance with the specified user information.
|
195 |
+
*
|
196 |
+
* This method MUST retain the state of the current instance, and return
|
197 |
+
* an instance that contains the specified user information.
|
198 |
+
*
|
199 |
+
* Password is optional, but the user information MUST include the
|
200 |
+
* user; an empty string for the user is equivalent to removing user
|
201 |
+
* information.
|
202 |
+
*
|
203 |
+
* @param string $user The user name to use for authority.
|
204 |
+
* @param null|string $password The password associated with $user.
|
205 |
+
* @return static A new instance with the specified user information.
|
206 |
+
*/
|
207 |
+
public function withUserInfo($user, $password = null);
|
208 |
+
|
209 |
+
/**
|
210 |
+
* Return an instance with the specified host.
|
211 |
+
*
|
212 |
+
* This method MUST retain the state of the current instance, and return
|
213 |
+
* an instance that contains the specified host.
|
214 |
+
*
|
215 |
+
* An empty host value is equivalent to removing the host.
|
216 |
+
*
|
217 |
+
* @param string $host The hostname to use with the new instance.
|
218 |
+
* @return static A new instance with the specified host.
|
219 |
+
* @throws \InvalidArgumentException for invalid hostnames.
|
220 |
+
*/
|
221 |
+
public function withHost($host);
|
222 |
+
|
223 |
+
/**
|
224 |
+
* Return an instance with the specified port.
|
225 |
+
*
|
226 |
+
* This method MUST retain the state of the current instance, and return
|
227 |
+
* an instance that contains the specified port.
|
228 |
+
*
|
229 |
+
* Implementations MUST raise an exception for ports outside the
|
230 |
+
* established TCP and UDP port ranges.
|
231 |
+
*
|
232 |
+
* A null value provided for the port is equivalent to removing the port
|
233 |
+
* information.
|
234 |
+
*
|
235 |
+
* @param null|int $port The port to use with the new instance; a null value
|
236 |
+
* removes the port information.
|
237 |
+
* @return static A new instance with the specified port.
|
238 |
+
* @throws \InvalidArgumentException for invalid ports.
|
239 |
+
*/
|
240 |
+
public function withPort($port);
|
241 |
+
|
242 |
+
/**
|
243 |
+
* Return an instance with the specified path.
|
244 |
+
*
|
245 |
+
* This method MUST retain the state of the current instance, and return
|
246 |
+
* an instance that contains the specified path.
|
247 |
+
*
|
248 |
+
* The path can either be empty or absolute (starting with a slash) or
|
249 |
+
* rootless (not starting with a slash). Implementations MUST support all
|
250 |
+
* three syntaxes.
|
251 |
+
*
|
252 |
+
* If the path is intended to be domain-relative rather than path relative then
|
253 |
+
* it must begin with a slash ("/"). Paths not starting with a slash ("/")
|
254 |
+
* are assumed to be relative to some base path known to the application or
|
255 |
+
* consumer.
|
256 |
+
*
|
257 |
+
* Users can provide both encoded and decoded path characters.
|
258 |
+
* Implementations ensure the correct encoding as outlined in getPath().
|
259 |
+
*
|
260 |
+
* @param string $path The path to use with the new instance.
|
261 |
+
* @return static A new instance with the specified path.
|
262 |
+
* @throws \InvalidArgumentException for invalid paths.
|
263 |
+
*/
|
264 |
+
public function withPath($path);
|
265 |
+
|
266 |
+
/**
|
267 |
+
* Return an instance with the specified query string.
|
268 |
+
*
|
269 |
+
* This method MUST retain the state of the current instance, and return
|
270 |
+
* an instance that contains the specified query string.
|
271 |
+
*
|
272 |
+
* Users can provide both encoded and decoded query characters.
|
273 |
+
* Implementations ensure the correct encoding as outlined in getQuery().
|
274 |
+
*
|
275 |
+
* An empty query string value is equivalent to removing the query string.
|
276 |
+
*
|
277 |
+
* @param string $query The query string to use with the new instance.
|
278 |
+
* @return static A new instance with the specified query string.
|
279 |
+
* @throws \InvalidArgumentException for invalid query strings.
|
280 |
+
*/
|
281 |
+
public function withQuery($query);
|
282 |
+
|
283 |
+
/**
|
284 |
+
* Return an instance with the specified URI fragment.
|
285 |
+
*
|
286 |
+
* This method MUST retain the state of the current instance, and return
|
287 |
+
* an instance that contains the specified URI fragment.
|
288 |
+
*
|
289 |
+
* Users can provide both encoded and decoded fragment characters.
|
290 |
+
* Implementations ensure the correct encoding as outlined in getFragment().
|
291 |
+
*
|
292 |
+
* An empty fragment value is equivalent to removing the fragment.
|
293 |
+
*
|
294 |
+
* @param string $fragment The fragment to use with the new instance.
|
295 |
+
* @return static A new instance with the specified fragment.
|
296 |
+
*/
|
297 |
+
public function withFragment($fragment);
|
298 |
+
|
299 |
+
/**
|
300 |
+
* Return the string representation as a URI reference.
|
301 |
+
*
|
302 |
+
* Depending on which components of the URI are present, the resulting
|
303 |
+
* string is either a full URI or relative reference according to RFC 3986,
|
304 |
+
* Section 4.1. The method concatenates the various components of the URI,
|
305 |
+
* using the appropriate delimiters:
|
306 |
+
*
|
307 |
+
* - If a scheme is present, it MUST be suffixed by ":".
|
308 |
+
* - If an authority is present, it MUST be prefixed by "//".
|
309 |
+
* - The path can be concatenated without delimiters. But there are two
|
310 |
+
* cases where the path has to be adjusted to make the URI reference
|
311 |
+
* valid as PHP does not allow to throw an exception in __toString():
|
312 |
+
* - If the path is rootless and an authority is present, the path MUST
|
313 |
+
* be prefixed by "/".
|
314 |
+
* - If the path is starting with more than one "/" and no authority is
|
315 |
+
* present, the starting slashes MUST be reduced to one.
|
316 |
+
* - If a query is present, it MUST be prefixed by "?".
|
317 |
+
* - If a fragment is present, it MUST be prefixed by "#".
|
318 |
+
*
|
319 |
+
* @see http://tools.ietf.org/html/rfc3986#section-4.1
|
320 |
+
* @return string
|
321 |
+
*/
|
322 |
+
public function __toString();
|
323 |
+
}
|