|
@@ -1,4 +1,4 @@
|
1
|
|
-<?
|
|
1
|
+<?php
|
2
|
2
|
/*************************************************************************|
|
3
|
3
|
|--------------- Zip class -----------------------------------------------|
|
4
|
4
|
|*************************************************************************|
|
|
@@ -74,97 +74,102 @@ http://www.fileformat.info/tool/hexdump.htm - Useful for analyzing ZIP files
|
74
|
74
|
|*************************************************************************/
|
75
|
75
|
|
76
|
76
|
if (!extension_loaded('zlib')) {
|
77
|
|
- error('Zlib Extension not loaded.');
|
|
77
|
+ error('Zlib Extension not loaded.');
|
78
|
78
|
}
|
79
|
79
|
|
80
|
|
-class Zip {
|
81
|
|
- public $ArchiveSize = 0; // Total size
|
82
|
|
- public $ArchiveFiles = 0; // Total files
|
83
|
|
- private $Structure = ''; // Structure saved to memory
|
84
|
|
- private $FileOffset = 0; // Offset to write data
|
85
|
|
- private $Data = ''; //An idea
|
86
|
|
-
|
87
|
|
- public function __construct ($ArchiveName = 'Archive') {
|
88
|
|
- header("Content-type: application/octet-stream"); // Stream download
|
89
|
|
- header("Content-disposition: attachment; filename=\"$ArchiveName.zip\""); // Name the archive - Should not be urlencoded
|
90
|
|
- }
|
91
|
|
-
|
92
|
|
- public static function unlimit () {
|
93
|
|
- ob_end_clean();
|
94
|
|
- set_time_limit(3600); // Limit 1 hour
|
95
|
|
- ini_set('memory_limit', '1024M'); // Because the buffers can get extremely large
|
96
|
|
- }
|
97
|
|
-
|
98
|
|
- public function add_file ($FileData, $ArchivePath, $TimeStamp = 0) {
|
99
|
|
- /* File header */
|
100
|
|
- $this->Data = "\x50\x4b\x03\x04"; // PK signature
|
101
|
|
- $this->Data .= "\x14\x00"; // Version requirements
|
102
|
|
- $this->Data .= "\x00\x08"; // Bit flag - 0x8 = UTF-8 file names
|
103
|
|
- $this->Data .= "\x08\x00"; // Compression
|
104
|
|
- $this->Data .= "\x00\x00\x00\x00";
|
105
|
|
- $DataLength = strlen($FileData); // Saved as variable to avoid wasting CPU calculating it multiple times.
|
106
|
|
- $CRC32 = crc32($FileData); // Ditto.
|
107
|
|
- $ZipData = gzcompress($FileData); // Ditto.
|
108
|
|
- $ZipData = substr ($ZipData, 2, (strlen($ZipData) - 6)); // Checksum resolution
|
109
|
|
- $ZipLength = strlen($ZipData); // Ditto.
|
110
|
|
- $this->Data .= pack('V', $CRC32); // CRC-32
|
111
|
|
- $this->Data .= pack('V', $ZipLength); // Compressed file size
|
112
|
|
- $this->Data .= pack('V', $DataLength); // Uncompressed file size
|
113
|
|
- $this->Data .= pack('v', strlen($ArchivePath)); // Path name length
|
114
|
|
- $this->Data .="\x00\x00"; // Extra field length (0'd so we can ignore this)
|
115
|
|
- $this->Data .= $ArchivePath; // File name & Extra Field (length set to 0 so ignored)
|
116
|
|
- /* END file header */
|
117
|
|
-
|
118
|
|
- /* File data */
|
119
|
|
- $this->Data .= $ZipData; // File data
|
120
|
|
- /* END file data */
|
121
|
|
-
|
122
|
|
- /* Data descriptor
|
123
|
|
- Not needed (only needed when 3rd bitflag is set), causes problems with OS X archive utility
|
124
|
|
- $this->Data .= pack('V', $CRC32); // CRC-32
|
125
|
|
- $this->Data .= pack('V', $ZipLength); // Compressed file size
|
126
|
|
- $this->Data .= pack('V', $DataLength); // Uncompressed file size
|
127
|
|
- END data descriptor */
|
128
|
|
-
|
129
|
|
- $FileDataLength = strlen($this->Data);
|
130
|
|
- $this->ArchiveSize = $this->ArchiveSize + $FileDataLength; // All we really need is the size
|
131
|
|
- $CurrentOffset = $this->ArchiveSize; // Update offsets
|
132
|
|
- echo $this->Data; // Get this out to reduce our memory consumption
|
133
|
|
-
|
134
|
|
- /* Central Directory Structure */
|
135
|
|
- $CDS = "\x50\x4b\x01\x02"; // CDS signature
|
136
|
|
- $CDS .="\x14\x00"; // Constructor version
|
137
|
|
- $CDS .="\x14\x00"; // Version requirements
|
138
|
|
- $CDS .="\x00\x08"; // Bit flag - 0x8 = UTF-8 file names
|
139
|
|
- $CDS .="\x08\x00"; // Compression
|
140
|
|
- $CDS .="\x00\x00\x00\x00"; // Last modified
|
141
|
|
- $CDS .= pack('V', $CRC32); // CRC-32
|
142
|
|
- $CDS .= pack('V', $ZipLength); // Compressed file size
|
143
|
|
- $CDS .= pack('V', $DataLength); // Uncompressed file size
|
144
|
|
- $CDS .= pack('v', strlen($ArchivePath)); // Path name length
|
145
|
|
- $CDS .="\x00\x00"; // Extra field length (0'd so we can ignore this)
|
146
|
|
- $CDS .="\x00\x00"; // File comment length (no comment, 0'd)
|
147
|
|
- $CDS .="\x00\x00"; // Disk number start (0 seems valid)
|
148
|
|
- $CDS .="\x00\x00"; // Internal file attributes (again with the 0's)
|
149
|
|
- $CDS .="\x20\x00\x00\x00"; // External file attributes
|
150
|
|
- $CDS .= pack('V', $this->FileOffset); // Offsets
|
151
|
|
- $CDS .= $ArchivePath; // File name & Extra Field (length set to 0 so ignored)
|
152
|
|
- /* END central Directory Structure */
|
153
|
|
-
|
154
|
|
- $this->FileOffset = $CurrentOffset; // Update offsets
|
155
|
|
- $this->Structure .= $CDS; // Append to structure
|
156
|
|
- $this->ArchiveFiles++; // Increment file count
|
157
|
|
- }
|
158
|
|
-
|
159
|
|
- public function close_stream() {
|
160
|
|
- echo $this->Structure; // Structure Root
|
161
|
|
- echo "\x50\x4b\x05\x06"; // End of central directory signature
|
162
|
|
- echo "\x00\x00"; // This disk
|
163
|
|
- echo "\x00\x00"; // CDS start
|
164
|
|
- echo pack('v', $this->ArchiveFiles); // Handle the number of entries
|
165
|
|
- echo pack('v', $this->ArchiveFiles); // Ditto
|
166
|
|
- echo pack('V', strlen($this->Structure)); //Size
|
167
|
|
- echo pack('V', $this->ArchiveSize); // Offset
|
168
|
|
- echo "\x00\x00"; // No comment, close it off
|
169
|
|
- }
|
|
80
|
+class Zip
|
|
81
|
+{
|
|
82
|
+ public $ArchiveSize = 0; // Total size
|
|
83
|
+ public $ArchiveFiles = 0; // Total files
|
|
84
|
+ private $Structure = ''; // Structure saved to memory
|
|
85
|
+ private $FileOffset = 0; // Offset to write data
|
|
86
|
+ private $Data = ''; //An idea
|
|
87
|
+
|
|
88
|
+ public function __construct($ArchiveName = 'Archive')
|
|
89
|
+ {
|
|
90
|
+ header("Content-type: application/octet-stream"); // Stream download
|
|
91
|
+ header("Content-disposition: attachment; filename=\"$ArchiveName.zip\""); // Name the archive - Should not be urlencoded
|
|
92
|
+ }
|
|
93
|
+
|
|
94
|
+ public static function unlimit()
|
|
95
|
+ {
|
|
96
|
+ ob_end_clean();
|
|
97
|
+ set_time_limit(3600); // Limit 1 hour
|
|
98
|
+ ini_set('memory_limit', '1024M'); // Because the buffers can get extremely large
|
|
99
|
+ }
|
|
100
|
+
|
|
101
|
+ public function add_file($FileData, $ArchivePath, $TimeStamp = 0)
|
|
102
|
+ {
|
|
103
|
+ /* File header */
|
|
104
|
+ $this->Data = "\x50\x4b\x03\x04"; // PK signature
|
|
105
|
+ $this->Data .= "\x14\x00"; // Version requirements
|
|
106
|
+ $this->Data .= "\x00\x08"; // Bit flag - 0x8 = UTF-8 file names
|
|
107
|
+ $this->Data .= "\x08\x00"; // Compression
|
|
108
|
+ $this->Data .= "\x00\x00\x00\x00";
|
|
109
|
+ $DataLength = strlen($FileData); // Saved as variable to avoid wasting CPU calculating it multiple times.
|
|
110
|
+ $CRC32 = crc32($FileData); // Ditto.
|
|
111
|
+ $ZipData = gzcompress($FileData); // Ditto.
|
|
112
|
+ $ZipData = substr($ZipData, 2, (strlen($ZipData) - 6)); // Checksum resolution
|
|
113
|
+ $ZipLength = strlen($ZipData); // Ditto.
|
|
114
|
+ $this->Data .= pack('V', $CRC32); // CRC-32
|
|
115
|
+ $this->Data .= pack('V', $ZipLength); // Compressed file size
|
|
116
|
+ $this->Data .= pack('V', $DataLength); // Uncompressed file size
|
|
117
|
+ $this->Data .= pack('v', strlen($ArchivePath)); // Path name length
|
|
118
|
+ $this->Data .="\x00\x00"; // Extra field length (0'd so we can ignore this)
|
|
119
|
+ $this->Data .= $ArchivePath; // File name & Extra Field (length set to 0 so ignored)
|
|
120
|
+ /* END file header */
|
|
121
|
+
|
|
122
|
+ /* File data */
|
|
123
|
+ $this->Data .= $ZipData; // File data
|
|
124
|
+ /* END file data */
|
|
125
|
+
|
|
126
|
+ /* Data descriptor
|
|
127
|
+ Not needed (only needed when 3rd bitflag is set), causes problems with OS X archive utility
|
|
128
|
+ $this->Data .= pack('V', $CRC32); // CRC-32
|
|
129
|
+ $this->Data .= pack('V', $ZipLength); // Compressed file size
|
|
130
|
+ $this->Data .= pack('V', $DataLength); // Uncompressed file size
|
|
131
|
+ END data descriptor */
|
|
132
|
+
|
|
133
|
+ $FileDataLength = strlen($this->Data);
|
|
134
|
+ $this->ArchiveSize = $this->ArchiveSize + $FileDataLength; // All we really need is the size
|
|
135
|
+ $CurrentOffset = $this->ArchiveSize; // Update offsets
|
|
136
|
+ echo $this->Data; // Get this out to reduce our memory consumption
|
|
137
|
+
|
|
138
|
+ /* Central Directory Structure */
|
|
139
|
+ $CDS = "\x50\x4b\x01\x02"; // CDS signature
|
|
140
|
+ $CDS .="\x14\x00"; // Constructor version
|
|
141
|
+ $CDS .="\x14\x00"; // Version requirements
|
|
142
|
+ $CDS .="\x00\x08"; // Bit flag - 0x8 = UTF-8 file names
|
|
143
|
+ $CDS .="\x08\x00"; // Compression
|
|
144
|
+ $CDS .="\x00\x00\x00\x00"; // Last modified
|
|
145
|
+ $CDS .= pack('V', $CRC32); // CRC-32
|
|
146
|
+ $CDS .= pack('V', $ZipLength); // Compressed file size
|
|
147
|
+ $CDS .= pack('V', $DataLength); // Uncompressed file size
|
|
148
|
+ $CDS .= pack('v', strlen($ArchivePath)); // Path name length
|
|
149
|
+ $CDS .="\x00\x00"; // Extra field length (0'd so we can ignore this)
|
|
150
|
+ $CDS .="\x00\x00"; // File comment length (no comment, 0'd)
|
|
151
|
+ $CDS .="\x00\x00"; // Disk number start (0 seems valid)
|
|
152
|
+ $CDS .="\x00\x00"; // Internal file attributes (again with the 0's)
|
|
153
|
+ $CDS .="\x20\x00\x00\x00"; // External file attributes
|
|
154
|
+ $CDS .= pack('V', $this->FileOffset); // Offsets
|
|
155
|
+ $CDS .= $ArchivePath; // File name & Extra Field (length set to 0 so ignored)
|
|
156
|
+ /* END central Directory Structure */
|
|
157
|
+
|
|
158
|
+ $this->FileOffset = $CurrentOffset; // Update offsets
|
|
159
|
+ $this->Structure .= $CDS; // Append to structure
|
|
160
|
+ $this->ArchiveFiles++; // Increment file count
|
|
161
|
+ }
|
|
162
|
+
|
|
163
|
+ public function close_stream()
|
|
164
|
+ {
|
|
165
|
+ echo $this->Structure; // Structure Root
|
|
166
|
+ echo "\x50\x4b\x05\x06"; // End of central directory signature
|
|
167
|
+ echo "\x00\x00"; // This disk
|
|
168
|
+ echo "\x00\x00"; // CDS start
|
|
169
|
+ echo pack('v', $this->ArchiveFiles); // Handle the number of entries
|
|
170
|
+ echo pack('v', $this->ArchiveFiles); // Ditto
|
|
171
|
+ echo pack('V', strlen($this->Structure)); //Size
|
|
172
|
+ echo pack('V', $this->ArchiveSize); // Offset
|
|
173
|
+ echo "\x00\x00"; // No comment, close it off
|
|
174
|
+ }
|
170
|
175
|
}
|