XOOPS  2.6.0
class.tar.php
Go to the documentation of this file.
1 <?php
2 // $Id$
3 
91 class tar
92 {
97  public $filename;
98  public $isGzipped;
99  public $tar_file;
108  public $files;
109  public $directories;
110  public $numFiles;
112 
125  private function __computeUnsignedChecksum($bytestring)
126  {
127  $unsigned_chksum = '';
128  for ($i = 0; $i < 512; ++$i) {
129  $unsigned_chksum += ord($bytestring[$i]);
130  }
131  for ($i = 0; $i < 8; ++$i) {
132  $unsigned_chksum -= ord($bytestring[148 + $i]);
133  $unsigned_chksum += ord(' ') * 8;
134  }
135  return $unsigned_chksum;
136  }
137 
145  private function __parseNullPaddedString($string)
146  {
147  $position = strpos($string, chr(0));
148  return substr($string, 0, $position);
149  }
150 
157  private function __parseTar()
158  {
159  // Read Files from archive
160  $tar_length = strlen($this->tar_file);
161  $main_offset = 0;
162  $this->numFiles = 0;
163  while ($main_offset < $tar_length) {
164  // If we read a block of 512 nulls, we are at the end of the archive
165  if (substr($this->tar_file, $main_offset, 512) == str_repeat(chr(0), 512)) {
166  break;
167  }
168  // Parse file name
169  $file_name = $this->__parseNullPaddedString(substr($this->tar_file, $main_offset, 100));
170  // Parse the file mode
171  $file_mode = substr($this->tar_file, $main_offset + 100, 8);
172  // Parse the file user ID
173  $file_uid = octdec(substr($this->tar_file, $main_offset + 108, 8));
174  // Parse the file group ID
175  $file_gid = octdec(substr($this->tar_file, $main_offset + 116, 8));
176  // Parse the file size
177  $file_size = octdec(substr($this->tar_file, $main_offset + 124, 12));
178  // Parse the file update time - unix timestamp format
179  $file_time = octdec(substr($this->tar_file, $main_offset + 136, 12));
180  // Parse Checksum
181  $file_chksum = octdec(substr($this->tar_file, $main_offset + 148, 6));
182  // Parse user name
183  $file_uname = $this->__parseNullPaddedString(substr($this->tar_file, $main_offset + 265, 32));
184  // Parse Group name
185  $file_gname = $this->__parseNullPaddedString(substr($this->tar_file, $main_offset + 297, 32));
186  // Make sure our file is valid
187  if ($this->__computeUnsignedChecksum(substr($this->tar_file, $main_offset, 512)) != $file_chksum) {
188  return false;
189  }
190  // Parse File Contents
191  $file_contents = substr($this->tar_file, $main_offset + 512, $file_size);
192 
205  if ($file_size > 0) {
206  // Increment number of files
207  $this->numFiles++;
208  // Create us a new file in our array
209  $activeFile =& $this->files[];
210  // Asign Values
211  $activeFile["name"] = $file_name;
212  $activeFile["mode"] = $file_mode;
213  $activeFile["size"] = $file_size;
214  $activeFile["time"] = $file_time;
215  $activeFile["user_id"] = $file_uid;
216  $activeFile["group_id"] = $file_gid;
217  $activeFile["user_name"] = $file_uname;
218  $activeFile["group_name"] = $file_gname;
219  $activeFile["checksum"] = $file_chksum;
220  $activeFile["file"] = $file_contents;
221  } else {
222  // Increment number of directories
223  $this->numDirectories++;
224  // Create a new directory in our array
225  $activeDir =& $this->directories[];
226  // Assign values
227  $activeDir["name"] = $file_name;
228  $activeDir["mode"] = $file_mode;
229  $activeDir["time"] = $file_time;
230  $activeDir["user_id"] = $file_uid;
231  $activeDir["group_id"] = $file_gid;
232  $activeDir["user_name"] = $file_uname;
233  $activeDir["group_name"] = $file_gname;
234  $activeDir["checksum"] = $file_chksum;
235  }
236  // Move our offset the number of blocks we have processed
237  $main_offset += 512 + (ceil($file_size / 512) * 512);
238  }
239 
240  return true;
241  }
242 
250  private function __readTar($filename = '')
251  {
252  // Set the filename to load
253  if (!$filename) {
255  }
256  // Read in the TAR file
257  $fp = fopen($filename, 'rb');
258  $this->tar_file = fread($fp, filesize($filename));
259  fclose($fp);
260 
261  if ($this->tar_file[0] == chr(31) && $this->tar_file[1] == chr(139) && $this->tar_file[2] == chr(8)) {
262  if (!function_exists('gzinflate')) {
263  return false;
264  }
265  $this->isGzipped = true;
266  $this->tar_file = gzinflate(substr($this->tar_file, 10, -4));
267  }
268  // Parse the TAR file
269  $this->__parseTar();
270 
271  return true;
272  }
273 
280  private function __generateTAR()
281  {
282  // Clear any data currently in $this->tar_file
283  unset($this->tar_file);
284  // Generate Records for each directory, if we have directories
285  if ($this->numDirectories > 0) {
286  foreach ($this->directories as $key => $information) {
287  $header = '';
288  // Generate tar header for this directory
289  // Filename, Permissions, UID, GID, size, Time, checksum, typeflag, linkname, magic, version, user name, group name, devmajor, devminor, prefix, end
290  $header .= str_pad($information["name"], 100, chr(0));
291  $header .= str_pad(decoct($information["mode"]), 7, "0", STR_PAD_LEFT) . chr(0);
292  $header .= str_pad(decoct($information["user_id"]), 7, "0", STR_PAD_LEFT) . chr(0);
293  $header .= str_pad(decoct($information["group_id"]), 7, "0", STR_PAD_LEFT) . chr(0);
294  $header .= str_pad(decoct(0), 11, "0", STR_PAD_LEFT) . chr(0);
295  $header .= str_pad(decoct($information["time"]), 11, "0", STR_PAD_LEFT) . chr(0);
296  $header .= str_repeat(" ", 8);
297  $header .= "5";
298  $header .= str_repeat(chr(0), 100);
299  $header .= str_pad("ustar", 6, chr(32));
300  $header .= chr(32) . chr(0);
301  $header .= str_pad("", 32, chr(0));
302  $header .= str_pad("", 32, chr(0));
303  $header .= str_repeat(chr(0), 8);
304  $header .= str_repeat(chr(0), 8);
305  $header .= str_repeat(chr(0), 155);
306  $header .= str_repeat(chr(0), 12);
307  // Compute header checksum
308  $checksum = str_pad(decoct($this->__computeUnsignedChecksum($header)), 6, "0", STR_PAD_LEFT);
309  for ($i = 0; $i < 6; ++$i) {
310  $header[(148 + $i)] = substr($checksum, $i, 1);
311  }
312  $header[154] = chr(0);
313  $header[155] = chr(32);
314  // Add new tar formatted data to tar file contents
315  $this->tar_file .= $header;
316  }
317  }
318  // Generate Records for each file, if we have files (We should...)
319  if ($this->numFiles > 0) {
320  $this->tar_file = '';
321  foreach ($this->files as $key => $information) {
322  $header = '';
323  // Generate the TAR header for this file
324  // Filename, Permissions, UID, GID, size, Time, checksum, typeflag, linkname, magic, version, user name, group name, devmajor, devminor, prefix, end
325  $header .= str_pad($information["name"], 100, chr(0));
326  $header .= str_pad(decoct($information["mode"]), 7, "0", STR_PAD_LEFT) . chr(0);
327  $header .= str_pad(decoct($information["user_id"]), 7, "0", STR_PAD_LEFT) . chr(0);
328  $header .= str_pad(decoct($information["group_id"]), 7, "0", STR_PAD_LEFT) . chr(0);
329  $header .= str_pad(decoct($information["size"]), 11, "0", STR_PAD_LEFT) . chr(0);
330  $header .= str_pad(decoct($information["time"]), 11, "0", STR_PAD_LEFT) . chr(0);
331  $header .= str_repeat(" ", 8);
332  $header .= "0";
333  $header .= str_repeat(chr(0), 100);
334  $header .= str_pad("ustar", 6, chr(32));
335  $header .= chr(32) . chr(0);
336  $header .= str_pad($information["user_name"], 32, chr(0)); // How do I get a file's user name from PHP?
337  $header .= str_pad($information["group_name"], 32, chr(0)); // How do I get a file's group name from PHP?
338  $header .= str_repeat(chr(0), 8);
339  $header .= str_repeat(chr(0), 8);
340  $header .= str_repeat(chr(0), 155);
341  $header .= str_repeat(chr(0), 12);
342  // Compute header checksum
343  $checksum = str_pad(decoct($this->__computeUnsignedChecksum($header)), 6, "0", STR_PAD_LEFT);
344  for ($i = 0; $i < 6; ++$i) {
345  $header[(148 + $i)] = substr($checksum, $i, 1);
346  }
347  $header[154] = chr(0);
348  $header[155] = chr(32);
349  // Pad file contents to byte count divisible by 512
350  $file_contents = str_pad($information["file"], (ceil($information["size"] / 512) * 512), chr(0));
351  // Add new tar formatted data to tar file contents
352  $this->tar_file .= $header . $file_contents;
353  }
354  }
355  // Add 512 bytes of NULLs to designate EOF
356  $this->tar_file .= str_repeat(chr(0), 512);
357  return true;
358  }
359 
366  public function openTAR($filename)
367  {
368  // Clear any values from previous tar archives
369  unset($this->filename);
370  unset($this->isGzipped);
371  unset($this->tar_file);
372  unset($this->files);
373  unset($this->directories);
374  unset($this->numFiles);
375  unset($this->numDirectories);
376  // If the tar file doesn't exist...
378  return false;
379  }
380 
381  $this->filename = $filename;
382  // Parse this file
383  $this->__readTar();
384  return true;
385  }
386 
393  public function appendTar($filename)
394  {
395  // If the tar file doesn't exist...
397  return false;
398  }
399  $this->__readTar($filename);
400  return true;
401  }
402 
409  public function getFile($filename)
410  {
411  if ($this->numFiles > 0) {
412  foreach ($this->files as $information) {
413  if ($information['name'] == $filename) {
414  return $information;
415  }
416  }
417  }
418  return false;
419  }
420 
427  public function getDirectory($dirname)
428  {
429  if ($this->numDirectories > 0) {
430  foreach ($this->directories as $information) {
431  if ($information['name'] == $dirname) {
432  return $information;
433  }
434  }
435  }
436  return false;
437  }
438 
445  public function containsFile($filename)
446  {
447  if ($this->numFiles > 0) {
448  foreach ($this->files as $information) {
449  if ($information['name'] == $filename) {
450  return true;
451  }
452  }
453  }
454  return false;
455  }
456 
463  public function containsDirectory($dirname)
464  {
465  if ($this->numDirectories > 0) {
466  foreach ($this->directories as $information) {
467  if ($information['name'] == $dirname) {
468  return true;
469  }
470  }
471  }
472  return false;
473  }
474 
481  public function addDirectory($dirname)
482  {
484  return false;
485  }
486  // Get directory information
487  $file_information = stat($dirname);
488  // Add directory to processed data
489  $this->numDirectories++;
490  $activeDir =& $this->directories[];
491  $activeDir['name'] = $dirname;
492  $activeDir['mode'] = $file_information['mode'];
493  $activeDir['time'] = $file_information['time'];
494  $activeDir['user_id'] = $file_information['uid'];
495  $activeDir['group_id'] = $file_information['gid'];
496  $activeDir['checksum'] = isset($checksum) ? $checksum : '';
497 
498  return true;
499  }
500 
508  public function addFile($filename, $binary = false)
509  {
510  // Make sure the file we are adding exists!
512  return false;
513  }
514  // Make sure there are no other files in the archive that have this same filename
515  if ($this->containsFile($filename)) {
516  return false;
517  }
518  // Get file information
519  $file_information = stat($filename);
520  // Read in the file's contents
521  if (!$binary) {
522  $fp = fopen($filename, 'r');
523  } else {
524  $fp = fopen($filename, 'rb');
525  }
526  $file_contents = fread($fp, filesize($filename));
527  fclose($fp);
528  // Add file to processed data
529  $this->numFiles++;
530  $activeFile =& $this->files[];
531  $activeFile['name'] = $filename;
532  $activeFile['mode'] = $file_information['mode'];
533  $activeFile['user_id'] = $file_information['uid'];
534  $activeFile['group_id'] = $file_information['gid'];
535  $activeFile['size'] = $file_information['size'];
536  $activeFile['time'] = $file_information['mtime'];
537  $activeFile['checksum'] = isset($checksum) ? $checksum : '';
538  $activeFile['user_name'] = '';
539  $activeFile['group_name'] = '';
540  $activeFile['file'] = trim($file_contents);
541  return true;
542  }
543 
550  public function removeFile($filename)
551  {
552  if ($this->numFiles > 0) {
553  foreach ($this->files as $key => $information) {
554  if ($information['name'] == $filename) {
555  $this->numFiles--;
556  unset($this->files[$key]);
557  return true;
558  }
559  }
560  }
561  return false;
562  }
563 
570  public function removeDirectory($dirname)
571  {
572  if ($this->numDirectories > 0) {
573  foreach ($this->directories as $key => $information) {
574  if ($information['name'] == $dirname) {
575  $this->numDirectories--;
576  unset($this->directories[$key]);
577  return true;
578  }
579  }
580  }
581  return false;
582  }
583 
589  public function saveTar()
590  {
591  if (!$this->filename) {
592  return false;
593  }
594  // Write tar to current file using specified gzip compression
595  $this->toTar($this->filename, $this->isGzipped);
596  return true;
597  }
598 
606  public function toTar($filename, $useGzip)
607  {
608  if (!$filename) {
609  return false;
610  }
611  // Encode processed files into TAR file format
612  $this->__generateTar();
613  // GZ Compress the data if we need to
614  if ($useGzip) {
615  // Make sure we have gzip support
616  if (!function_exists('gzencode')) {
617  return false;
618  }
619  $file = gzencode($this->tar_file);
620  } else {
622  }
623  // Write the TAR file
624  $fp = fopen($filename, 'wb');
625  fwrite($fp, $file);
626  fclose($fp);
627  return true;
628  }
629 
637  public function toTarOutput($filename, $useGzip)
638  {
639  if (!$filename) {
640  return false;
641  }
642  // Encode processed files into TAR file format
643  $this->__generateTar();
644  // GZ Compress the data if we need to
645  if ($useGzip) {
646  // Make sure we have gzip support
647  if (!function_exists('gzencode')) {
648  return false;
649  }
650  $file = gzencode($this->tar_file);
651  } else {
653  }
654  return $file;
655  }
656 }
$numFiles
Definition: class.tar.php:110
$i
Definition: dialog.php:68
__parseTar()
Definition: class.tar.php:157
__computeUnsignedChecksum($bytestring)
Definition: class.tar.php:125
if(!isset($xoops->paths[$path_type])) if($path_type== 'var') $file
Definition: browse.php:55
openTAR($filename)
Definition: class.tar.php:366
$filename
Definition: class.tar.php:97
$tar_file
Definition: class.tar.php:99
$isGzipped
Definition: class.tar.php:98
addFile($filename, $binary=false)
Definition: class.tar.php:508
$header
removeDirectory($dirname)
Definition: class.tar.php:570
static fileExists($file)
Definition: xoopsload.php:506
appendTar($filename)
Definition: class.tar.php:393
$numDirectories
Definition: class.tar.php:111
__generateTAR()
Definition: class.tar.php:280
toTarOutput($filename, $useGzip)
Definition: class.tar.php:637
$directories
Definition: class.tar.php:109
$files
Definition: class.tar.php:108
getDirectory($dirname)
Definition: class.tar.php:427
$dirname
Definition: backend.php:38
containsDirectory($dirname)
Definition: class.tar.php:463
__parseNullPaddedString($string)
Definition: class.tar.php:145
saveTar()
Definition: class.tar.php:589
getFile($filename)
Definition: class.tar.php:409
containsFile($filename)
Definition: class.tar.php:445
addDirectory($dirname)
Definition: class.tar.php:481
toTar($filename, $useGzip)
Definition: class.tar.php:606
removeFile($filename)
Definition: class.tar.php:550
__readTar($filename= '')
Definition: class.tar.php:250