XCL Web Application Platform 2.5.0
The XoopsCube Legacy Project
Loading...
Searching...
No Matches
class.tar.php
1<?php
14
23class tar
24{
28 public $filename;
29 public $isGzipped;
30 public $tar_file;
32
36 public $files;
37 public $directories;
38 public $numFiles;
39 public $numDirectories;
41
45 public function __construct()
46 {
47 return true;
48 }
49
59 public function __computeUnsignedChecksum($bytestring)
60 {
61 $unsigned_chksum = null;
62 for ($i=0; $i<512; $i++) {
63 $unsigned_chksum += ord($bytestring[$i]);
64 }
65 for ($i=0; $i<8; $i++) {
66 $unsigned_chksum -= ord($bytestring[148 + $i]);
67 }
68 $unsigned_chksum += ord(' ') * 8;
69
70 return $unsigned_chksum;
71 }
72
73
83 public function __parseNullPaddedString($string)
84 {
85 $position = strpos($string, chr(0));
86 return substr($string, 0, $position);
87 }
88
96 public function __parseTar()
97 {
98 // Read Files from archive
99 $tar_length = strlen($this->tar_file);
100 $main_offset = 0;
101 $this->numFiles = 0;
102 while ($main_offset < $tar_length) {
103 // If we read a block of 512 nulls, we are at the end of the archive
104 if (substr($this->tar_file, $main_offset, 512) == str_repeat(chr(0), 512)) {
105 break;
106 }
107
108 // Parse file name
109 $file_name = $this->__parseNullPaddedString(substr($this->tar_file, $main_offset, 100));
110
111 // Parse the file mode
112 $file_mode = substr($this->tar_file, $main_offset + 100, 8);
113
114 // Parse the file user ID
115 $file_uid = octdec(substr($this->tar_file, $main_offset + 108, 8));
116
117 // Parse the file group ID
118 $file_gid = octdec(substr($this->tar_file, $main_offset + 116, 8));
119
120 // Parse the file size
121 $file_size = octdec(substr($this->tar_file, $main_offset + 124, 12));
122
123 // Parse the file update time - unix timestamp format
124 $file_time = octdec(substr($this->tar_file, $main_offset + 136, 12));
125
126 // Parse Checksum
127 $file_chksum = octdec(substr($this->tar_file, $main_offset + 148, 6));
128
129 // Parse user name
130 $file_uname = $this->__parseNullPaddedString(substr($this->tar_file, $main_offset + 265, 32));
131
132 // Parse Group name
133 $file_gname = $this->__parseNullPaddedString(substr($this->tar_file, $main_offset + 297, 32));
134
135 // Make sure our file is valid
136 if ($this->__computeUnsignedChecksum(substr($this->tar_file, $main_offset, 512)) != $file_chksum) {
137 return false;
138 }
139
140 // Parse File Contents
141 $file_contents = substr($this->tar_file, $main_offset + 512, $file_size);
142
143 /* ### Unused Header Information ###
144 $activeFile["typeflag"] = substr($this->tar_file,$main_offset + 156,1);
145 $activeFile["linkname"] = substr($this->tar_file,$main_offset + 157,100);
146 $activeFile["magic"] = substr($this->tar_file,$main_offset + 257,6);
147 $activeFile["version"] = substr($this->tar_file,$main_offset + 263,2);
148 $activeFile["devmajor"] = substr($this->tar_file,$main_offset + 329,8);
149 $activeFile["devminor"] = substr($this->tar_file,$main_offset + 337,8);
150 $activeFile["prefix"] = substr($this->tar_file,$main_offset + 345,155);
151 $activeFile["endheader"] = substr($this->tar_file,$main_offset + 500,12);
152 */
153
154 if ($file_size > 0) {
155 // Increment number of files
156 $this->numFiles++;
157
158 // Create us a new file in our array
159 $activeFile = &$this->files[];
160
161 // Asign Values
162 $activeFile['name'] = $file_name;
163 $activeFile['mode'] = $file_mode;
164 $activeFile['size'] = $file_size;
165 $activeFile['time'] = $file_time;
166 $activeFile['user_id'] = $file_uid;
167 $activeFile['group_id'] = $file_gid;
168 $activeFile['user_name'] = $file_uname;
169 $activeFile['group_name'] = $file_gname;
170 $activeFile['checksum'] = $file_chksum;
171 $activeFile['file'] = $file_contents;
172 } else {
173 // Increment number of directories
174 $this->numDirectories++;
175
176 // Create a new directory in our array
177 $activeDir = &$this->directories[];
178
179 // Assign values
180 $activeDir['name'] = $file_name;
181 $activeDir['mode'] = $file_mode;
182 $activeDir['time'] = $file_time;
183 $activeDir['user_id'] = $file_uid;
184 $activeDir['group_id'] = $file_gid;
185 $activeDir['user_name'] = $file_uname;
186 $activeDir['group_name'] = $file_gname;
187 $activeDir['checksum'] = $file_chksum;
188 }
189
190 // Move our offset the number of blocks we have processed
191 $main_offset += 512 + (ceil($file_size / 512) * 512);
192 }
193
194 return true;
195 }
196
205 public function __readTar($filename='')
206 {
207 // Set the filename to load
208 if (!$filename) {
210 }
211
212 // Read in the TAR file
213 $fp = fopen($filename, 'rb');
214 $this->tar_file = fread($fp, filesize($filename));
215 fclose($fp);
216
217 if ($this->tar_file[0] == chr(31) && $this->tar_file[1] == chr(139) && $this->tar_file[2] == chr(8)) {
218 if (!function_exists('gzinflate')) {
219 return false;
220 }
221
222 $this->isGzipped = true;
223
224 $this->tar_file = gzinflate(substr($this->tar_file, 10, -4));
225 }
226
227 // Parse the TAR file
228 $this->__parseTar();
229
230 return true;
231 }
232
240 public function __generateTAR()
241 {
242 // Clear any data currently in $this->tar_file
243 unset($this->tar_file);
244
245 // Generate Records for each directory, if we have directories
246 if ($this->numDirectories > 0) {
247 foreach ($this->directories as $key => $information) {
248 unset($header);
249
250 // Generate tar header for this directory
251 // Filename, Permissions, UID, GID, size, Time, checksum, typeflag, linkname, magic, version, user name, group name, devmajor, devminor, prefix, end
252 $header .= str_pad($information['name'], 100, chr(0));
253 $header .= str_pad(decoct($information['mode']), 7, '0', STR_PAD_LEFT) . chr(0);
254 $header .= str_pad(decoct($information['user_id']), 7, '0', STR_PAD_LEFT) . chr(0);
255 $header .= str_pad(decoct($information['group_id']), 7, '0', STR_PAD_LEFT) . chr(0);
256 $header .= str_pad(decoct(0), 11, '0', STR_PAD_LEFT) . chr(0);
257 $header .= str_pad(decoct($information['time']), 11, '0', STR_PAD_LEFT) . chr(0);
258 $header .= str_repeat(' ', 8);
259 $header .= '5';
260 $header .= str_repeat(chr(0), 100);
261 $header .= str_pad('ustar', 6, chr(32));
262 $header .= chr(32) . chr(0);
263 $header .= str_pad('', 32, chr(0));
264 $header .= str_pad('', 32, chr(0));
265 $header .= str_repeat(chr(0), 8);
266 $header .= str_repeat(chr(0), 8);
267 $header .= str_repeat(chr(0), 155);
268 $header .= str_repeat(chr(0), 12);
269
270 // Compute header checksum
271 $checksum = str_pad(decoct($this->__computeUnsignedChecksum($header)), 6, '0', STR_PAD_LEFT);
272 for ($i=0; $i<6; $i++) {
273 $header[(148 + $i)] = substr($checksum, $i, 1);
274 }
275 $header[154] = chr(0);
276 $header[155] = chr(32);
277
278 // Add new tar formatted data to tar file contents
279 $this->tar_file .= $header;
280 }
281 }
282
283 // Generate Records for each file, if we have files (We should...)
284 if ($this->numFiles > 0) {
285 $this->tar_file = '';
286 foreach ($this->files as $key => $information) {
287 unset($header);
288
289 // Generate the TAR header for this file
290 // Filename, Permissions, UID, GID, size, Time, checksum, typeflag, linkname, magic, version, user name, group name, devmajor, devminor, prefix, end
291 $header = str_pad($information['name'], 100, chr(0));
292 $header .= str_pad(decoct($information['mode']), 7, '0', STR_PAD_LEFT) . chr(0);
293 $header .= str_pad(decoct($information['user_id']), 7, '0', STR_PAD_LEFT) . chr(0);
294 $header .= str_pad(decoct($information['group_id']), 7, '0', STR_PAD_LEFT) . chr(0);
295 $header .= str_pad(decoct($information['size']), 11, '0', STR_PAD_LEFT) . chr(0);
296 $header .= str_pad(decoct($information['time']), 11, '0', STR_PAD_LEFT) . chr(0);
297 $header .= str_repeat(' ', 8);
298 $header .= '0';
299 $header .= str_repeat(chr(0), 100);
300 $header .= str_pad('ustar', 6, chr(32));
301 $header .= chr(32) . chr(0);
302 $header .= str_pad($information['user_name'], 32, chr(0)); // How do I get a file's user name from PHP?
303 $header .= str_pad($information['group_name'], 32, chr(0)); // How do I get a file's group name from PHP?
304 $header .= str_repeat(chr(0), 8);
305 $header .= str_repeat(chr(0), 8);
306 $header .= str_repeat(chr(0), 155);
307 $header .= str_repeat(chr(0), 12);
308
309 // Compute header checksum
310 $checksum = str_pad(decoct($this->__computeUnsignedChecksum($header)), 6, '0', STR_PAD_LEFT);
311 for ($i=0; $i<6; $i++) {
312 $header[(148 + $i)] = substr($checksum, $i, 1);
313 }
314 $header[154] = chr(0);
315 $header[155] = chr(32);
316
317 // Pad file contents to byte count divisible by 512
318 $file_contents = str_pad($information['file'], (ceil($information['size'] / 512) * 512), chr(0));
319
320 // Add new tar formatted data to tar file contents
321 $this->tar_file .= $header . $file_contents;
322 }
323 }
324
325 // Add 512 bytes of NULLs to designate EOF
326 $this->tar_file .= str_repeat(chr(0), 512);
327
328 return true;
329 }
330
331
338 public function openTAR($filename)
339 {
340 // Clear any values from previous tar archives
341 unset($this->filename);
342 unset($this->isGzipped);
343 unset($this->tar_file);
344 unset($this->files);
345 unset($this->directories);
346 unset($this->numFiles);
347 unset($this->numDirectories);
348
349 // If the tar file doesn't exist...
350 if (!file_exists($filename)) {
351 return false;
352 }
353
354 $this->filename = $filename;
355
356 // Parse this file
357 $this->__readTar();
358
359 return true;
360 }
361
368 public function appendTar($filename)
369 {
370 // If the tar file doesn't exist...
371 if (!file_exists($filename)) {
372 return false;
373 }
374
375 $this->__readTar($filename);
376
377 return true;
378 }
379
386 public function getFile($filename)
387 {
388 if ($this->numFiles > 0) {
389 foreach ($this->files as $key => $information) {
390 if ($information['name'] == $filename) {
391 return $information;
392 }
393 }
394 }
395
396 return false;
397 }
398
405 public function getDirectory($dirname)
406 {
407 if ($this->numDirectories > 0) {
408 foreach ($this->directories as $key => $information) {
409 if ($information['name'] == $dirname) {
410 return $information;
411 }
412 }
413 }
414
415 return false;
416 }
417
424 public function containsFile($filename)
425 {
426 if ($this->numFiles > 0) {
427 foreach ($this->files as $key => $information) {
428 if ($information['name'] == $filename) {
429 return true;
430 }
431 }
432 }
433 return false;
434 }
435
442 public function containsDirectory($dirname)
443 {
444 if ($this->numDirectories > 0) {
445 foreach ($this->directories as $key => $information) {
446 if ($information['name'] == $dirname) {
447 return true;
448 }
449 }
450 }
451 return false;
452 }
453
460 public function addDirectory($dirname)
461 {
462 if (!file_exists($dirname)) {
463 return false;
464 }
465
466 // Get directory information
467 $file_information = stat($dirname);
468
469 // Add directory to processed data
470 $this->numDirectories++;
471 $activeDir = &$this->directories[];
472 $activeDir['name'] = $dirname;
473 $activeDir['mode'] = $file_information['mode'];
474 $activeDir['time'] = $file_information['time'];
475 $activeDir['user_id'] = $file_information['uid'];
476 $activeDir['group_id'] = $file_information['gid'];
477 $activeDir['checksum'] = $checksum;
478
479 return true;
480 }
481
489 public function addFile($filename, $binary = false)
490 {
491 // Make sure the file we are adding exists!
492 if (!file_exists($filename)) {
493 return false;
494 }
495
496 // Make sure there are no other files in the archive that have this same filename
497 if ($this->containsFile($filename)) {
498 return false;
499 }
500
501 // Get file information
502 $file_information = stat($filename);
503
504 // Read in the file's contents
505 if (!$binary) {
506 $fp = fopen($filename, 'r');
507 } else {
508 $fp = fopen($filename, 'rb');
509 }
510 $file_contents = filesize($filename) ? fread($fp, filesize($filename)) : '' ;
511 fclose($fp);
512
513 // Add file to processed data
514 $this->numFiles++;
515 $activeFile = &$this->files[];
516 $activeFile['name'] = $filename;
517 $activeFile['mode'] = $file_information['mode'];
518 $activeFile['user_id'] = $file_information['uid'];
519 $activeFile['group_id'] = $file_information['gid'];
520 $activeFile['size'] = $file_information['size'];
521 $activeFile['time'] = $file_information['mtime'];
522 $activeFile['checksum'] = isset($checksum) ? $checksum : '';
523 $activeFile['user_name'] = '';
524 $activeFile['group_name'] = '';
525 // "trim" May be needless. by nao-pon
526 //$activeFile["file"] = trim($file_contents);
527 $activeFile['file'] = $file_contents;
528
529 return true;
530 }
531
538 public function removeFile($filename)
539 {
540 if ($this->numFiles > 0) {
541 foreach ($this->files as $key => $information) {
542 if ($information['name'] == $filename) {
543 $this->numFiles--;
544 unset($this->files[$key]);
545 return true;
546 }
547 }
548 }
549 return false;
550 }
551
558 public function removeDirectory($dirname)
559 {
560 if ($this->numDirectories > 0) {
561 foreach ($this->directories as $key => $information) {
562 if ($information['name'] == $dirname) {
563 $this->numDirectories--;
564 unset($this->directories[$key]);
565 return true;
566 }
567 }
568 }
569 return false;
570 }
571
577 public function saveTar()
578 {
579 if (!$this->filename) {
580 return false;
581 }
582
583 // Write tar to current file using specified gzip compression
584 $this->toTar($this->filename, $this->isGzipped);
585
586 return true;
587 }
588
596 public function toTar($filename, $useGzip)
597 {
598 if (!$filename) {
599 return false;
600 }
601
602 // Encode processed files into TAR file format
603 $this->__generateTar();
604
605 // GZ Compress the data if we need to
606 if ($useGzip) {
607 // Make sure we have gzip support
608 if (!function_exists('gzencode')) {
609 return false;
610 }
611
612 $file = gzencode($this->tar_file);
613 } else {
614 $file = $this->tar_file;
615 }
616
617 // Write the TAR file
618 $fp = fopen($filename, 'wb');
619 fwrite($fp, $file);
620 fclose($fp);
621
622 return true;
623 }
624
632 public function toTarOutput($filename, $useGzip)
633 {
634 if (!$filename) {
635 return false;
636 }
637
638 // Encode processed files into TAR file format
639 $this->__generateTar();
640
641 // GZ Compress the data if we need to
642 if ($useGzip) {
643 // Make sure we have gzip support
644 if (!function_exists('gzencode')) {
645 return false;
646 }
647
648 $file = gzencode($this->tar_file);
649 } else {
650 $file = $this->tar_file;
651 }
652
653 return $file;
654 }
655}
__parseNullPaddedString($string)
Definition class.tar.php:83
$filename
Definition class.tar.php:28
__construct()
Definition class.tar.php:45
addFile($filename, $binary=false)
toTarOutput($filename, $useGzip)
getDirectory($dirname)
__generateTAR()
saveTar()
removeFile($filename)
__parseTar()
Definition class.tar.php:96
addDirectory($dirname)
__computeUnsignedChecksum($bytestring)
Definition class.tar.php:59
openTAR($filename)
containsFile($filename)
__readTar($filename='')
appendTar($filename)
getFile($filename)
containsDirectory($dirname)
toTar($filename, $useGzip)
removeDirectory($dirname)