0,0 → 1,574 |
<?php |
/************************* |
Coppermine Photo Gallery |
************************ |
Copyright (c) 2003-2005 Coppermine Dev Team |
v1.1 originaly written by Gregory DEMAR |
|
This program is free software; you can redistribute it and/or modify |
it under the terms of the GNU General Public License as published by |
the Free Software Foundation; either version 2 of the License, or |
(at your option) any later version. |
******************************************** |
Coppermine version: 1.3.3 |
$Source: /cvsroot/coppermine/stable/include/archive.php,v $ |
$Revision: 1.4 $ |
$Author: gaugau $ |
$Date: 2005/04/19 03:17:11 $ |
**********************************************/ |
|
/*-------------------------------------------------- |
| TAR/GZIP/ZIP ARCHIVE CLASSES |
| By Devin Doucette |
| Copyright (c) 2003 Devin Doucette |
| Email: darksnoopy@shaw.ca |
+-------------------------------------------------- |
| Email bugs/suggestions to darksnoopy@shaw.ca |
+-------------------------------------------------- |
| This script has been created and released under |
| the GNU GPL and is free to use and redistribute |
| only if this copyright statement is not removed |
+--------------------------------------------------*/ |
|
/*------------------------------------------------------------ |
| To create tar files: |
| $example = new tarfile($cwd,$flags); // args optional |
| -current working directory |
| -flags (array): |
| -overwrite - whether to overwrite existing files or return |
| an error message |
| -defaultperms - default file permissions (like chmod(), |
| must include 0 in front of value [eg. 0777, 0644]) |
| -recursesd[1,0] - whether or not to include subdirs |
| -storepath[1,0] - whether or not to store relative paths |
| -replacestats[array] - values to replace those from files |
| -mode - same as the result of a fileperms() call |
| -uid/gid - user/group id |
| -time - timestamp |
| -type - file type (5=dir,1=link,0=file) |
| -link - the file that is linked to |
| -path - only supported in USTAR, not recommended |
+------------------------------------------------------------*/ |
|
/*------------------------------------------------------------ |
| To create gzip files: |
| $example = new gzfile($cwd,$flags); // args optional |
| -current working directory |
| -flags (array): |
| -overwrite - whether to overwrite existing files or return |
| an error message |
| -defaultperms - default file permissions (like chmod(), |
| must include 0 in front of value [eg. 0777, 0644]) |
+------------------------------------------------------------*/ |
|
/*------------------------------------------------------------ |
| To create zip files: |
| $example = new zipfile($cwd,$flags); // args optional |
| -current working directory |
| -flags (array): |
| -overwrite - whether to overwrite existing files or return |
| an error message |
| -defaultperms - default file permissions (like chmod(), |
| must include 0 in front of value [eg. 0777, 0644]) |
| -time - timestamp to use to replace the mtime from files |
| -recursesd[1,0] - whether or not to include subdirs |
| -storepath[1,0] - whether or not to store relative paths |
| -level[0-9] - compression level (0 = none, 9 = max) |
| -comment - comment to add to the archive |
+------------------------------------------------------------*/ |
|
/*------------------------------------------------------------ |
| To add files: |
| $example->addfile($data,$filename,$flags); |
| -data - file contents |
| -filename - name of file to be put in archive |
| -flags (all flags are optional) |
| -flags (tar) [array]: -same flags as tarfile() |
| -flags (gzip) [string]: -comment to add to archive |
| -flags (zip) [array] -time - last modification time |
| |
| $example->addfiles($filelist); // tar and zip only |
| -filelist - array of file names relative to CWD |
| |
| $example->adddirectories($dirlist); // tar and zip only |
| -dirlist - array of directory names relative to CWD |
+------------------------------------------------------------*/ |
|
/*------------------------------------------------------------ |
| To output files: |
| $example->getdata(); |
| -returns file contents |
| |
| $example->filedownload($filename); |
| -filename - the name to give the file that is being sent |
| |
| $example->filewrite($filename,$perms); // perms optional |
| -filename - the name (including path) of the file to write |
| -perms - permissions to give the file after it is written |
+------------------------------------------------------------*/ |
|
/*------------------------------------------------------------ |
| To extract files (tar and gzip) |
| $example->extract($data); |
| -data - data to extract files from |
| -returns an array containing file attributes and contents |
| |
| $example->extractfile($filename); |
| -filename - the name (including path) of the file to use |
| -returns an array containing file attributes and contents |
| |
| Both functions will return a string containing any errors |
+------------------------------------------------------------*/ |
|
class tarfile extends archive { |
var $cwd = "./"; |
var $tardata = ""; |
var $defaultflags = array( |
'mode' => 0, |
'uid' => 0, |
'gid' => 0, |
'time' => 0, |
'type' => 0, |
'link' => "", |
'path' => "", |
); |
var $replacestats = array(); |
var $recursesd = 1; |
var $storepath = 1; |
|
function tarfile($cwd="./",$flags=array()) { |
$this->cwd = $cwd; |
$this->defaultflags['mode'] = decoct(0x8000 | 0x0100 | 0x0080 | 0x0020 | 0x0004); |
$this->defaultflags['time'] = time(); |
if(isset($flags['recursesd'])) |
$this->recursesd = $flags['recursesd']; |
if(isset($flags['storepath'])) |
$this->storepath = $flags['storepath']; |
if(isset($flags['replacestats'])) { |
if(is_array($flags['replacestats'])) { |
if(isset($flags['replacestats']['mode'])) |
$this->replacestats['mode'] = $flags['replacestats']['mode']; |
if(isset($flags['replacestats']['time'])) |
$this->replacestats['time'] = $flags['replacestats']['time']; |
} |
else if($flags['replacestats'] == 1) { |
$this->replacestats['mode'] = $this->defaultflags['mode']; |
$this->replacestats['time'] = $this->defaultflags['time']; |
} |
} |
|
$this->archive($flags); |
} |
|
function addfile($data,$filename,$flags=array()) { |
if(strlen($filename) > 99) |
return $this->error("The file name $filename is too long to archive."); |
|
$flags['mode'] = isset($this->replacestats['mode'])? $this->replacestats['mode'] : (isset($flags['mode'])? $flags['mode'] : $this->defaultflags['mode']); |
$flags['uid'] = isset($flags['uid'])? $flags['uid'] : $this->defaultflags['uid']; |
$flags['gid'] = isset($flags['gid'])? $flags['gid'] : $this->defaultflags['gid']; |
$flags['time'] = isset($this->replacestats['time'])? $this->replacestats['time'] : (isset($flags['time'])? $flags['time'] : $this->defaultflags['time']); |
$flags['type'] = isset($flags['type'])? $flags['type'] : $this->defaultflags['type']; |
$flags['link'] = isset($flags['link'])? $flags['link'] : $this->defaultflags['link']; |
$flags['path'] = isset($flags['path'])? $flags['path'] : $this->defaultflags['path']; |
$flags['size'] = isset($flags['size'])? $flags['size'] : strlen($data); |
|
if($this->storepath != 1) { |
$filename = strstr($filename,"/")? substr($filename,strrpos($filename,"/")+1) : $filename; |
$flags['path'] = ""; |
} |
else |
$filename = preg_replace("/^(\.{1,2}(\/|\\\))+/","",$filename); |
|
$blockbeg = pack("a100a8a8a8a12a12",$filename,$flags['mode'],sprintf("%6s ",decoct($flags['uid'])),sprintf("%6s ",decoct($flags['gid'])),sprintf("%11s ",decoct($flags['size'])),sprintf("%11s ",decoct($flags['time']))); |
$blockend = pack("a1a100a6a2a32a32a8a8a155",$flags['type'],$flags['link'],"ustar","00","Unknown","Unknown","","",$flags['path']); |
|
$checksum = 0; |
for($i = 0; $i < 148; $i++) |
$checksum += ord(substr($blockbeg,$i,1)); |
for($i = 148; $i < 156; $i++) |
$checksum += ord(" "); |
for($i = 156; $i < 512; $i++) |
$checksum += ord(substr($blockend,$i-156,1)); |
$checksum = pack("a8",sprintf("%6s ",decoct($checksum))); |
|
if($flags['size'] % 512 > 0) |
$data .= $this->nullpad(512 - $flags['size'] % 512); |
|
$this->tardata .= $blockbeg . $checksum . $blockend . pack("a12","") . $data; |
} |
|
function addfiles($filelist) { |
$pwd = getcwd(); |
@chdir($this->cwd); |
|
foreach($filelist as $current) { |
$file = array(); |
|
if($this->storepath != 1) |
$file['name'] = strstr($current,"/")? substr($current,strrpos($current,"/")+1) : $current; |
else |
$file['name'] = preg_replace("/^(\.{1,2}(\/|\\\))+/","",$current); |
|
$file['mode'] = @fileperms($current); |
if($file['mode'] & 0x4000) |
$file['type'] = 5; // Directory |
else if($file['mode'] & 0x8000) |
$file['type'] = 0; // Regular |
else if($file['mode'] & 0xA000) |
$file['type'] = 1; // Link |
else |
$file['type'] = 9; // Unknown |
$file['mode'] = decoct($file['mode']); |
|
if($file['type'] == 0 && !@file_exists($current)) |
return $this->error("$current does not exist"); |
else if(strlen($file['name']) > 99) { |
$offset = strrpos($file['name'],"/") + 1; |
$file['path'] = substr($file['name'],0,$offset); |
$file['name'] = substr($file['name'],$offset); |
if(strlen($file['name']) > 99 || strlen($file['path']) > 154) |
return $this->error("The file name {$file['name']} is too long to archive."); |
} |
else |
$file['path'] = ""; |
|
$stat = stat($current); |
|
if(($file['type'] == 0 || $file['type'] == 1) && $fp = @fopen($current,"rb")) { |
$data = fread($fp,$stat[7]); |
fclose($fp); |
} |
else |
$data = ""; |
|
$flags = array( |
'mode' => $file['mode'], |
'uid' => $stat[4], |
'gid' => $stat[5], |
'size' => $stat[7], |
'time' => $stat[9], |
'type' => $file['type'], |
'link' => $file['type'] == 1? @readlink($current) : "", |
'path' => $file['path'], |
); |
|
$this->addfile($data,$file['name'],$flags); |
} |
|
@chdir($pwd); |
} |
|
function extract($data) { |
$return = array(); |
$blocks = strlen($data)/512 - 1; |
$offset = 0; |
|
while($offset < $blocks) { |
$header = substr($data,512*$offset,512); |
$current = unpack("a100filename/a8mode/a8uid/a8gid/a12size/a12mtime/a8checksum/a1type/a100linkname/a6magic/a2version/a32uname/a32gname/a8devmajor/a8devminor/a155path",$header); |
foreach($current as $k => $v) |
$current[$k] = trim($v); |
$current['mode'] = octdec($current['mode']); |
$current['uid'] = octdec($current['uid']); |
$current['gid'] = octdec($current['gid']); |
$current['size'] = octdec($current['size']); |
$current['mtime'] = octdec($current['mtime']); |
$current['checksum'] = octdec($current['checksum']); |
$current['type'] = octdec($current['type']); |
|
if($this->storepath != 1) |
$current['filename'] = substr($current['filename'],strrpos($current['filename'],"/")+1); |
|
$checksum = 0; |
for($i = 0; $i < 148; $i++) |
$checksum += ord(substr($header,$i,1)); |
for($i = 148; $i < 156; $i++) |
$checksum += ord(" "); |
for($i = 156; $i < 512; $i++) |
$checksum += ord(substr($header,$i,1)); |
if($current['checksum'] != $checksum) |
return $this->error("Checksum error."); |
|
$size = ceil($current['size']/512); |
$current['data'] = substr($data,512*(++$offset),$current['size']); |
$offset += $size; |
$return[] = $current; |
} |
|
return $return; |
} |
|
function getdata() { |
return $this->tardata . pack("a512",""); |
} |
|
function filedownload($filename) { |
@header("Content-type: application/x-tar"); |
@header("Content-disposition: attachment; filename=$filename"); |
|
print($this->getdata()); |
} |
|
function nullpad($bytes) { |
$return = ""; |
for($i = 0; $i < $bytes; ++$i) |
$return .= "\0"; |
return $return; |
} |
} |
|
class gzfile extends archive { |
var $gzdata = ""; |
|
function addfile($data,$filename=null,$comment=null) { |
$flags = bindec("000".(!empty($comment)? "1" : "0").(!empty($filename)? "1" : "0")."000"); |
$this->gzdata .= pack("C1C1C1C1VC1C1",0x1f,0x8b,8,$flags,time(),2,0xFF); |
|
if(!empty($filename)) |
$this->gzdata .= "$filename\0"; |
|
if(!empty($comment)) |
$this->gzdata .= "$comment\0"; |
|
$this->gzdata .= gzdeflate($data); |
|
$this->gzdata .= pack("VV",crc32($data),strlen($data)); |
} |
|
function extract($data) { |
$id = unpack("H2id1/H2id2",substr($data,0,2)); |
if($id['id1'] != "1f" || $id['id2'] != "8b") |
return $this->error("Not valid gzip data."); |
|
$temp = unpack("Cflags",substr($data,2,1)); |
$temp = decbin($temp['flags']); |
if($temp & 0x8) |
$flags['name'] = 1; |
if($temp & 0x4) |
$flags['comment'] = 1; |
|
$offset = 10; |
|
$filename = ""; |
while(!empty($flags['name'])) { |
$char = substr($data,$offset,1); |
$offset++; |
if($char == "\0") |
break; |
$filename .= $char; |
} |
if($filename == "") |
$filename = "file"; |
|
$comment = ""; |
while(!empty($flags['comment'])) { |
$char = substr($data,$offset,1); |
$offset++; |
if($char == "\0") |
break; |
$comment .= $char; |
} |
|
$temp = unpack("Vcrc32/Visize",substr($data,strlen($data)-8,8)); |
$crc32 = $temp['crc32']; |
$isize = $temp['isize']; |
|
$data = gzinflate(substr($data,$offset,strlen($data)-8-$offset)); |
|
if($crc32 != crc32($data)) |
return $this->error("Checksum error"); |
|
return array('filename'=>$filename,'comment'=>$comment,'size'=>$isize,'data'=>$data); |
} |
|
function getdata() { |
return $this->gzdata; |
} |
|
function filedownload($filename) { |
@header("Content-type: application/x-gzip"); |
@header("Content-disposition: attachment; filename=$filename"); |
|
print($this->getdata()); |
} |
} |
|
class zipfile extends archive { |
var $cwd = "./"; |
var $comment = ""; |
var $level = 9; |
var $offset = 0; |
var $recursesd = 1; |
var $storepath = 1; |
var $replacetime = 0; |
var $central = array(); |
var $zipdata = array(); |
|
function zipfile($cwd="./",$flags=array()) { |
$this->cwd = $cwd; |
if(isset($flags['time'])) |
$this->replacetime = $flags['time']; |
if(isset($flags['recursesd'])) |
$this->recursesd = $flags['recursesd']; |
if(isset($flags['storepath'])) |
$this->storepath = $flags['storepath']; |
if(isset($flags['level'])) |
$this->level = $flags['level']; |
if(isset($flags['comment'])) |
$this->comment = $flags['comment']; |
|
$this->archive($flags); |
} |
|
function addfile($data,$filename,$flags=array()) { |
if($this->storepath != 1) |
$filename = strstr($filename,"/")? substr($filename,strrpos($filename,"/")+1) : $filename; |
else |
$filename = preg_replace("/^(\.{1,2}(\/|\\\))+/","",$filename); |
|
$mtime = !empty($this->replacetime)? getdate($this->replacetime) : (isset($flags['time'])? getdate($flags['time']) : getdate()); |
$mtime = preg_replace("/(..){1}(..){1}(..){1}(..){1}/","\\x\\4\\x\\3\\x\\2\\x\\1",dechex(($mtime['year']-1980<<25)|($mtime['mon']<<21)|($mtime['mday']<<16)|($mtime['hours']<<11)|($mtime['minutes']<<5)|($mtime['seconds']>>1))); |
eval('$mtime = "'.$mtime.'";'); |
|
$crc32 = crc32($data); |
$normlength = strlen($data); |
if(function_exists('gzcompress') ){ |
$data = gzcompress($data,$this->level); |
} |
$data = substr($data,2,strlen($data)-6); |
$complength = strlen($data); |
|
$this->zipdata[] = "\x50\x4b\x03\x04\x14\x00\x00\x00\x08\x00".$mtime.pack("VVVvv",$crc32,$complength,$normlength,strlen($filename),0x00).$filename.$data.pack("VVV",$crc32,$complength,$normlength); |
$this->central[] = "\x50\x4b\x01\x02\x00\x00\x14\x00\x00\x00\x08\x00".$mtime.pack("VVVvvvvvVV",$crc32,$complength,$normlength,strlen($filename),0x00,0x00,0x00,0x00,0x0000,$this->offset).$filename; |
|
$this->offset = strlen(implode("",$this->zipdata)); |
} |
|
function addfiles($filelist) { |
$pwd = getcwd(); |
@chdir($this->cwd); |
|
foreach($filelist as $current) { |
if(!@file_exists($current)) |
continue; |
|
$stat = stat($current); |
|
if($fp = @fopen($current,"rb")) { |
$data = fread($fp,$stat[7]); |
fclose($fp); |
} |
else |
$data = ""; |
|
$flags = array('time'=>$stat[9]); |
|
$this->addfile($data,$current,$flags); |
} |
|
@chdir($pwd); |
} |
|
function getdata() { |
$central = implode("",$this->central); |
$zipdata = implode("",$this->zipdata); |
return $zipdata.$central."\x50\x4b\x05\x06\x00\x00\x00\x00".pack("vvVVv",sizeof($this->central),sizeof($this->central),strlen($central),strlen($zipdata),strlen($this->comment)).$this->comment; |
} |
|
function filedownload($filename) { |
@header("Content-type: application/zip"); |
@header("Content-disposition: attachment; filename=$filename"); |
|
print($this->getdata()); |
} |
} |
|
class archive { |
var $overwrite = 0; |
var $defaultperms = 0644; |
|
function archive($flags=array()) { |
if(isset($flags['overwrite'])) |
$this->overwrite = $flags['overwrite']; |
if(isset($flags['defaultperms'])) |
$this->defaultperms = $flags['defaultperms']; |
} |
|
function adddirectories($dirlist) { |
$pwd = getcwd(); |
@chdir($this->cwd); |
|
$filelist = array(); |
|
foreach($dirlist as $current) { |
if(@is_dir($current)) { |
$temp = $this->parsedirectories($current); |
foreach($temp as $filename) |
$filelist[] = $filename; |
} |
else if(@file_exists($current)) |
$filelist[] = $current; |
} |
|
@chdir($pwd); |
$this->addfiles($filelist); |
} |
|
function parsedirectories($dirname) { |
$filelist = array(); |
$dir = @opendir($dirname); |
|
while($file = @readdir($dir)) { |
if($file == "." || $file == "..") |
continue; |
else if(@is_dir($dirname."/".$file)) { |
if($this->recursesd != 1) |
continue; |
$temp = $this->parsedirectories($dirname."/".$file); |
foreach($temp as $file2) |
$filelist[] = $file2; |
} |
else if(@file_exists($dirname."/".$file)) |
$filelist[] = $dirname."/".$file; |
} |
|
@closedir($dir); |
|
return $filelist; |
} |
|
function filewrite($filename,$perms=null) { |
if($this->overwrite != 1 && @file_exists($filename)) |
return $this->error("File $filename already exists."); |
|
if(@file_exists($filename)) |
@unlink($filename); |
|
$fp = @fopen($filename,"wb"); |
|
if(!fwrite($fp,$this->getdata())) |
return $this->error("Could not write data to $filename."); |
|
@fclose($fp); |
|
if(!isset($perms)) |
$perms = $this->defaultperms; |
|
@chmod($filename,$perms); |
} |
|
function extractfile($filename) { |
if($fp = @fopen($filename,"rb")) { |
return $this->extract(fread($fp,filesize($filename))); |
@fclose($fp); |
} |
else |
return $this->error("Could not open $filename."); |
} |
|
function error($error) { |
$this->errors[] = $error; |
return 0; |
} |
} ?> |