XOOPS 2.5.6  Final
 All Classes Namespaces Files Functions Variables Pages
class.tar.php
Go to the documentation of this file.
1 <?php
2 // $Id: class.tar.php 8066 2011-11-06 05:09:33Z beckmi $
3 
93 class tar
94 {
99  var $filename;
110  var $files;
121  function tar()
122  {
123  return true;
124  }
125 
133  function __computeUnsignedChecksum($bytestring)
134  {
135  $unsigned_chksum = '';
136  for ($i = 0; $i < 512; $i++) {
137  $unsigned_chksum += ord($bytestring[$i]);
138  }
139  for ($i = 0; $i < 8; $i++) {
140  $unsigned_chksum -= ord($bytestring[148 + $i]);
141  $unsigned_chksum += ord(' ') * 8;
142  }
143  return $unsigned_chksum;
144  }
145 
153  function __parseNullPaddedString($string)
154  {
155  $position = strpos($string, chr(0));
156  return substr($string, 0, $position);
157  }
158 
165  function __parseTar()
166  {
167  // Read Files from archive
168  $tar_length = strlen($this->tar_file);
169  $main_offset = 0;
170  $this->numFiles = 0;
171  while ($main_offset < $tar_length) {
172  // If we read a block of 512 nulls, we are at the end of the archive
173  if (substr($this->tar_file, $main_offset, 512) == str_repeat(chr(0), 512))
174  break;
175  // Parse file name
176  $file_name = $this->__parseNullPaddedString(substr($this->tar_file, $main_offset, 100));
177  // Parse the file mode
178  $file_mode = substr($this->tar_file, $main_offset + 100, 8);
179  // Parse the file user ID
180  $file_uid = octdec(substr($this->tar_file, $main_offset + 108, 8));
181  // Parse the file group ID
182  $file_gid = octdec(substr($this->tar_file, $main_offset + 116, 8));
183  // Parse the file size
184  $file_size = octdec(substr($this->tar_file, $main_offset + 124, 12));
185  // Parse the file update time - unix timestamp format
186  $file_time = octdec(substr($this->tar_file, $main_offset + 136, 12));
187  // Parse Checksum
188  $file_chksum = octdec(substr($this->tar_file, $main_offset + 148, 6));
189  // Parse user name
190  $file_uname = $this->__parseNullPaddedString(substr($this->tar_file, $main_offset + 265, 32));
191  // Parse Group name
192  $file_gname = $this->__parseNullPaddedString(substr($this->tar_file, $main_offset + 297, 32));
193  // Make sure our file is valid
194  if ($this->__computeUnsignedChecksum(substr($this->tar_file, $main_offset, 512)) != $file_chksum)
195  return false;
196  // Parse File Contents
197  $file_contents = substr($this->tar_file, $main_offset + 512, $file_size);
198 
211  if ($file_size > 0) {
212  // Increment number of files
213  $this->numFiles++;
214  // Create us a new file in our array
215  $activeFile =& $this->files[];
216  // Asign Values
217  $activeFile["name"] = $file_name;
218  $activeFile["mode"] = $file_mode;
219  $activeFile["size"] = $file_size;
220  $activeFile["time"] = $file_time;
221  $activeFile["user_id"] = $file_uid;
222  $activeFile["group_id"] = $file_gid;
223  $activeFile["user_name"] = $file_uname;
224  $activeFile["group_name"] = $file_gname;
225  $activeFile["checksum"] = $file_chksum;
226  $activeFile["file"] = $file_contents;
227  } else {
228  // Increment number of directories
229  $this->numDirectories ++;
230  // Create a new directory in our array
231  $activeDir =& $this->directories[];
232  // Assign values
233  $activeDir["name"] = $file_name;
234  $activeDir["mode"] = $file_mode;
235  $activeDir["time"] = $file_time;
236  $activeDir["user_id"] = $file_uid;
237  $activeDir["group_id"] = $file_gid;
238  $activeDir["user_name"] = $file_uname;
239  $activeDir["group_name"] = $file_gname;
240  $activeDir["checksum"] = $file_chksum;
241  }
242  // Move our offset the number of blocks we have processed
243  $main_offset += 512 + (ceil($file_size / 512) * 512);
244  }
245 
246  return true;
247  }
248 
256  function __readTar($filename = '')
257  {
258  // Set the filename to load
259  if (!$filename) {
261  }
262  // Read in the TAR file
263  $fp = fopen($filename, 'rb');
264  $this->tar_file = fread($fp, filesize($filename));
265  fclose($fp);
266 
267  if ($this->tar_file[0] == chr(31) && $this->tar_file[1] == chr(139) && $this->tar_file[2] == chr(8)) {
268  if (!function_exists('gzinflate')) {
269  return false;
270  }
271  $this->isGzipped = true;
272  $this->tar_file = gzinflate(substr($this->tar_file, 10, - 4));
273  }
274  // Parse the TAR file
275  $this->__parseTar();
276 
277  return true;
278  }
279 
286  function __generateTAR()
287  {
288  // Clear any data currently in $this->tar_file
289  unset($this->tar_file);
290  // Generate Records for each directory, if we have directories
291  if ($this->numDirectories > 0) {
292  foreach ($this->directories as $key => $information) {
293  unset($header);
294  // Generate tar header for this directory
295  // Filename, Permissions, UID, GID, size, Time, checksum, typeflag, linkname, magic, version, user name, group name, devmajor, devminor, prefix, end
296  $header .= str_pad($information["name"], 100, chr(0));
297  $header .= str_pad(decoct($information["mode"]), 7, "0", STR_PAD_LEFT) . chr(0);
298  $header .= str_pad(decoct($information["user_id"]), 7, "0", STR_PAD_LEFT) . chr(0);
299  $header .= str_pad(decoct($information["group_id"]), 7, "0", STR_PAD_LEFT) . chr(0);
300  $header .= str_pad(decoct(0), 11, "0", STR_PAD_LEFT) . chr(0);
301  $header .= str_pad(decoct($information["time"]), 11, "0", STR_PAD_LEFT) . chr(0);
302  $header .= str_repeat(" ", 8);
303  $header .= "5";
304  $header .= str_repeat(chr(0), 100);
305  $header .= str_pad("ustar", 6, chr(32));
306  $header .= chr(32) . chr(0);
307  $header .= str_pad("", 32, chr(0));
308  $header .= str_pad("", 32, chr(0));
309  $header .= str_repeat(chr(0), 8);
310  $header .= str_repeat(chr(0), 8);
311  $header .= str_repeat(chr(0), 155);
312  $header .= str_repeat(chr(0), 12);
313  // Compute header checksum
314  $checksum = str_pad(decoct($this->__computeUnsignedChecksum($header)), 6, "0", STR_PAD_LEFT);
315  for ($i = 0; $i < 6; $i ++) {
316  $header[(148 + $i)] = substr($checksum, $i, 1);
317  }
318  $header[154] = chr(0);
319  $header[155] = chr(32);
320  // Add new tar formatted data to tar file contents
321  $this->tar_file .= $header;
322  }
323  }
324  // Generate Records for each file, if we have files (We should...)
325  if ($this->numFiles > 0) {
326  $this->tar_file = '';
327  foreach($this->files as $key => $information) {
328  unset($header);
329  // Generate the TAR header for this file
330  // Filename, Permissions, UID, GID, size, Time, checksum, typeflag, linkname, magic, version, user name, group name, devmajor, devminor, prefix, end
331  $header = str_pad($information["name"], 100, chr(0));
332  $header .= str_pad(decoct($information["mode"]), 7, "0", STR_PAD_LEFT) . chr(0);
333  $header .= str_pad(decoct($information["user_id"]), 7, "0", STR_PAD_LEFT) . chr(0);
334  $header .= str_pad(decoct($information["group_id"]), 7, "0", STR_PAD_LEFT) . chr(0);
335  $header .= str_pad(decoct($information["size"]), 11, "0", STR_PAD_LEFT) . chr(0);
336  $header .= str_pad(decoct($information["time"]), 11, "0", STR_PAD_LEFT) . chr(0);
337  $header .= str_repeat(" ", 8);
338  $header .= "0";
339  $header .= str_repeat(chr(0), 100);
340  $header .= str_pad("ustar", 6, chr(32));
341  $header .= chr(32) . chr(0);
342  $header .= str_pad($information["user_name"], 32, chr(0)); // How do I get a file's user name from PHP?
343  $header .= str_pad($information["group_name"], 32, chr(0)); // How do I get a file's group name from PHP?
344  $header .= str_repeat(chr(0), 8);
345  $header .= str_repeat(chr(0), 8);
346  $header .= str_repeat(chr(0), 155);
347  $header .= str_repeat(chr(0), 12);
348  // Compute header checksum
349  $checksum = str_pad(decoct($this->__computeUnsignedChecksum($header)), 6, "0", STR_PAD_LEFT);
350  for ($i = 0; $i < 6; $i++) {
351  $header[(148 + $i)] = substr($checksum, $i, 1);
352  }
353  $header[154] = chr(0);
354  $header[155] = chr(32);
355  // Pad file contents to byte count divisible by 512
356  $file_contents = str_pad($information["file"], (ceil($information["size"] / 512) * 512), chr(0));
357  // Add new tar formatted data to tar file contents
358  $this->tar_file .= $header . $file_contents;
359  }
360  }
361  // Add 512 bytes of NULLs to designate EOF
362  $this->tar_file .= str_repeat(chr(0), 512);
363  return true;
364  }
365 
372  function openTAR($filename)
373  {
374  // Clear any values from previous tar archives
375  unset($this->filename);
376  unset($this->isGzipped);
377  unset($this->tar_file);
378  unset($this->files);
379  unset($this->directories);
380  unset($this->numFiles);
381  unset($this->numDirectories);
382  // If the tar file doesn't exist...
383  if (!file_exists($filename))
384  return false;
385 
386  $this->filename = $filename;
387  // Parse this file
388  $this->__readTar();
389  return true;
390  }
391 
399  {
400  // If the tar file doesn't exist...
401  if (!file_exists($filename)) {
402  return false;
403  }
404  $this->__readTar($filename);
405  return true;
406  }
407 
414  function getFile($filename)
415  {
416  if ($this->numFiles > 0) {
417  foreach ($this->files as $key => $information) {
418  if ($information['name'] == $filename) {
419  return $information;
420  }
421  }
422  }
423  return false;
424  }
425 
433  {
434  if ($this->numDirectories > 0) {
435  foreach ($this->directories as $key => $information) {
436  if ($information['name'] == $dirname) {
437  return $information;
438  }
439  }
440  }
441  return false;
442  }
443 
451  {
452  if ($this->numFiles > 0) {
453  foreach ($this->files as $key => $information) {
454  if ($information['name'] == $filename) {
455  return true;
456  }
457  }
458  }
459  return false;
460  }
461 
469  {
470  if ($this->numDirectories > 0) {
471  foreach ($this->directories as $key => $information) {
472  if ($information['name'] == $dirname) {
473  return true;
474  }
475  }
476  }
477  return false;
478  }
479 
487  {
488  if (! file_exists($dirname)) {
489  return false;
490  }
491  // Get directory information
492  $file_information = stat($dirname);
493  // Add directory to processed data
494  $this->numDirectories++;
495  $activeDir =& $this->directories[];
496  $activeDir['name'] = $dirname;
497  $activeDir['mode'] = $file_information['mode'];
498  $activeDir['time'] = $file_information['time'];
499  $activeDir['user_id'] = $file_information['uid'];
500  $activeDir['group_id'] = $file_information['gid'];
501  $activeDir['checksum'] = $checksum;
502 
503  return true;
504  }
505 
513  function addFile($filename, $binary = false)
514  {
515  // Make sure the file we are adding exists!
516  if (!file_exists($filename)) {
517  return false;
518  }
519  // Make sure there are no other files in the archive that have this same filename
520  if ($this->containsFile($filename)) {
521  return false;
522  }
523  // Get file information
524  $file_information = stat($filename);
525  // Read in the file's contents
526  if (!$binary) {
527  $fp = fopen($filename, 'r');
528  } else {
529  $fp = fopen($filename, 'rb');
530  }
531  $file_contents = fread($fp, filesize($filename));
532  fclose($fp);
533  // Add file to processed data
534  $this->numFiles++;
535  $activeFile =& $this->files[];
536  $activeFile['name'] = $filename;
537  $activeFile['mode'] = $file_information['mode'];
538  $activeFile['user_id'] = $file_information['uid'];
539  $activeFile['group_id'] = $file_information['gid'];
540  $activeFile['size'] = $file_information['size'];
541  $activeFile['time'] = $file_information['mtime'];
542  $activeFile['checksum'] = isset($checksum) ? $checksum : '';
543  $activeFile['user_name'] = '';
544  $activeFile['group_name'] = '';
545  $activeFile['file'] = trim($file_contents);
546  return true;
547  }
548 
556  {
557  if ($this->numFiles > 0) {
558  foreach ($this->files as $key => $information) {
559  if ($information['name'] == $filename) {
560  $this->numFiles--;
561  unset($this->files[$key]);
562  return true;
563  }
564  }
565  }
566  return false;
567  }
568 
576  {
577  if ($this->numDirectories > 0) {
578  foreach ($this->directories as $key => $information) {
579  if ($information['name'] == $dirname) {
580  $this->numDirectories--;
581  unset($this->directories[$key]);
582  return true;
583  }
584  }
585  }
586  return false;
587  }
588 
594  function saveTar()
595  {
596  if (!$this->filename) {
597  return false;
598  }
599  // Write tar to current file using specified gzip compression
600  $this->toTar($this->filename, $this->isGzipped);
601  return true;
602  }
603 
611  function toTar($filename, $useGzip)
612  {
613  if (!$filename) {
614  return false;
615  }
616  // Encode processed files into TAR file format
617  $this->__generateTar();
618  // GZ Compress the data if we need to
619  if ($useGzip) {
620  // Make sure we have gzip support
621  if (!function_exists('gzencode')) {
622  return false;
623  }
624  $file = gzencode($this->tar_file);
625  } else {
627  }
628  // Write the TAR file
629  $fp = fopen($filename, 'wb');
630  fwrite($fp, $file);
631  fclose($fp);
632  return true;
633  }
634 
642  function toTarOutput($filename, $useGzip)
643  {
644  if (!$filename) {
645  return false;
646  }
647  // Encode processed files into TAR file format
648  $this->__generateTar();
649  // GZ Compress the data if we need to
650  if ($useGzip) {
651  // Make sure we have gzip support
652  if (!function_exists('gzencode')) {
653  return false;
654  }
655  $file = gzencode($this->tar_file);
656  } else {
658  }
659  return $file;
660  }
661 }
662 
663 ?>