1*a33f8e80Stracker-user<?php 2*a33f8e80Stracker-user 3*a33f8e80Stracker-usernamespace dokuwiki\plugin\sitebackup; 4*a33f8e80Stracker-user 5*a33f8e80Stracker-useruse splitbrain\PHPArchive\Tar as UpstreamTar; 6*a33f8e80Stracker-user 7*a33f8e80Stracker-user/** 8*a33f8e80Stracker-user * Tar with the upstream mtime bug patched. 9*a33f8e80Stracker-user * 10*a33f8e80Stracker-user * DokuWiki 2025-05-14b "Librarian" ships an old version of 11*a33f8e80Stracker-user * splitbrain/php-archive whose Tar::writeRawFileHeader() contains: 12*a33f8e80Stracker-user * $size = self::numberEncode($size, 12); 13*a33f8e80Stracker-user * $mtime = self::numberEncode($size, 12); // <-- $size, not $mtime 14*a33f8e80Stracker-user * So every file's mtime field ends up holding its size, octal-encoded. GNU tar 15*a33f8e80Stracker-user * dutifully reads the value as a Unix timestamp and shows 1970-01-01 with a 16*a33f8e80Stracker-user * size-derived seconds offset. 17*a33f8e80Stracker-user * 18*a33f8e80Stracker-user * Fixed upstream in splitbrain/php-archive PR #38. This subclass copies the 19*a33f8e80Stracker-user * method verbatim and corrects the one line so existing DokuWiki installs 20*a33f8e80Stracker-user * don't have to wait for the vendored library to be bumped. 21*a33f8e80Stracker-user */ 22*a33f8e80Stracker-userclass PatchedTar extends UpstreamTar 23*a33f8e80Stracker-user{ 24*a33f8e80Stracker-user /** 25*a33f8e80Stracker-user * @inheritdoc 26*a33f8e80Stracker-user */ 27*a33f8e80Stracker-user protected function writeRawFileHeader($name, $uid, $gid, $perm, $size, $mtime, $typeflag = '') 28*a33f8e80Stracker-user { 29*a33f8e80Stracker-user // handle filename length restrictions 30*a33f8e80Stracker-user $prefix = ''; 31*a33f8e80Stracker-user $namelen = strlen($name); 32*a33f8e80Stracker-user if ($namelen > 100) { 33*a33f8e80Stracker-user $file = basename($name); 34*a33f8e80Stracker-user $dir = dirname($name); 35*a33f8e80Stracker-user if (strlen($file) > 100 || strlen($dir) > 155) { 36*a33f8e80Stracker-user // we're still too large, let's use GNU longlink 37*a33f8e80Stracker-user $this->writeRawFileHeader('././@LongLink', 0, 0, 0, $namelen, 0, 'L'); 38*a33f8e80Stracker-user for ($s = 0; $s < $namelen; $s += 512) { 39*a33f8e80Stracker-user $this->writebytes(pack("a512", substr($name, $s, 512))); 40*a33f8e80Stracker-user } 41*a33f8e80Stracker-user $name = substr($name, 0, 100); // cut off name 42*a33f8e80Stracker-user } else { 43*a33f8e80Stracker-user // we're fine when splitting, use POSIX ustar 44*a33f8e80Stracker-user $prefix = $dir; 45*a33f8e80Stracker-user $name = $file; 46*a33f8e80Stracker-user } 47*a33f8e80Stracker-user } 48*a33f8e80Stracker-user 49*a33f8e80Stracker-user // values are needed in octal 50*a33f8e80Stracker-user $uid = sprintf("%6s ", decoct($uid)); 51*a33f8e80Stracker-user $gid = sprintf("%6s ", decoct($gid)); 52*a33f8e80Stracker-user $perm = sprintf("%6s ", decoct($perm)); 53*a33f8e80Stracker-user $size = self::numberEncode($size, 12); 54*a33f8e80Stracker-user $mtime = self::numberEncode($mtime, 12); // patched: was numberEncode($size, 12) 55*a33f8e80Stracker-user 56*a33f8e80Stracker-user $data_first = pack("a100a8a8a8a12A12", $name, $perm, $uid, $gid, $size, $mtime); 57*a33f8e80Stracker-user $data_last = pack("a1a100a6a2a32a32a8a8a155a12", $typeflag, '', 'ustar', '', '', '', '', '', $prefix, ""); 58*a33f8e80Stracker-user 59*a33f8e80Stracker-user for ($i = 0, $chks = 0; $i < 148; $i++) { 60*a33f8e80Stracker-user $chks += ord($data_first[$i]); 61*a33f8e80Stracker-user } 62*a33f8e80Stracker-user 63*a33f8e80Stracker-user for ($i = 156, $chks += 256, $j = 0; $i < 512; $i++, $j++) { 64*a33f8e80Stracker-user $chks += ord($data_last[$j]); 65*a33f8e80Stracker-user } 66*a33f8e80Stracker-user 67*a33f8e80Stracker-user $this->writebytes($data_first); 68*a33f8e80Stracker-user 69*a33f8e80Stracker-user $chks = pack("a8", sprintf("%6s ", decoct($chks))); 70*a33f8e80Stracker-user $this->writebytes($chks.$data_last); 71*a33f8e80Stracker-user } 72*a33f8e80Stracker-user} 73