Blame | Last modification | View Log | Download
<?php/*************************Coppermine Photo Gallery************************Copyright (c) 2003-2005 Coppermine Dev Teamv1.1 originaly written by Gregory DEMARThis program is free software; you can redistribute it and/or modifyit under the terms of the GNU General Public License as published bythe 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; // Directoryelse if($file['mode'] & 0x8000)$file['type'] = 0; // Regularelse if($file['mode'] & 0xA000)$file['type'] = 1; // Linkelse$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);}elsereturn $this->error("Could not open $filename.");}function error($error) {$this->errors[] = $error;return 0;}} ?>